xref: /freebsd/sys/dev/isp/isp_freebsd.h (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
1 /* $FreeBSD$ */
2 /*
3  * Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions (CAM version)
4  *---------------------------------------
5  * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
6  * NASA/Ames Research Center
7  * All rights reserved.
8  *---------------------------------------
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 immediately at the beginning of the file, without modification,
15  *    this list of conditions, and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #ifndef	_ISP_FREEBSD_H
35 #define	_ISP_FREEBSD_H
36 
37 #define	ISP_PLATFORM_VERSION_MAJOR	5
38 #define	ISP_PLATFORM_VERSION_MINOR	2
39 
40 
41 #include <sys/param.h>
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/queue.h>
46 #include <sys/malloc.h>
47 #include <sys/proc.h>
48 
49 #include <machine/bus_memio.h>
50 #include <machine/bus_pio.h>
51 #include <machine/bus.h>
52 #include <machine/clock.h>
53 #include <machine/cpu.h>
54 
55 #include <cam/cam.h>
56 #include <cam/cam_debug.h>
57 #include <cam/cam_ccb.h>
58 #include <cam/cam_sim.h>
59 #include <cam/cam_xpt.h>
60 #include <cam/cam_xpt_sim.h>
61 #include <cam/cam_debug.h>
62 #include <cam/scsi/scsi_all.h>
63 #include <cam/scsi/scsi_message.h>
64 
65 #include "opt_ddb.h"
66 #include "opt_isp.h"
67 /*
68  * We are now always supporting fabric mode.
69  */
70 #define	ISP2100_FABRIC		1
71 #define	ISP2100_SCRLEN		0x400
72 
73 #ifndef	SCSI_CHECK
74 #define	SCSI_CHECK	SCSI_STATUS_CHECK_COND
75 #endif
76 #ifndef	SCSI_BUSY
77 #define	SCSI_BUSY	SCSI_STATUS_BUSY
78 #endif
79 #ifndef	SCSI_QFULL
80 #define	SCSI_QFULL	SCSI_STATUS_QUEUE_FULL
81 #endif
82 
83 #define	ISP_SCSI_XFER_T		struct ccb_scsiio
84 typedef void ispfwfunc __P((int, int, int, const u_int16_t **));
85 
86 #ifdef	ISP_TARGET_MODE
87 typedef struct tstate {
88 	struct tstate *next;
89 	struct cam_path *owner;
90 	struct ccb_hdr_slist atios;
91 	struct ccb_hdr_slist inots;
92 	lun_id_t lun;
93 	u_int32_t hold;
94 } tstate_t;
95 
96 /*
97  * This should work very well for 100% of parallel SCSI cases, 100%
98  * of non-SCCLUN FC cases, and hopefully some larger fraction of the
99  * SCCLUN FC cases. Basically, we index by the low 5 bits of lun and
100  * then linear search. This has to be reasonably zippy, but not crucially
101  * so.
102  */
103 #define	LUN_HASH_SIZE		32
104 #define	LUN_HASH_FUNC(lun)	((lun) & 0x1f)
105 
106 #endif
107 
108 struct isposinfo {
109 	struct ispsoftc *	next;
110 	u_int64_t		default_wwn;
111 	char			name[8];
112 	int			unit;
113 	struct cam_sim		*sim;
114 	struct cam_path		*path;
115 	struct cam_sim		*sim2;
116 	struct cam_path		*path2;
117 	struct intr_config_hook	ehook;
118 	volatile u_int16_t	:	14,
119 		islocked	:	1,
120 		intsok		:	1;
121 	u_int8_t		mboxwaiting;
122 	u_int8_t		simqfrozen;
123 	int			splsaved;
124 #ifdef	ISP_TARGET_MODE
125 #define	TM_WANTED		0x01
126 #define	TM_BUSY			0x02
127 #define	TM_TMODE_ENABLED	0x80
128 	u_int8_t		tmflags;
129 	u_int8_t		rstatus;
130 	u_int16_t		rollinfo;
131 	tstate_t		tsdflt;
132 	tstate_t		*lun_hash[LUN_HASH_SIZE];
133 #endif
134 };
135 #define	SIMQFRZ_RESOURCE	0x1
136 #define	SIMQFRZ_LOOPDOWN	0x2
137 #define	SIMQFRZ_TIMED		0x4
138 
139 #define	isp_sim		isp_osinfo.sim
140 #define	isp_path	isp_osinfo.path
141 #define	isp_sim2	isp_osinfo.sim2
142 #define	isp_path2	isp_osinfo.path2
143 #define	isp_unit	isp_osinfo.unit
144 #define	isp_name	isp_osinfo.name
145 
146 #define	MAXISPREQUEST		256
147 
148 #include <dev/isp/ispreg.h>
149 #include <dev/isp/ispvar.h>
150 #include <dev/isp/ispmbox.h>
151 
152 #define	DFLT_DBLEVEL		isp_debug
153 extern int isp_debug;
154 
155 static __inline void isp_lock(struct ispsoftc *);
156 static __inline void isp_unlock(struct ispsoftc *);
157 
158 static __inline void
159 isp_lock(struct ispsoftc *isp)
160 {
161 	int s = splcam();
162 	if (isp->isp_osinfo.islocked == 0) {
163 		isp->isp_osinfo.islocked = 1;
164 		isp->isp_osinfo.splsaved = s;
165 	} else {
166 		splx(s);
167 	}
168 }
169 
170 static __inline void
171 isp_unlock(struct ispsoftc *isp)
172 {
173 	if (isp->isp_osinfo.islocked) {
174 		isp->isp_osinfo.islocked = 0;
175 		splx(isp->isp_osinfo.splsaved);
176 	}
177 }
178 
179 #define	ISP_LOCK		isp_lock
180 #define	ISP_UNLOCK		isp_unlock
181 #define	SERVICING_INTERRUPT(isp)	1
182 /* not ready yet... */
183 #if	0
184 #define	SERVICING_INTERRUPT(isp)	(intr_nesting_level != 0)
185 #endif
186 
187 #define	MBOX_WAIT_COMPLETE(isp)		\
188 	if (isp->isp_osinfo.intsok == 0 || SERVICING_INTERRUPT(isp)) { \
189 		int j; \
190 		for (j = 0; j < 60 * 2000; j++) { \
191 			if (isp_intr(isp) == 0) { \
192 				SYS_DELAY(500); \
193 			} \
194 			if (isp->isp_mboxbsy == 0) \
195 				break; \
196 		} \
197 		if (isp->isp_mboxbsy != 0) \
198 			printf("%s: mailbox timeout\n", isp->isp_name); \
199 	} else { \
200 		isp->isp_osinfo.mboxwaiting = 1; \
201 		while (isp->isp_mboxbsy != 0) \
202 			(void) tsleep(&isp->isp_osinfo.mboxwaiting, PRIBIO, \
203 			    "isp_mailbox", 0);\
204 	}
205 
206 #define	MBOX_NOTIFY_COMPLETE(isp)	\
207 	if (isp->isp_osinfo.mboxwaiting) { \
208 		isp->isp_osinfo.mboxwaiting = 0; \
209 		wakeup(&isp->isp_osinfo.mboxwaiting); \
210 	} \
211 	isp->isp_mboxbsy = 0
212 
213 #define	XS_NULL(ccb)		ccb == NULL
214 #define	XS_ISP(ccb)		((struct ispsoftc *) (ccb)->ccb_h.spriv_ptr1)
215 
216 #define	XS_LUN(ccb)		(ccb)->ccb_h.target_lun
217 #define	XS_TGT(ccb)		(ccb)->ccb_h.target_id
218 #define	XS_CHANNEL(ccb)		cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
219 #define	XS_RESID(ccb)		(ccb)->resid
220 #define	XS_XFRLEN(ccb)		(ccb)->dxfer_len
221 #define	XS_CDBLEN(ccb)		(ccb)->cdb_len
222 #define	XS_CDBP(ccb)		(((ccb)->ccb_h.flags & CAM_CDB_POINTER)? \
223 	(ccb)->cdb_io.cdb_ptr : (ccb)->cdb_io.cdb_bytes)
224 #define	XS_STS(ccb)		(ccb)->scsi_status
225 #define	XS_TIME(ccb)		(ccb)->ccb_h.timeout
226 #define	XS_SNSP(ccb)		(&(ccb)->sense_data)
227 #define	XS_SNSLEN(ccb)		\
228 	imin((sizeof((ccb)->sense_data)), ccb->sense_len)
229 #define	XS_SNSKEY(ccb)		((ccb)->sense_data.flags & 0xf)
230 
231 /*
232  * A little tricky- HBA_NOERROR is "in progress" so
233  * that XS_CMD_DONE can transition this to CAM_REQ_CMP.
234  */
235 #define	HBA_NOERROR		CAM_REQ_INPROG
236 #define	HBA_BOTCH		CAM_UNREC_HBA_ERROR
237 #define	HBA_CMDTIMEOUT		CAM_CMD_TIMEOUT
238 #define	HBA_SELTIMEOUT		CAM_SEL_TIMEOUT
239 #define	HBA_TGTBSY		CAM_SCSI_STATUS_ERROR
240 #define	HBA_BUSRESET		CAM_SCSI_BUS_RESET
241 #define	HBA_ABORTED		CAM_REQ_ABORTED
242 #define	HBA_DATAOVR		CAM_DATA_RUN_ERR
243 #define	HBA_ARQFAIL		CAM_AUTOSENSE_FAIL
244 
245 #define	XS_SNS_IS_VALID(ccb) ((ccb)->ccb_h.status |= CAM_AUTOSNS_VALID)
246 #define	XS_IS_SNS_VALID(ccb) (((ccb)->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
247 
248 #define	ISP_SPRIV_ERRSET	0x1
249 #define	ISP_SPRIV_INWDOG	0x2
250 #define	ISP_SPRIV_GRACE		0x4
251 #define	ISP_SPRIV_DONE		0x8
252 
253 #define	XS_CMD_S_WDOG(sccb)	(sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_INWDOG
254 #define	XS_CMD_C_WDOG(sccb)	(sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_INWDOG
255 #define	XS_CMD_WDOG_P(sccb)	((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_INWDOG)
256 
257 #define	XS_CMD_S_GRACE(sccb)	(sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_GRACE
258 #define	XS_CMD_C_GRACE(sccb)	(sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_GRACE
259 #define	XS_CMD_GRACE_P(sccb)	((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_GRACE)
260 
261 #define	XS_CMD_S_DONE(sccb)	(sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_DONE
262 #define	XS_CMD_C_DONE(sccb)	(sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_DONE
263 #define	XS_CMD_DONE_P(sccb)	((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_DONE)
264 
265 #define	XS_CMD_S_CLEAR(sccb)	(sccb)->ccb_h.spriv_field0 = 0
266 
267 
268 #define	XS_SETERR(ccb, v)	(ccb)->ccb_h.status &= ~CAM_STATUS_MASK, \
269 				(ccb)->ccb_h.status |= v, \
270 				(ccb)->ccb_h.spriv_field0 |= ISP_SPRIV_ERRSET
271 
272 #define	XS_INITERR(ccb)		XS_SETERR(ccb, CAM_REQ_INPROG), \
273 				XS_CMD_S_CLEAR(ccb)
274 
275 #define	XS_ERR(ccb)		((ccb)->ccb_h.status & CAM_STATUS_MASK)
276 
277 #define	XS_NOERR(ccb)		\
278 	(((ccb)->ccb_h.spriv_field0 & ISP_SPRIV_ERRSET) == 0 || \
279 	 ((ccb)->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)
280 
281 #define	XS_CMD_DONE		isp_done
282 
283 extern void isp_done(struct ccb_scsiio *);
284 
285 /*
286  * Can we tag?
287  */
288 #define	XS_CANTAG(ccb)		(((ccb)->ccb_h.flags & CAM_TAG_ACTION_VALID) \
289 				  && (ccb)->tag_action != CAM_TAG_ACTION_NONE)
290 /*
291  * And our favorite tag is....
292  */
293 #define	XS_KINDOF_TAG(ccb)	\
294 	((ccb->tag_action == MSG_SIMPLE_Q_TAG)? REQFLAG_STAG : \
295 	  ((ccb->tag_action == MSG_HEAD_OF_Q_TAG)? REQFLAG_HTAG : REQFLAG_OTAG))
296 
297 #define	CMD_COMPLETE		0
298 #define	CMD_EAGAIN		1
299 #define	CMD_QUEUED		2
300 #define	CMD_RQLATER		3
301 
302 extern void isp_attach(struct ispsoftc *);
303 extern void isp_uninit(struct ispsoftc *);
304 
305 #define	MEMZERO			bzero
306 #define	MEMCPY(dst, src, amt)	bcopy((src), (dst), (amt))
307 #ifdef	__alpha__
308 #define	MemoryBarrier	alpha_mb
309 #else
310 #define	MemoryBarrier()
311 #endif
312 
313 
314 #define	DMA_MSW(x)	(((x) >> 16) & 0xffff)
315 #define	DMA_LSW(x)	(((x) & 0xffff))
316 
317 #define	ISP_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src)	\
318 	bcopy(src, dest, sizeof (isp_pdb_t))
319 #define	ISP_SWIZZLE_ICB(a, b)
320 #define	ISP_SWIZZLE_REQUEST(a, b)
321 #define	ISP_UNSWIZZLE_RESPONSE(a, b)
322 #define	ISP_SWIZZLE_SNS_REQ(a, b)
323 #define	ISP_UNSWIZZLE_SNS_RSP(a, b, c)
324 
325 #define	IDPRINTF(lev, x)	if (isp->isp_dblev >= (u_int8_t) lev) printf x
326 #define	PRINTF			printf
327 #define	CFGPRINTF		if (bootverbose || DFLT_DBLEVEL > 1) printf
328 #define	STRNCAT			strncat
329 static __inline char *strncat(char *, const char *, size_t);
330 static __inline char *
331 strncat(char *d, const char *s, size_t c)
332 {
333         char *t = d;
334 
335         if (c) {
336                 while (*d)
337                         d++;
338                 while ((*d++ = *s++)) {
339                         if (--c == 0) {
340                                 *d = '\0';
341                                 break;
342                         }
343                 }
344         }
345         return (t);
346 }
347 
348 #define	SYS_DELAY(x)	DELAY(x)
349 
350 #define	FC_FW_READY_DELAY	(5 * 1000000)
351 #define	DEFAULT_LOOPID(x)	109
352 #define	DEFAULT_WWN(x)		(x)->isp_osinfo.default_wwn
353 
354 #define	INLINE	__inline
355 #include <dev/isp/isp_inline.h>
356 #endif	/* _ISP_FREEBSD_H */
357