1 /** $MirOS: src/sys/dev/ic/isp_openbsd.h,v 1.2 2005/03/06 21:27:40 tg Exp $ */
2 /* $OpenBSD: isp_openbsd.h,v 1.24 2003/03/30 16:57:42 krw Exp $ */
3 /*
4 * OpenBSD Specific definitions for the Qlogic ISP Host Adapter
5 */
6 /*
7 * Copyright (C) 1999, 2000, 2001 by Matthew Jacob
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #ifndef _ISP_OPENBSD_H
30 #define _ISP_OPENBSD_H
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/errno.h>
37 #include <sys/ioctl.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/proc.h>
42 #include <sys/user.h>
43 #include <sys/queue.h>
44
45 #if !(defined(__sparc__) && !defined(__sparcv9__))
46 #include <machine/bus.h>
47 #endif
48
49 #include <scsi/scsi_all.h>
50 #include <scsi/scsiconf.h>
51
52 #include <scsi/scsi_message.h>
53 #include <scsi/scsi_debug.h>
54
55 #include <uvm/uvm_extern.h>
56
57 /*
58 * Efficiency- get rid of SBus code && tests unless we need them.
59 */
60 #if defined(__sparcv9__ ) || defined(__sparc__)
61 #define ISP_SBUS_SUPPORTED 1
62 #else
63 #define ISP_SBUS_SUPPORTED 0
64 #endif
65
66 #define ISP_PLATFORM_VERSION_MAJOR 2
67 #define ISP_PLATFORM_VERSION_MINOR 1
68
69 struct isposinfo {
70 struct device _dev;
71 struct scsi_link _link[2];
72 struct scsi_adapter _adapter;
73 int hiwater;
74 int splsaved;
75 int mboxwaiting;
76 u_int32_t islocked;
77 u_int32_t onintstack;
78 #if !(defined(__sparc__) && !defined(__sparcv9__))
79 bus_dma_tag_t dmatag;
80 bus_dmamap_t rqdmap;
81 bus_dmamap_t rsdmap;
82 bus_dmamap_t scdmap; /* FC only */
83 #define isp_dmatag isp_osinfo.dmatag
84 #define isp_rqdmap isp_osinfo.rqdmap
85 #define isp_rsdmap isp_osinfo.rsdmap
86 #define isp_scdmap isp_osinfo.scdmap
87 #endif
88 unsigned int : 28,
89
90 rtpend : 1,
91 no_mbox_ints : 1,
92 blocked : 2;
93 union {
94 u_int64_t _wwn;
95 u_int16_t _discovered[2];
96 } un;
97 #define discovered un._discovered
98 struct scsi_xfer *wqf, *wqt;
99 struct timeout rqt;
100 };
101 #define MUST_POLL(isp) \
102 (isp->isp_osinfo.onintstack || isp->isp_osinfo.no_mbox_ints)
103
104 /*
105 * Locking macros...
106 */
107 #define ISP_LOCK isp_lock
108 #define ISP_UNLOCK isp_unlock
109
110 /*
111 * Required Macros/Defines
112 */
113
114 #define INLINE inline
115
116 #define ISP2100_SCRLEN 0x800
117
118 #define MEMZERO(d, l) memset((d), 0, (l))
119 #define MEMCPY memmove
120 #define SNPRINTF snprintf
121 #define USEC_DELAY(x) delay(x)
122 #define USEC_SLEEP(isp, x) \
123 if (!MUST_POLL(isp)) \
124 ISP_UNLOCK(isp); \
125 delay(x); \
126 if (!MUST_POLL(isp)) \
127 ISP_LOCK(isp)
128
129 #define NANOTIME_T struct timeval
130 #define GET_NANOTIME microtime
131 #define GET_NANOSEC(x) (((x)->tv_sec * 1000000 + (x)->tv_usec) * 1000)
132 #define NANOTIME_SUB isp_microtime_sub
133
134 #define MAXISPREQUEST(isp) 256
135
136 #if !(defined(__sparc__) && !defined(__sparcv9__))
137 #define MEMORYBARRIER(isp, type, offset, size) \
138 switch (type) { \
139 case SYNC_REQUEST: \
140 { \
141 off_t off = (off_t) offset * QENTRY_LEN; \
142 bus_dmamap_sync(isp->isp_dmatag, isp->isp_rqdmap, \
143 off, size, BUS_DMASYNC_PREWRITE); \
144 break; \
145 } \
146 case SYNC_RESULT: \
147 { \
148 off_t off = (off_t) offset * QENTRY_LEN; \
149 bus_dmamap_sync(isp->isp_dmatag, isp->isp_rsdmap, \
150 off, size, BUS_DMASYNC_POSTREAD); \
151 break; \
152 } \
153 case SYNC_SFORDEV: \
154 { \
155 off_t off = (off_t) offset; \
156 bus_dmamap_sync(isp->isp_dmatag, isp->isp_scdmap, \
157 off, size, BUS_DMASYNC_PREWRITE); \
158 break; \
159 } \
160 case SYNC_SFORCPU: \
161 { \
162 off_t off = (off_t) offset; \
163 bus_dmamap_sync(isp->isp_dmatag, isp->isp_scdmap, \
164 off, size, BUS_DMASYNC_POSTREAD); \
165 break; \
166 } \
167 case SYNC_REG: \
168 default: \
169 break; \
170 }
171 #else
172 #define MEMORYBARRIER(isp, type, offset, size)
173 #endif
174
175 #define MBOX_ACQUIRE(isp)
176 #define MBOX_WAIT_COMPLETE isp_wait_complete
177
178 #define MBOX_NOTIFY_COMPLETE(isp) \
179 if (isp->isp_osinfo.mboxwaiting) { \
180 isp->isp_osinfo.mboxwaiting = 0; \
181 wakeup(&isp->isp_osinfo.mboxwaiting); \
182 } \
183 isp->isp_mboxbsy = 0
184
185 #define MBOX_RELEASE(isp)
186
187 #define FC_SCRATCH_ACQUIRE(isp)
188 #define FC_SCRATCH_RELEASE(isp)
189
190 #ifndef SCSI_GOOD
191 #define SCSI_GOOD 0x0
192 #endif
193 #ifndef SCSI_CHECK
194 #define SCSI_CHECK 0x2
195 #endif
196 #ifndef SCSI_BUSY
197 #define SCSI_BUSY 0x8
198 #endif
199 #ifndef SCSI_QFULL
200 #define SCSI_QFULL 0x28
201 #endif
202
203 #define XS_T struct scsi_xfer
204 #define XS_CHANNEL(xs) (((xs)->sc_link->flags & SDEV_2NDBUS)? 1 : 0)
205 #define XS_ISP(xs) (xs)->sc_link->adapter_softc
206 #define XS_LUN(xs) ((int) (xs)->sc_link->lun)
207 #define XS_TGT(xs) ((int) (xs)->sc_link->target)
208 #define XS_CDBP(xs) ((caddr_t) (xs)->cmd)
209 #define XS_CDBLEN(xs) (xs)->cmdlen
210 #define XS_XFRLEN(xs) (xs)->datalen
211 #define XS_TIME(xs) (xs)->timeout
212 #define XS_RESID(xs) (xs)->resid
213 #define XS_STSP(xs) (&(xs)->status)
214 #define XS_SNSP(xs) (&(xs)->sense)
215 #define XS_SNSLEN(xs) (sizeof (xs)->sense)
216 #define XS_SNSKEY(xs) ((xs)->sense.flags)
217 #define XS_TAG_P(xs) (((xs)->flags & SCSI_POLL) != 0)
218 #define XS_TAG_TYPE(xs) REQFLAG_STAG
219
220 #define XS_SETERR(xs, v) (xs)->error = v
221
222 # define HBA_NOERROR XS_NOERROR
223 # define HBA_BOTCH XS_DRIVER_STUFFUP
224 # define HBA_CMDTIMEOUT XS_TIMEOUT
225 # define HBA_SELTIMEOUT XS_SELTIMEOUT
226 # define HBA_TGTBSY XS_BUSY
227 # define HBA_BUSRESET XS_RESET
228 # define HBA_ABORTED XS_DRIVER_STUFFUP
229 # define HBA_DATAOVR XS_DRIVER_STUFFUP
230 # define HBA_ARQFAIL XS_DRIVER_STUFFUP
231
232 #define XS_ERR(xs) (xs)->error
233
234 #define XS_NOERR(xs) (xs)->error == XS_NOERROR
235
236 #define XS_INITERR(xs) (xs)->error = 0, XS_CMD_S_CLEAR(xs)
237
238 #define XS_SAVE_SENSE(xs, sp) \
239 if (xs->error == XS_NOERROR) { \
240 xs->error = XS_SENSE; \
241 } \
242 memmove(&(xs)->sense, sp->req_sense_data, \
243 imin(XS_SNSLEN(xs), sp->req_sense_len))
244
245 #define XS_SET_STATE_STAT(a, b, c)
246
247 #define DEFAULT_IID(x) 7
248 #define DEFAULT_LOOPID(x) 107
249 #define DEFAULT_NODEWWN(isp) (isp)->isp_osinfo.un._wwn
250 #define DEFAULT_PORTWWN(isp) (isp)->isp_osinfo.un._wwn
251 #define ISP_NODEWWN(isp) FCPARAM(isp)->isp_nodewwn
252 #define ISP_PORTWWN(isp) FCPARAM(isp)->isp_portwwn
253
254 #if BYTE_ORDER == BIG_ENDIAN
255 #ifdef ISP_SBUS_SUPPORTED
256 #define ISP_IOXPUT_8(isp, s, d) *(d) = s
257 #define ISP_IOXPUT_16(isp, s, d) \
258 *(d) = (isp->isp_bustype == ISP_BT_SBUS)? s : swap16(s)
259 #define ISP_IOXPUT_32(isp, s, d) \
260 *(d) = (isp->isp_bustype == ISP_BT_SBUS)? s : swap32(s)
261
262 #define ISP_IOXGET_8(isp, s, d) d = (*((u_int8_t *)s))
263 #define ISP_IOXGET_16(isp, s, d) \
264 d = (isp->isp_bustype == ISP_BT_SBUS)? \
265 *((u_int16_t *)s) : swap16(*((u_int16_t *)s))
266 #define ISP_IOXGET_32(isp, s, d) \
267 d = (isp->isp_bustype == ISP_BT_SBUS)? \
268 *((u_int32_t *)s) : swap32(*((u_int32_t *)s))
269 #else
270 #define ISP_IOXPUT_8(isp, s, d) *(d) = s
271 #define ISP_IOXPUT_16(isp, s, d) *(d) = swap16(s)
272 #define ISP_IOXPUT_32(isp, s, d) *(d) = swap32(s)
273 #define ISP_IOXGET_8(isp, s, d) d = (*((u_int8_t *)s))
274 #define ISP_IOXGET_16(isp, s, d) d = swap16(*((u_int16_t *)s))
275 #define ISP_IOXGET_32(isp, s, d) d = swap32(*((u_int32_t *)s))
276 #endif
277 #define ISP_SWIZZLE_NVRAM_WORD(isp, rp) *rp = swap16(*rp)
278 #else
279 #define ISP_IOXPUT_8(isp, s, d) *(d) = s
280 #define ISP_IOXPUT_16(isp, s, d) *(d) = s
281 #define ISP_IOXPUT_32(isp, s, d) *(d) = s
282 #define ISP_IOXGET_8(isp, s, d) d = *(s)
283 #define ISP_IOXGET_16(isp, s, d) d = *(s)
284 #define ISP_IOXGET_32(isp, s, d) d = *(s)
285 #define ISP_SWIZZLE_NVRAM_WORD(isp, rp)
286 #endif
287
288 /*
289 * Includes of common header files
290 */
291
292 #include <dev/ic/ispreg.h>
293 #include <dev/ic/ispvar.h>
294 #include <dev/ic/ispmbox.h>
295
296 /*
297 * isp_osinfo definitions, extensions and shorthand.
298 */
299 #define isp_name isp_osinfo._dev.dv_xname
300 #define isp_unit isp_osinfo._dev.dv_unit
301
302 /*
303 * Driver prototypes..
304 */
305 void isp_attach(struct ispsoftc *);
306 void isp_uninit(struct ispsoftc *);
307
308 static INLINE void isp_lock(struct ispsoftc *);
309 static INLINE void isp_unlock(struct ispsoftc *);
310 static INLINE u_int64_t
311 isp_microtime_sub(struct timeval *, struct timeval *);
312 static void isp_wait_complete(struct ispsoftc *);
313
314 /*
315 * Driver wide data...
316 */
317
318 /*
319 * Platform private flags
320 */
321
322 #define XS_PSTS_INWDOG 0x10000
323 #define XS_PSTS_GRACE 0x20000
324 #define XS_PSTS_TIMED 0x40000
325 #define XS_PSTS_ALL SCSI_PRIVATE
326
327 #define XS_CMD_S_WDOG(xs) (xs)->flags |= XS_PSTS_INWDOG
328 #define XS_CMD_C_WDOG(xs) (xs)->flags &= ~XS_PSTS_INWDOG
329 #define XS_CMD_WDOG_P(xs) (((xs)->flags & XS_PSTS_INWDOG) != 0)
330
331 #define XS_CMD_S_TIMER(xs) (xs)->flags |= XS_PSTS_TIMED
332 #define XS_CMD_C_TIMER(xs) (xs)->flags &= ~XS_PSTS_TIMED
333 #define XS_CMD_TIMER_P(xs) (((xs)->flags & XS_PSTS_TIMED) != 0)
334
335 #define XS_CMD_S_GRACE(xs) (xs)->flags |= XS_PSTS_GRACE
336 #define XS_CMD_C_GRACE(xs) (xs)->flags &= ~XS_PSTS_GRACE
337 #define XS_CMD_GRACE_P(xs) (((xs)->flags & XS_PSTS_GRACE) != 0)
338
339 #define XS_CMD_S_DONE(xs) (xs)->flags |= ITSDONE
340 #define XS_CMD_C_DONE(xs) (xs)->flags &= ~ITSDONE
341 #define XS_CMD_DONE_P(xs) (((xs)->flags & ITSDONE) != 0)
342
343 #define XS_CMD_S_CLEAR(xs) (xs)->flags &= ~XS_PSTS_ALL
344
345 /*
346 * Platform specific 'INLINE' or support functions
347 */
348 static INLINE void
isp_lock(struct ispsoftc * isp)349 isp_lock(struct ispsoftc *isp)
350 {
351 int s = splbio();
352 if (isp->isp_osinfo.islocked++ == 0) {
353 isp->isp_osinfo.splsaved = s;
354 } else {
355 splx(s);
356 }
357 }
358
359 static INLINE void
isp_unlock(struct ispsoftc * isp)360 isp_unlock(struct ispsoftc *isp)
361 {
362 if (isp->isp_osinfo.islocked-- <= 1) {
363 isp->isp_osinfo.islocked = 0;
364 splx(isp->isp_osinfo.splsaved);
365 }
366 }
367
368 static INLINE u_int64_t
isp_microtime_sub(struct timeval * b,struct timeval * a)369 isp_microtime_sub(struct timeval *b, struct timeval *a)
370 {
371 struct timeval x;
372 u_int64_t elapsed;
373 timersub(b, a, &x);
374 elapsed = GET_NANOSEC(&x);
375 if (elapsed == 0)
376 elapsed++;
377 return (elapsed);
378 }
379
380 static INLINE void
isp_wait_complete(struct ispsoftc * isp)381 isp_wait_complete(struct ispsoftc *isp)
382 {
383 int delaytime;
384 if (isp->isp_mbxwrk0)
385 delaytime = 60;
386 else
387 delaytime = 5;
388 if (MUST_POLL(isp)) {
389 int usecs = 0;
390 delaytime *= 1000000; /* convert to usecs */
391 while (usecs < delaytime) {
392 u_int16_t isr, sema, mbox;
393 if (isp->isp_mboxbsy == 0) {
394 break;
395 }
396 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
397 isp_intr(isp, isr, sema, mbox);
398 if (isp->isp_mboxbsy == 0) {
399 break;
400 }
401 }
402 USEC_DELAY(500);
403 usecs += 500;
404 }
405 if (isp->isp_mboxbsy != 0) {
406 isp_prt(isp, ISP_LOGWARN,
407 "Polled Mailbox Command (0x%x) Timeout",
408 isp->isp_lastmbxcmd);
409 }
410 } else {
411 int rv = 0;
412 isp->isp_osinfo.mboxwaiting = 1;
413 while (isp->isp_osinfo.mboxwaiting && rv == 0) {
414 rv = tsleep(&isp->isp_osinfo.mboxwaiting,
415 PRIBIO, "isp_mboxcmd", delaytime * hz);
416 }
417 if (rv == EWOULDBLOCK) {
418 isp->isp_mboxbsy = 0;
419 isp->isp_osinfo.mboxwaiting = 0;
420 isp_prt(isp, ISP_LOGWARN,
421 "Interrupting Mailbox Command (0x%x) Timeout",
422 isp->isp_lastmbxcmd);
423 }
424 }
425 }
426
427 /*
428 * Common INLINE functions
429 */
430 #include <dev/ic/isp_inline.h>
431
432 #endif /* _ISP_NETBSD_H */
433