ispvar.h revision 52347
1218885Sdim/* $FreeBSD: head/sys/dev/isp/ispvar.h 52347 1999-10-17 18:45:31Z mjacob $ */
2218885Sdim/*
3218885Sdim * Soft Definitions for for Qlogic ISP SCSI adapters.
4218885Sdim *
5218885Sdim * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
6218885Sdim * NASA/Ames Research Center
7218885Sdim * All rights reserved.
8218885Sdim *
9218885Sdim * Redistribution and use in source and binary forms, with or without
10218885Sdim * modification, are permitted provided that the following conditions
11218885Sdim * are met:
12218885Sdim * 1. Redistributions of source code must retain the above copyright
13218885Sdim *    notice immediately at the beginning of the file, without modification,
14249423Sdim *    this list of conditions, and the following disclaimer.
15249423Sdim * 2. Redistributions in binary form must reproduce the above copyright
16218885Sdim *    notice, this list of conditions and the following disclaimer in the
17243830Sdim *    documentation and/or other materials provided with the distribution.
18218885Sdim * 3. The name of the author may not be used to endorse or promote products
19218885Sdim *    derived from this software without specific prior written permission.
20218885Sdim *
21218885Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22218885Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23218885Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24218885Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25218885Sdim * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26218885Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27218885Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28218885Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29218885Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30218885Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31218885Sdim * SUCH DAMAGE.
32218885Sdim *
33218885Sdim */
34218885Sdim
35218885Sdim#ifndef	_ISPVAR_H
36218885Sdim#define	_ISPVAR_H
37218885Sdim
38218885Sdim#if defined(__NetBSD__) || defined(__OpenBSD__)
39218885Sdim#include <dev/ic/ispmbox.h>
40218885Sdim#endif
41218885Sdim#ifdef	__FreeBSD__
42218885Sdim#include <dev/isp/ispmbox.h>
43218885Sdim#endif
44218885Sdim#ifdef	__linux__
45218885Sdim#include "ispmbox.h"
46218885Sdim#endif
47218885Sdim
48218885Sdim#define	ISP_CORE_VERSION_MAJOR	1
49218885Sdim#define	ISP_CORE_VERSION_MINOR	10
50218885Sdim
51218885Sdim/*
52218885Sdim * Vector for bus specific code to provide specific services.
53218885Sdim */
54218885Sdimstruct ispsoftc;
55218885Sdimstruct ispmdvec {
56218885Sdim	u_int16_t	(*dv_rd_reg) __P((struct ispsoftc *, int));
57218885Sdim	void		(*dv_wr_reg) __P((struct ispsoftc *, int, u_int16_t));
58218885Sdim	int		(*dv_mbxdma) __P((struct ispsoftc *));
59218885Sdim	int		(*dv_dmaset) __P((struct ispsoftc *,
60218885Sdim		ISP_SCSI_XFER_T *, ispreq_t *, u_int8_t *, u_int8_t));
61218885Sdim	void		(*dv_dmaclr)
62218885Sdim		__P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t));
63218885Sdim	void		(*dv_reset0) __P((struct ispsoftc *));
64218885Sdim	void		(*dv_reset1) __P((struct ispsoftc *));
65218885Sdim	void		(*dv_dregs) __P((struct ispsoftc *));
66218885Sdim	const u_int16_t *dv_ispfw;	/* ptr to f/w */
67218885Sdim	u_int16_t 	dv_fwlen;	/* length of f/w */
68218885Sdim	u_int16_t	dv_codeorg;	/* code ORG for f/w */
69218885Sdim	u_int32_t	dv_fwrev;	/* f/w revision */
70218885Sdim	/*
71218885Sdim	 * Initial values for conf1 register
72218885Sdim	 */
73218885Sdim	u_int16_t	dv_conf1;
74218885Sdim	u_int16_t	dv_clock;	/* clock frequency */
75218885Sdim};
76218885Sdim
77218885Sdim#define	MAX_TARGETS	16
78218885Sdim#ifdef	ISP2100_FABRIC
79243830Sdim#define	MAX_FC_TARG	256
80243830Sdim#else
81218885Sdim#define	MAX_FC_TARG	126
82218885Sdim#endif
83218885Sdim
84218885Sdim#define	ISP_MAX_TARGETS(isp)	(IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS)
85218885Sdim#ifdef	ISP2100_SCCLUN
86218885Sdim#define	_ISP_FC_LUN(isp)	65536
87218885Sdim#else
88218885Sdim#define	_ISP_FC_LUN(isp)	16
89218885Sdim#endif
90218885Sdim#define	_ISP_SCSI_LUN(isp)	\
91218885Sdim	((ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(7, 55, 0))? 32 : 8)
92218885Sdim#define	ISP_MAX_LUNS(isp)	\
93218885Sdim	(IS_FC(isp)? _ISP_FC_LUN(isp) : _ISP_SCSI_LUN(isp))
94218885Sdim
95218885Sdim/* this is the size of a queue entry (request and response) */
96218885Sdim#define	QENTRY_LEN			64
97218885Sdim/* both request and result queue length must be a power of two */
98218885Sdim#define	RQUEST_QUEUE_LEN		MAXISPREQUEST
99218885Sdim/* I've seen wierdnesses with the result queue < 64 */
100218885Sdim#if	MAXISPREQUEST > 64
101218885Sdim#define	RESULT_QUEUE_LEN		(MAXISPREQUEST/2)
102218885Sdim#else
103218885Sdim#define	RESULT_QUEUE_LEN		MAXISPREQUEST
104218885Sdim#endif
105218885Sdim#define	ISP_QUEUE_ENTRY(q, idx)		((q) + ((idx) * QENTRY_LEN))
106218885Sdim#define	ISP_QUEUE_SIZE(n)		((n) * QENTRY_LEN)
107218885Sdim#define	ISP_NXT_QENTRY(idx, qlen)	(((idx) + 1) & ((qlen)-1))
108218885Sdim#define	ISP_QAVAIL(in, out, qlen)	\
109218885Sdim	((in == out)? (qlen - 1) : ((in > out)? \
110218885Sdim	((qlen - 1) - (in - out)) : (out - in - 1)))
111218885Sdim/*
112218885Sdim * SCSI Specific Host Adapter Parameters- per bus, per target
113218885Sdim */
114218885Sdim
115218885Sdimtypedef struct {
116218885Sdim	u_int		isp_gotdparms		: 1,
117218885Sdim			isp_req_ack_active_neg	: 1,
118218885Sdim			isp_data_line_active_neg: 1,
119218885Sdim			isp_cmd_dma_burst_enable: 1,
120218885Sdim			isp_data_dma_burst_enabl: 1,
121218885Sdim			isp_fifo_threshold	: 3,
122218885Sdim			isp_ultramode		: 1,
123218885Sdim			isp_diffmode		: 1,
124218885Sdim			isp_lvdmode		: 1,
125218885Sdim						: 1,
126218885Sdim			isp_initiator_id	: 4,
127218885Sdim			isp_async_data_setup	: 4;
128218885Sdim	u_int16_t	isp_selection_timeout;
129218885Sdim	u_int16_t	isp_max_queue_depth;
130218885Sdim	u_int8_t	isp_tag_aging;
131218885Sdim	u_int8_t	isp_bus_reset_delay;
132218885Sdim	u_int8_t	isp_retry_count;
133218885Sdim	u_int8_t	isp_retry_delay;
134218885Sdim	struct {
135218885Sdim		u_int	dev_enable	:	1,	/* ignored */
136218885Sdim					:	1,
137218885Sdim			dev_update	:	1,
138218885Sdim			dev_refresh	:	1,
139218885Sdim			exc_throttle	:	8,
140218885Sdim			cur_offset	:	4,
141218885Sdim			sync_offset	:	4;
142218885Sdim		u_int8_t	cur_period;	/* current sync period */
143218885Sdim		u_int8_t	sync_period;	/* goal sync period */
144218885Sdim		u_int16_t	dev_flags;	/* goal device flags */
145218885Sdim		u_int16_t	cur_dflags;	/* current device flags */
146218885Sdim	} isp_devparam[MAX_TARGETS];
147218885Sdim} sdparam;
148218885Sdim
149218885Sdim/*
150218885Sdim * Device Flags
151218885Sdim */
152218885Sdim#define	DPARM_DISC	0x8000
153218885Sdim#define	DPARM_PARITY	0x4000
154218885Sdim#define	DPARM_WIDE	0x2000
155218885Sdim#define	DPARM_SYNC	0x1000
156#define	DPARM_TQING	0x0800
157#define	DPARM_ARQ	0x0400
158#define	DPARM_QFRZ	0x0200
159#define	DPARM_RENEG	0x0100
160#define	DPARM_NARROW	0x0080	/* Possibly only available with >= 7.55 fw */
161#define	DPARM_ASYNC	0x0040	/* Possibly only available with >= 7.55 fw */
162#define	DPARM_DEFAULT	(0xFF00 & ~DPARM_QFRZ)
163#define	DPARM_SAFE_DFLT	(DPARM_DEFAULT & ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING))
164
165
166/* technically, not really correct, as they need to be rated based upon clock */
167#define	ISP_40M_SYNCPARMS	0x080a
168#define	ISP_20M_SYNCPARMS	0x080c
169#define	ISP_10M_SYNCPARMS	0x0c19
170#define	ISP_08M_SYNCPARMS	0x0c25
171#define	ISP_05M_SYNCPARMS	0x0c32
172#define	ISP_04M_SYNCPARMS	0x0c41
173
174/*
175 * Fibre Channel Specifics
176 */
177#define	FL_PORT_ID		0x7e	/* FL_Port Special ID */
178#define	FC_PORT_ID		0x7f	/* Fabric Controller Special ID */
179#define	FC_SNS_ID		0x80	/* SNS Server Special ID */
180
181typedef struct {
182	u_int32_t		isp_fwoptions	: 16,
183						: 7,
184				loop_seen_once	: 1,
185				isp_loopstate	: 3,	/* Current Loop State */
186				isp_fwstate	: 3,	/* ISP F/W state */
187				isp_gotdparms	: 1,
188				isp_onfabric	: 1;
189	u_int8_t		isp_loopid;	/* hard loop id */
190	u_int8_t		isp_alpa;	/* ALPA */
191	volatile u_int16_t	isp_lipseq;	/* LIP sequence # */
192	u_int32_t		isp_portid;
193	u_int8_t		isp_execthrottle;
194	u_int8_t		isp_retry_delay;
195	u_int8_t		isp_retry_count;
196	u_int8_t		isp_reserved;
197	u_int16_t		isp_maxalloc;
198	u_int16_t		isp_maxfrmlen;
199	u_int64_t		isp_nodewwn;
200	u_int64_t		isp_portwwn;
201	/*
202	 * Port Data Base. This is indexed by 'target', which is invariate.
203	 * However, elements within can move around due to loop changes,
204	 * so the actual loop ID passed to the F/W is in this structure.
205	 * The first time the loop is seen up, loopid will match the index
206	 * (except for fabric nodes which are above mapped above FC_SNS_ID
207	 * and are completely virtual), but subsequent LIPs can cause things
208	 * to move around.
209	 */
210	struct lportdb {
211		u_int
212					loopid	: 8,
213						: 4,
214					fabdev	: 1,
215					roles	: 2,
216					valid	: 1;
217		u_int32_t		portid;
218		u_int64_t		node_wwn;
219		u_int64_t		port_wwn;
220	} portdb[MAX_FC_TARG], tport[FL_PORT_ID];
221
222	/*
223	 * Scratch DMA mapped in area to fetch Port Database stuff, etc.
224	 */
225	caddr_t			isp_scratch;
226	u_int32_t		isp_scdma;
227} fcparam;
228
229#define	FW_CONFIG_WAIT		0
230#define	FW_WAIT_AL_PA		1
231#define	FW_WAIT_LOGIN		2
232#define	FW_READY		3
233#define	FW_LOSS_OF_SYNC		4
234#define	FW_ERROR		5
235#define	FW_REINIT		6
236#define	FW_NON_PART		7
237
238#define	LOOP_NIL		0
239#define	LOOP_LIP_RCVD		1
240#define	LOOP_PDB_RCVD		2
241#define	LOOP_READY		7
242
243/*
244 * Soft Structure per host adapter
245 */
246struct ispsoftc {
247	/*
248	 * Platform (OS) specific data
249	 */
250	struct isposinfo	isp_osinfo;
251
252	/*
253	 * Pointer to bus specific data
254	 */
255	struct ispmdvec *	isp_mdvec;
256
257	/*
258	 * Mostly nonvolatile state.
259	 */
260
261	u_int		isp_clock	: 8,
262			isp_confopts	: 8,
263			isp_fast_mttr	: 1,
264					: 1,
265			isp_used	: 1,
266			isp_dblev	: 3,
267			isp_dogactive	: 1,
268			isp_bustype	: 1,	/* BUS Implementation */
269			isp_type	: 8;	/* HBA Type and Revision */
270
271	u_int16_t		isp_fwrev[3];	/* Running F/W revision */
272	u_int16_t		isp_romfw_rev[3]; /* 'ROM' F/W revision */
273	u_int16_t		isp_maxcmds;	/* max active I/O cmds */
274	void * 			isp_param;
275
276	/*
277	 * Volatile state
278	 */
279
280	volatile u_int		:	9,
281		isp_state	:	3,
282		isp_sendmarker	:	2,	/* send a marker entry */
283		isp_update	:	2,	/* update parameters */
284		isp_nactive	:	16;	/* how many commands active */
285
286	volatile u_int16_t	isp_reqodx;	/* index of last ISP pickup */
287	volatile u_int16_t	isp_reqidx;	/* index of next request */
288	volatile u_int16_t	isp_residx;	/* index of next result */
289	volatile u_int16_t	isp_lasthdls;	/* last handle seed */
290
291	/*
292	 * Active commands are stored here, found by handle functions.
293	 */
294	ISP_SCSI_XFER_T **isp_xflist;
295
296	/*
297	 * request/result queue pointers and dma handles for them.
298	 */
299	caddr_t			isp_rquest;
300	caddr_t			isp_result;
301	u_int32_t		isp_rquest_dma;
302	u_int32_t		isp_result_dma;
303};
304
305#define	SDPARAM(isp)	((sdparam *) (isp)->isp_param)
306#define	FCPARAM(isp)	((fcparam *) (isp)->isp_param)
307
308/*
309 * ISP States
310 */
311#define	ISP_NILSTATE	0
312#define	ISP_RESETSTATE	1
313#define	ISP_INITSTATE	2
314#define	ISP_RUNSTATE	3
315
316/*
317 * ISP Configuration Options
318 */
319#define	ISP_CFG_NORELOAD	0x80	/* don't download f/w */
320#define	ISP_CFG_NONVRAM		0x40	/* ignore NVRAM */
321#define	ISP_CFG_FULL_DUPLEX	0x01	/* Fibre Channel Only */
322
323#define	ISP_FW_REV(maj, min, mic)	((maj << 24) | (min << 16) | mic)
324#define	ISP_FW_REVX(xp)	((xp[0]<<24) | (xp[1] << 16) | xp[2])
325
326/*
327 * Bus (implementation) types
328 */
329#define	ISP_BT_PCI		0	/* PCI Implementations */
330#define	ISP_BT_SBUS		1	/* SBus Implementations */
331
332/*
333 * Chip Types
334 */
335#define	ISP_HA_SCSI		0xf
336#define	ISP_HA_SCSI_UNKNOWN	0x1
337#define	ISP_HA_SCSI_1020	0x2
338#define	ISP_HA_SCSI_1020A	0x3
339#define	ISP_HA_SCSI_1040	0x4
340#define	ISP_HA_SCSI_1040A	0x5
341#define	ISP_HA_SCSI_1040B	0x6
342#define	ISP_HA_SCSI_1040C	0x7
343#define	ISP_HA_SCSI_1080	0xd
344#define	ISP_HA_SCSI_12X0	0xe
345#define	ISP_HA_FC		0xf0
346#define	ISP_HA_FC_2100		0x10
347#define	ISP_HA_FC_2200		0x20
348
349#define	IS_SCSI(isp)	(isp->isp_type & ISP_HA_SCSI)
350#define	IS_1080(isp)	(isp->isp_type == ISP_HA_SCSI_1080)
351#define	IS_12X0(isp)	(isp->isp_type == ISP_HA_SCSI_12X0)
352#define	IS_FC(isp)	(isp->isp_type & ISP_HA_FC)
353
354/*
355 * Macros to read, write ISP registers through bus specific code.
356 */
357
358#define	ISP_READ(isp, reg)	\
359	(*(isp)->isp_mdvec->dv_rd_reg)((isp), (reg))
360
361#define	ISP_WRITE(isp, reg, val)	\
362	(*(isp)->isp_mdvec->dv_wr_reg)((isp), (reg), (val))
363
364#define	ISP_MBOXDMASETUP(isp)	\
365	(*(isp)->isp_mdvec->dv_mbxdma)((isp))
366
367#define	ISP_DMASETUP(isp, xs, req, iptrp, optr)	\
368	(*(isp)->isp_mdvec->dv_dmaset)((isp), (xs), (req), (iptrp), (optr))
369
370#define	ISP_DMAFREE(isp, xs, hndl)	\
371	if ((isp)->isp_mdvec->dv_dmaclr) \
372	    (*(isp)->isp_mdvec->dv_dmaclr)((isp), (xs), (hndl))
373
374#define	ISP_RESET0(isp)	\
375	if ((isp)->isp_mdvec->dv_reset0) (*(isp)->isp_mdvec->dv_reset0)((isp))
376#define	ISP_RESET1(isp)	\
377	if ((isp)->isp_mdvec->dv_reset1) (*(isp)->isp_mdvec->dv_reset1)((isp))
378#define	ISP_DUMPREGS(isp)	\
379	if ((isp)->isp_mdvec->dv_dregs) (*(isp)->isp_mdvec->dv_dregs)((isp))
380
381#define	ISP_SETBITS(isp, reg, val)	\
382 (*(isp)->isp_mdvec->dv_wr_reg)((isp), (reg), ISP_READ((isp), (reg)) | (val))
383
384#define	ISP_CLRBITS(isp, reg, val)	\
385 (*(isp)->isp_mdvec->dv_wr_reg)((isp), (reg), ISP_READ((isp), (reg)) & ~(val))
386
387/*
388 * Function Prototypes
389 */
390
391/*
392 * Reset Hardware. Totally. Assumes that you'll follow this with
393 * a call to isp_init.
394 */
395void isp_reset __P((struct ispsoftc *));
396
397/*
398 * Initialize Hardware to known state
399 */
400void isp_init __P((struct ispsoftc *));
401
402/*
403 * Reset the ISP and call completion for any orphaned commands.
404 */
405void isp_restart __P((struct ispsoftc *));
406
407/*
408 * Interrupt Service Routine
409 */
410int isp_intr __P((void *));
411
412/*
413 * Command Entry Point
414 */
415int32_t ispscsicmd __P((ISP_SCSI_XFER_T *));
416
417/*
418 * Platform Dependent to External to Internal Control Function
419 *
420 * Assumes all locks are held and that no reentrancy issues need be dealt with.
421 *
422 */
423typedef enum {
424	ISPCTL_RESET_BUS,		/* Reset Bus */
425	ISPCTL_RESET_DEV,		/* Reset Device */
426	ISPCTL_ABORT_CMD,		/* Abort Command */
427	ISPCTL_UPDATE_PARAMS,		/* Update Operating Parameters */
428	ISPCTL_FCLINK_TEST		/* Test FC Link Status */
429} ispctl_t;
430int isp_control __P((struct ispsoftc *, ispctl_t, void *));
431
432
433/*
434 * Platform Dependent to Internal to External Control Function
435 * (each platform must provide such a function)
436 *
437 * Assumes all locks are held and that no reentrancy issues need be dealt with.
438 *
439 */
440
441typedef enum {
442	ISPASYNC_NEW_TGT_PARAMS,
443	ISPASYNC_BUS_RESET,		/* Bus Was Reset */
444	ISPASYNC_LOOP_DOWN,		/* FC Loop Down */
445	ISPASYNC_LOOP_UP,		/* FC Loop Up */
446	ISPASYNC_PDB_CHANGED,		/* FC Port Data Base Changed */
447	ISPASYNC_CHANGE_NOTIFY,		/* FC SNS Change Notification */
448	ISPASYNC_FABRIC_DEV,		/* FC New Fabric Device */
449} ispasync_t;
450int isp_async __P((struct ispsoftc *, ispasync_t, void *));
451
452/*
453 * lost command routine (XXXX IN TRANSITION XXXX)
454 */
455void isp_lostcmd __P((struct ispsoftc *, ISP_SCSI_XFER_T *));
456
457#endif	/* _ISPVAR_H */
458