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