isp_freebsd.h revision 62496
1258945Sroberto/* $FreeBSD: head/sys/dev/isp/isp_freebsd.h 62496 2000-07-04 01:04:35Z mjacob $ */
2280849Scy/*
3258945Sroberto * Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions (CAM version)
4258945Sroberto *---------------------------------------
5258945Sroberto * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
6258945Sroberto * NASA/Ames Research Center
7258945Sroberto * All rights reserved.
8258945Sroberto *---------------------------------------
9258945Sroberto *
10258945Sroberto * Redistribution and use in source and binary forms, with or without
11258945Sroberto * modification, are permitted provided that the following conditions
12258945Sroberto * are met:
13258945Sroberto * 1. Redistributions of source code must retain the above copyright
14258945Sroberto *    notice immediately at the beginning of the file, without modification,
15258945Sroberto *    this list of conditions, and the following disclaimer.
16258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright
17258945Sroberto *    notice, this list of conditions and the following disclaimer in the
18258945Sroberto *    documentation and/or other materials provided with the distribution.
19258945Sroberto * 3. The name of the author may not be used to endorse or promote products
20258945Sroberto *    derived from this software without specific prior written permission.
21258945Sroberto *
22258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24258945Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25258945Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26258945Sroberto * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27258945Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28258945Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29258945Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30258945Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31258945Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32258945Sroberto * SUCH DAMAGE.
33258945Sroberto */
34258945Sroberto#ifndef	_ISP_FREEBSD_H
35258945Sroberto#define	_ISP_FREEBSD_H
36258945Sroberto
37258945Sroberto#define	ISP_PLATFORM_VERSION_MAJOR	5
38258945Sroberto#define	ISP_PLATFORM_VERSION_MINOR	2
39258945Sroberto
40258945Sroberto
41258945Sroberto#include <sys/param.h>
42258945Sroberto#include <sys/param.h>
43258945Sroberto#include <sys/systm.h>
44258945Sroberto#include <sys/kernel.h>
45258945Sroberto#include <sys/queue.h>
46258945Sroberto#include <sys/malloc.h>
47258945Sroberto#include <sys/proc.h>
48258945Sroberto
49258945Sroberto#include <machine/bus_memio.h>
50258945Sroberto#include <machine/bus_pio.h>
51258945Sroberto#include <machine/bus.h>
52258945Sroberto#include <machine/clock.h>
53258945Sroberto#include <machine/cpu.h>
54258945Sroberto
55258945Sroberto#include <cam/cam.h>
56258945Sroberto#include <cam/cam_debug.h>
57258945Sroberto#include <cam/cam_ccb.h>
58258945Sroberto#include <cam/cam_sim.h>
59258945Sroberto#include <cam/cam_xpt.h>
60258945Sroberto#include <cam/cam_xpt_sim.h>
61258945Sroberto#include <cam/cam_debug.h>
62258945Sroberto#include <cam/scsi/scsi_all.h>
63258945Sroberto#include <cam/scsi/scsi_message.h>
64258945Sroberto
65258945Sroberto#include "opt_ddb.h"
66258945Sroberto#include "opt_isp.h"
67258945Sroberto/*
68258945Sroberto * We are now always supporting fabric mode.
69258945Sroberto */
70258945Sroberto#define	ISP2100_FABRIC		1
71258945Sroberto#define	ISP2100_SCRLEN		0x400
72258945Sroberto
73258945Sroberto#ifndef	SCSI_CHECK
74280849Scy#define	SCSI_CHECK	SCSI_STATUS_CHECK_COND
75258945Sroberto#endif
76258945Sroberto#ifndef	SCSI_BUSY
77258945Sroberto#define	SCSI_BUSY	SCSI_STATUS_BUSY
78258945Sroberto#endif
79258945Sroberto#ifndef	SCSI_QFULL
80258945Sroberto#define	SCSI_QFULL	SCSI_STATUS_QUEUE_FULL
81258945Sroberto#endif
82258945Sroberto
83258945Sroberto#define	ISP_SCSI_XFER_T		struct ccb_scsiio
84258945Srobertotypedef void ispfwfunc __P((int, int, int, const u_int16_t **));
85258945Sroberto
86258945Sroberto#ifdef	ISP_TARGET_MODE
87258945Srobertotypedef struct tstate {
88258945Sroberto	struct tstate *next;
89258945Sroberto	struct cam_path *owner;
90258945Sroberto	struct ccb_hdr_slist atios;
91258945Sroberto	struct ccb_hdr_slist inots;
92258945Sroberto	lun_id_t lun;
93258945Sroberto	u_int32_t hold;
94258945Sroberto} tstate_t;
95293894Sglebius
96258945Sroberto/*
97258945Sroberto * This should work very well for 100% of parallel SCSI cases, 100%
98258945Sroberto * of non-SCCLUN FC cases, and hopefully some larger fraction of the
99258945Sroberto * SCCLUN FC cases. Basically, we index by the low 5 bits of lun and
100258945Sroberto * then linear search. This has to be reasonably zippy, but not crucially
101258945Sroberto * so.
102258945Sroberto */
103258945Sroberto#define	LUN_HASH_SIZE		32
104258945Sroberto#define	LUN_HASH_FUNC(lun)	((lun) & 0x1f)
105258945Sroberto
106258945Sroberto#endif
107258945Sroberto
108258945Srobertostruct isposinfo {
109258945Sroberto	struct ispsoftc *	next;
110258945Sroberto	u_int64_t		default_wwn;
111258945Sroberto	char			name[8];
112258945Sroberto	int			unit;
113258945Sroberto	struct cam_sim		*sim;
114258945Sroberto	struct cam_path		*path;
115258945Sroberto	struct cam_sim		*sim2;
116258945Sroberto	struct cam_path		*path2;
117258945Sroberto	struct intr_config_hook	ehook;
118258945Sroberto	volatile u_int16_t	:	14,
119258945Sroberto		islocked	:	1,
120258945Sroberto		intsok		:	1;
121258945Sroberto	u_int8_t		mboxwaiting;
122258945Sroberto	u_int8_t		simqfrozen;
123258945Sroberto	int			splsaved;
124258945Sroberto#ifdef	ISP_TARGET_MODE
125258945Sroberto#define	TM_WANTED		0x01
126258945Sroberto#define	TM_BUSY			0x02
127258945Sroberto#define	TM_TMODE_ENABLED	0x80
128258945Sroberto	u_int8_t		tmflags;
129258945Sroberto	u_int8_t		rstatus;
130258945Sroberto	u_int16_t		rollinfo;
131258945Sroberto	tstate_t		tsdflt;
132258945Sroberto	tstate_t		*lun_hash[LUN_HASH_SIZE];
133258945Sroberto#endif
134258945Sroberto};
135258945Sroberto#define	SIMQFRZ_RESOURCE	0x1
136258945Sroberto#define	SIMQFRZ_LOOPDOWN	0x2
137258945Sroberto#define	SIMQFRZ_TIMED		0x4
138258945Sroberto
139258945Sroberto#define	isp_sim		isp_osinfo.sim
140258945Sroberto#define	isp_path	isp_osinfo.path
141258945Sroberto#define	isp_sim2	isp_osinfo.sim2
142258945Sroberto#define	isp_path2	isp_osinfo.path2
143258945Sroberto#define	isp_unit	isp_osinfo.unit
144258945Sroberto#define	isp_name	isp_osinfo.name
145258945Sroberto
146258945Sroberto#define	MAXISPREQUEST		256
147258945Sroberto
148258945Sroberto#include <dev/isp/ispreg.h>
149258945Sroberto#include <dev/isp/ispvar.h>
150258945Sroberto#include <dev/isp/ispmbox.h>
151258945Sroberto
152258945Sroberto#define	DFLT_DBLEVEL		isp_debug
153258945Srobertoextern int isp_debug;
154258945Sroberto
155258945Srobertostatic __inline void isp_lock(struct ispsoftc *);
156258945Srobertostatic __inline void isp_unlock(struct ispsoftc *);
157258945Sroberto
158258945Srobertostatic __inline void
159258945Srobertoisp_lock(struct ispsoftc *isp)
160258945Sroberto{
161258945Sroberto	int s = splcam();
162258945Sroberto	if (isp->isp_osinfo.islocked == 0) {
163258945Sroberto		isp->isp_osinfo.islocked = 1;
164258945Sroberto		isp->isp_osinfo.splsaved = s;
165258945Sroberto	} else {
166258945Sroberto		splx(s);
167258945Sroberto	}
168258945Sroberto}
169293894Sglebius
170258945Srobertostatic __inline void
171258945Srobertoisp_unlock(struct ispsoftc *isp)
172258945Sroberto{
173258945Sroberto	if (isp->isp_osinfo.islocked) {
174258945Sroberto		isp->isp_osinfo.islocked = 0;
175258945Sroberto		splx(isp->isp_osinfo.splsaved);
176258945Sroberto	}
177258945Sroberto}
178258945Sroberto
179258945Sroberto#define	ISP_LOCK		isp_lock
180258945Sroberto#define	ISP_UNLOCK		isp_unlock
181258945Sroberto#define	SERVICING_INTERRUPT(isp)	(intr_nesting_level != 0)
182258945Sroberto
183258945Sroberto#define	MBOX_WAIT_COMPLETE(isp)		\
184258945Sroberto	if (isp->isp_osinfo.intsok == 0 || SERVICING_INTERRUPT(isp)) { \
185258945Sroberto		int j; \
186258945Sroberto		for (j = 0; j < 60 * 2000; j++) { \
187258945Sroberto			if (isp_intr(isp) == 0) { \
188258945Sroberto				SYS_DELAY(500); \
189258945Sroberto			} \
190258945Sroberto			if (isp->isp_mboxbsy == 0) \
191258945Sroberto				break; \
192258945Sroberto		} \
193258945Sroberto		if (isp->isp_mboxbsy != 0) \
194258945Sroberto			printf("%s: mailbox timeout\n", isp->isp_name); \
195258945Sroberto	} else { \
196		isp->isp_osinfo.mboxwaiting = 1; \
197		while (isp->isp_mboxbsy != 0) \
198			(void) tsleep(&isp->isp_osinfo.mboxwaiting, PRIBIO, \
199			    "isp_mailbox", 0);\
200	}
201
202#define	MBOX_NOTIFY_COMPLETE(isp)	\
203	if (isp->isp_osinfo.mboxwaiting) { \
204		isp->isp_osinfo.mboxwaiting = 0; \
205		wakeup(&isp->isp_osinfo.mboxwaiting); \
206	} \
207	isp->isp_mboxbsy = 0
208
209#define	XS_NULL(ccb)		ccb == NULL
210#define	XS_ISP(ccb)		((struct ispsoftc *) (ccb)->ccb_h.spriv_ptr1)
211
212#define	XS_LUN(ccb)		(ccb)->ccb_h.target_lun
213#define	XS_TGT(ccb)		(ccb)->ccb_h.target_id
214#define	XS_CHANNEL(ccb)		cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
215#define	XS_RESID(ccb)		(ccb)->resid
216#define	XS_XFRLEN(ccb)		(ccb)->dxfer_len
217#define	XS_CDBLEN(ccb)		(ccb)->cdb_len
218#define	XS_CDBP(ccb)		(((ccb)->ccb_h.flags & CAM_CDB_POINTER)? \
219	(ccb)->cdb_io.cdb_ptr : (ccb)->cdb_io.cdb_bytes)
220#define	XS_STS(ccb)		(ccb)->scsi_status
221#define	XS_TIME(ccb)		(ccb)->ccb_h.timeout
222#define	XS_SNSP(ccb)		(&(ccb)->sense_data)
223#define	XS_SNSLEN(ccb)		\
224	imin((sizeof((ccb)->sense_data)), ccb->sense_len)
225#define	XS_SNSKEY(ccb)		((ccb)->sense_data.flags & 0xf)
226
227/*
228 * A little tricky- HBA_NOERROR is "in progress" so
229 * that XS_CMD_DONE can transition this to CAM_REQ_CMP.
230 */
231#define	HBA_NOERROR		CAM_REQ_INPROG
232#define	HBA_BOTCH		CAM_UNREC_HBA_ERROR
233#define	HBA_CMDTIMEOUT		CAM_CMD_TIMEOUT
234#define	HBA_SELTIMEOUT		CAM_SEL_TIMEOUT
235#define	HBA_TGTBSY		CAM_SCSI_STATUS_ERROR
236#define	HBA_BUSRESET		CAM_SCSI_BUS_RESET
237#define	HBA_ABORTED		CAM_REQ_ABORTED
238#define	HBA_DATAOVR		CAM_DATA_RUN_ERR
239#define	HBA_ARQFAIL		CAM_AUTOSENSE_FAIL
240
241#define	XS_SNS_IS_VALID(ccb) ((ccb)->ccb_h.status |= CAM_AUTOSNS_VALID)
242#define	XS_IS_SNS_VALID(ccb) (((ccb)->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
243
244#define	ISP_SPRIV_ERRSET	0x1
245#define	ISP_SPRIV_INWDOG	0x2
246#define	ISP_SPRIV_GRACE		0x4
247#define	ISP_SPRIV_DONE		0x8
248
249#define	XS_CMD_S_WDOG(sccb)	(sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_INWDOG
250#define	XS_CMD_C_WDOG(sccb)	(sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_INWDOG
251#define	XS_CMD_WDOG_P(sccb)	((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_INWDOG)
252
253#define	XS_CMD_S_GRACE(sccb)	(sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_GRACE
254#define	XS_CMD_C_GRACE(sccb)	(sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_GRACE
255#define	XS_CMD_GRACE_P(sccb)	((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_GRACE)
256
257#define	XS_CMD_S_DONE(sccb)	(sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_DONE
258#define	XS_CMD_C_DONE(sccb)	(sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_DONE
259#define	XS_CMD_DONE_P(sccb)	((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_DONE)
260
261#define	XS_CMD_S_CLEAR(sccb)	(sccb)->ccb_h.spriv_field0 = 0
262
263
264#define	XS_SETERR(ccb, v)	(ccb)->ccb_h.status &= ~CAM_STATUS_MASK, \
265				(ccb)->ccb_h.status |= v, \
266				(ccb)->ccb_h.spriv_field0 |= ISP_SPRIV_ERRSET
267
268#define	XS_INITERR(ccb)		XS_SETERR(ccb, CAM_REQ_INPROG), \
269				XS_CMD_S_CLEAR(ccb)
270
271#define	XS_ERR(ccb)		((ccb)->ccb_h.status & CAM_STATUS_MASK)
272
273#define	XS_NOERR(ccb)		\
274	(((ccb)->ccb_h.spriv_field0 & ISP_SPRIV_ERRSET) == 0 || \
275	 ((ccb)->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)
276
277#define	XS_CMD_DONE		isp_done
278
279extern void isp_done(struct ccb_scsiio *);
280
281/*
282 * Can we tag?
283 */
284#define	XS_CANTAG(ccb)		(((ccb)->ccb_h.flags & CAM_TAG_ACTION_VALID) \
285				  && (ccb)->tag_action != CAM_TAG_ACTION_NONE)
286/*
287 * And our favorite tag is....
288 */
289#define	XS_KINDOF_TAG(ccb)	\
290	((ccb->tag_action == MSG_SIMPLE_Q_TAG)? REQFLAG_STAG : \
291	  ((ccb->tag_action == MSG_HEAD_OF_Q_TAG)? REQFLAG_HTAG : REQFLAG_OTAG))
292
293#define	CMD_COMPLETE		0
294#define	CMD_EAGAIN		1
295#define	CMD_QUEUED		2
296#define	CMD_RQLATER		3
297
298extern void isp_attach(struct ispsoftc *);
299extern void isp_uninit(struct ispsoftc *);
300
301#define	MEMZERO			bzero
302#define	MEMCPY(dst, src, amt)	bcopy((src), (dst), (amt))
303#ifdef	__alpha__
304#define	MemoryBarrier	alpha_mb
305#else
306#define	MemoryBarrier()
307#endif
308
309
310#define	DMA_MSW(x)	(((x) >> 16) & 0xffff)
311#define	DMA_LSW(x)	(((x) & 0xffff))
312
313#define	ISP_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src)	\
314	bcopy(src, dest, sizeof (isp_pdb_t))
315#define	ISP_SWIZZLE_ICB(a, b)
316#define	ISP_SWIZZLE_REQUEST(a, b)
317#define	ISP_UNSWIZZLE_RESPONSE(a, b)
318#define	ISP_SWIZZLE_SNS_REQ(a, b)
319#define	ISP_UNSWIZZLE_SNS_RSP(a, b, c)
320
321#define	IDPRINTF(lev, x)	if (isp->isp_dblev >= (u_int8_t) lev) printf x
322#define	PRINTF			printf
323#define	CFGPRINTF		if (bootverbose || DFLT_DBLEVEL > 1) printf
324#define	STRNCAT			strncat
325static __inline char *strncat(char *, const char *, size_t);
326static __inline char *
327strncat(char *d, const char *s, size_t c)
328{
329        char *t = d;
330
331        if (c) {
332                while (*d)
333                        d++;
334                while ((*d++ = *s++)) {
335                        if (--c == 0) {
336                                *d = '\0';
337                                break;
338                        }
339                }
340        }
341        return (t);
342}
343
344#define	SYS_DELAY(x)	DELAY(x)
345
346#define	FC_FW_READY_DELAY	(5 * 1000000)
347#define	DEFAULT_LOOPID(x)	109
348#define	DEFAULT_WWN(x)		(x)->isp_osinfo.default_wwn
349
350#define	INLINE	__inline
351#include <dev/isp/isp_inline.h>
352#endif	/* _ISP_FREEBSD_H */
353