isp_target.h revision 77365
1180811Sstas/* $FreeBSD: head/sys/dev/isp/isp_target.h 77365 2001-05-28 21:20:43Z mjacob $ */
2180811Sstas/*
3181602Sraj * Qlogic Target Mode Structure and Flag Definitions
4181602Sraj *
5180811Sstas * Copyright (c) 1997, 1998
6180811Sstas * Patrick Stirling
7180811Sstas * pms@psconsult.com
8180811Sstas * All rights reserved.
9180811Sstas *
10180811Sstas * Additional Copyright (c) 1999, 2000, 2001
11180811Sstas * Matthew Jacob
12180811Sstas * mjacob@feral.com
13180811Sstas * All rights reserved.
14180811Sstas *
15180811Sstas *
16180811Sstas * Redistribution and use in source and binary forms, with or without
17180811Sstas * modification, are permitted provided that the following conditions
18180811Sstas * are met:
19180811Sstas * 1. Redistributions of source code must retain the above copyright
20180811Sstas *    notice immediately at the beginning of the file, without modification,
21180811Sstas *    this list of conditions, and the following disclaimer.
22180811Sstas * 2. The name of the author may not be used to endorse or promote products
23180811Sstas *    derived from this software without specific prior written permission.
24180811Sstas *
25180811Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26180811Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27180811Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28180811Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
29180811Sstas * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30180811Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31181602Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32180811Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33180811Sstas * SUCH DAMAGE.
34180811Sstas *
35180811Sstas */
36180811Sstas#ifndef	_ISP_TARGET_H
37180811Sstas#define	_ISP_TARGET_H
38180811Sstas
39180811Sstas/*
40180811Sstas * Defines for all entry types
41180811Sstas */
42180811Sstas#define QLTM_SVALID	0x80
43180811Sstas#define	QLTM_SENSELEN	18
44180811Sstas
45180811Sstas/*
46180811Sstas * Structure for Enable Lun and Modify Lun queue entries
47180811Sstas */
48180811Sstastypedef struct {
49180811Sstas	isphdr_t	le_header;
50180811Sstas	u_int32_t	le_reserved;
51180811Sstas	u_int8_t	le_lun;
52180811Sstas	u_int8_t	le_rsvd;
53180811Sstas	u_int8_t	le_ops;		/* Modify LUN only */
54180811Sstas	u_int8_t	le_tgt;		/* Not for FC */
55180811Sstas	u_int32_t	le_flags;	/* Not for FC */
56181602Sraj	u_int8_t	le_status;
57181602Sraj	u_int8_t	le_reserved2;
58181602Sraj	u_int8_t	le_cmd_count;
59181602Sraj	u_int8_t	le_in_count;
60181602Sraj	u_int8_t	le_cdb6len;	/* Not for FC */
61180811Sstas	u_int8_t	le_cdb7len;	/* Not for FC */
62181602Sraj	u_int16_t	le_timeout;
63181602Sraj	u_int16_t	le_reserved3[20];
64181602Sraj} lun_entry_t;
65181602Sraj
66180811Sstas/*
67181602Sraj * le_flags values
68181602Sraj */
69181602Sraj#define LUN_TQAE	0x00000002	/* bit1  Tagged Queue Action Enable */
70181602Sraj#define LUN_DSSM	0x01000000	/* bit24 Disable Sending SDP Message */
71180811Sstas#define	LUN_DISAD	0x02000000	/* bit25 Disable autodisconnect */
72181602Sraj#define LUN_DM		0x40000000	/* bit30 Disconnects Mandatory */
73181602Sraj
74181602Sraj/*
75181602Sraj * le_ops values
76181602Sraj */
77181602Sraj#define LUN_CCINCR	0x01	/* increment command count */
78181602Sraj#define LUN_CCDECR	0x02	/* decrement command count */
79181602Sraj#define LUN_ININCR	0x40	/* increment immed. notify count */
80181602Sraj#define LUN_INDECR	0x80	/* decrement immed. notify count */
81181602Sraj
82181602Sraj/*
83181602Sraj * le_status values
84181602Sraj */
85181602Sraj#define	LUN_OK		0x01	/* we be rockin' */
86180811Sstas#define LUN_ERR		0x04	/* request completed with error */
87180811Sstas#define LUN_INVAL	0x06	/* invalid request */
88181602Sraj#define LUN_NOCAP	0x16	/* can't provide requested capability */
89181602Sraj#define LUN_ENABLED	0x3E	/* LUN already enabled */
90181602Sraj
91181602Sraj/*
92181602Sraj * Immediate Notify Entry structure
93180811Sstas */
94181602Sraj#define IN_MSGLEN	8	/* 8 bytes */
95180811Sstas#define IN_RSVDLEN	8	/* 8 words */
96181602Srajtypedef struct {
97181602Sraj	isphdr_t	in_header;
98181602Sraj	u_int32_t	in_reserved;
99181602Sraj	u_int8_t	in_lun;		/* lun */
100180811Sstas	u_int8_t	in_iid;		/* initiator */
101181602Sraj	u_int8_t	in_reserved2;
102181602Sraj	u_int8_t	in_tgt;		/* target */
103181602Sraj	u_int32_t	in_flags;
104181602Sraj	u_int8_t	in_status;
105181602Sraj	u_int8_t	in_rsvd2;
106181602Sraj	u_int8_t	in_tag_val;	/* tag value */
107181602Sraj	u_int8_t	in_tag_type;	/* tag type */
108181602Sraj	u_int16_t	in_seqid;	/* sequence id */
109181602Sraj	u_int8_t	in_msg[IN_MSGLEN];	/* SCSI message bytes */
110181602Sraj	u_int16_t	in_reserved3[IN_RSVDLEN];
111181602Sraj	u_int8_t	in_sense[QLTM_SENSELEN];/* suggested sense data */
112181602Sraj} in_entry_t;
113181602Sraj
114181602Srajtypedef struct {
115181602Sraj	isphdr_t	in_header;
116181602Sraj	u_int32_t	in_reserved;
117181602Sraj	u_int8_t	in_lun;		/* lun */
118181602Sraj	u_int8_t	in_iid;		/* initiator */
119181602Sraj	u_int16_t	in_scclun;
120181602Sraj	u_int32_t	in_reserved2;
121181602Sraj	u_int16_t	in_status;
122181602Sraj	u_int16_t	in_task_flags;
123181602Sraj	u_int16_t	in_seqid;	/* sequence id */
124181602Sraj} in_fcentry_t;
125181602Sraj
126181602Sraj/*
127181602Sraj * Values for the in_status field
128181602Sraj */
129181602Sraj#define	IN_REJECT	0x0D	/* Message Reject message received */
130181602Sraj#define IN_RESET	0x0E	/* Bus Reset occurred */
131181602Sraj#define IN_NO_RCAP	0x16	/* requested capability not available */
132181602Sraj#define IN_IDE_RECEIVED	0x33	/* Initiator Detected Error msg received */
133181602Sraj#define IN_RSRC_UNAVAIL	0x34	/* resource unavailable */
134181602Sraj#define IN_MSG_RECEIVED	0x36	/* SCSI message received */
135181602Sraj#define	IN_ABORT_TASK	0x20	/* task named in RX_ID is being aborted (FC) */
136181602Sraj#define	IN_PORT_LOGOUT	0x29	/* port has logged out (FC) */
137181602Sraj#define	IN_PORT_CHANGED	0x2A	/* port changed */
138181602Sraj#define	IN_GLOBAL_LOGO	0x2E	/* all ports logged out */
139181602Sraj#define	IN_NO_NEXUS	0x3B	/* Nexus not established */
140181602Sraj
141181602Sraj/*
142181602Sraj * Values for the in_task_flags field- should only get one at a time!
143181602Sraj */
144181602Sraj#define	TASK_FLAGS_ABORT_TASK		(1<<9)
145181602Sraj#define	TASK_FLAGS_CLEAR_TASK_SET	(1<<10)
146181602Sraj#define	TASK_FLAGS_TARGET_RESET		(1<<13)
147181602Sraj#define	TASK_FLAGS_CLEAR_ACA		(1<<14)
148181602Sraj#define	TASK_FLAGS_TERMINATE_TASK	(1<<15)
149181602Sraj
150181602Sraj#ifndef	MSG_ABORT_TAG
151181602Sraj#define	MSG_ABORT_TAG		0x06
152181602Sraj#endif
153181602Sraj#ifndef	MSG_CLEAR_QUEUE
154180811Sstas#define	MSG_CLEAR_QUEUE		0x0e
155181602Sraj#endif
156181602Sraj#ifndef	MSG_BUS_DEV_RESET
157181602Sraj#define	MSG_BUS_DEV_RESET	0x0b
158181602Sraj#endif
159181602Sraj#ifndef	MSG_REL_RECOVERY
160181602Sraj#define	MSG_REL_RECOVERY	0x10
161181602Sraj#endif
162181602Sraj#ifndef	MSG_TERM_IO_PROC
163181602Sraj#define	MSG_TERM_IO_PROC	0x11
164181602Sraj#endif
165181602Sraj
166181602Sraj
167181602Sraj/*
168181602Sraj * Notify Acknowledge Entry structure
169181602Sraj */
170181602Sraj#define NA_RSVDLEN	22
171181602Srajtypedef struct {
172181602Sraj	isphdr_t	na_header;
173181602Sraj	u_int32_t	na_reserved;
174181602Sraj	u_int8_t	na_lun;		/* lun */
175181602Sraj	u_int8_t	na_iid;		/* initiator */
176181602Sraj	u_int8_t	na_reserved2;
177181602Sraj	u_int8_t	na_tgt;		/* target */
178181602Sraj	u_int32_t	na_flags;
179181602Sraj	u_int8_t	na_status;
180181602Sraj	u_int8_t	na_event;
181181602Sraj	u_int16_t	na_seqid;	/* sequence id */
182181602Sraj	u_int16_t	na_reserved3[NA_RSVDLEN];
183181602Sraj} na_entry_t;
184181602Sraj
185181602Sraj/*
186181602Sraj * Value for the na_event field
187180811Sstas */
188180811Sstas#define NA_RST_CLRD	0x80	/* Clear an async event notification */
189180811Sstas#define	NA_OK		0x01	/* Notify Acknowledge Succeeded */
190180811Sstas#define	NA_INVALID	0x06	/* Invalid Notify Acknowledge */
191181602Sraj
192181602Sraj#define	NA2_RSVDLEN	21
193180811Sstastypedef struct {
194180811Sstas	isphdr_t	na_header;
195181602Sraj	u_int32_t	na_reserved;
196180811Sstas	u_int8_t	na_lun;		/* lun */
197181602Sraj	u_int8_t	na_iid;		/* initiator */
198181602Sraj	u_int16_t	na_scclun;
199180811Sstas	u_int16_t	na_flags;
200181602Sraj	u_int16_t	na_reserved2;
201181602Sraj	u_int16_t	na_status;
202181602Sraj	u_int16_t	na_task_flags;
203181602Sraj	u_int16_t	na_seqid;	/* sequence id */
204181602Sraj	u_int16_t	na_reserved3[NA2_RSVDLEN];
205180811Sstas} na_fcentry_t;
206181602Sraj#define	NAFC_RCOUNT	0x80	/* increment resource count */
207181602Sraj#define NAFC_RST_CLRD	0x20	/* Clear LIP Reset */
208181602Sraj/*
209181602Sraj * Accept Target I/O Entry structure
210181602Sraj */
211181602Sraj#define ATIO_CDBLEN	26
212181602Sraj
213181602Srajtypedef struct {
214181602Sraj	isphdr_t	at_header;
215180811Sstas	u_int16_t	at_reserved;
216180811Sstas	u_int16_t	at_handle;
217181602Sraj	u_int8_t	at_lun;		/* lun */
218181602Sraj	u_int8_t	at_iid;		/* initiator */
219180811Sstas	u_int8_t	at_cdblen; 	/* cdb length */
220181602Sraj	u_int8_t	at_tgt;		/* target */
221181602Sraj	u_int32_t	at_flags;
222181602Sraj	u_int8_t	at_status;	/* firmware status */
223181602Sraj	u_int8_t	at_scsi_status;	/* scsi status */
224181602Sraj	u_int8_t	at_tag_val;	/* tag value */
225180811Sstas	u_int8_t	at_tag_type;	/* tag type */
226181602Sraj	u_int8_t	at_cdb[ATIO_CDBLEN];	/* received CDB */
227180811Sstas	u_int8_t	at_sense[QLTM_SENSELEN];/* suggested sense data */
228181602Sraj} at_entry_t;
229181602Sraj
230181602Sraj/*
231181602Sraj * at_flags values
232181602Sraj */
233181602Sraj#define AT_NODISC	0x00008000	/* disconnect disabled */
234181602Sraj#define AT_TQAE		0x00000002	/* Tagged Queue Action enabled */
235181602Sraj
236181602Sraj/*
237181602Sraj * at_status values
238181602Sraj */
239181602Sraj#define AT_PATH_INVALID	0x07	/* ATIO sent to firmware for disabled lun */
240181602Sraj#define	AT_RESET	0x0E	/* SCSI Bus Reset Occurred */
241181602Sraj#define AT_PHASE_ERROR	0x14	/* Bus phase sequence error */
242181602Sraj#define AT_NOCAP	0x16	/* Requested capability not available */
243180811Sstas#define AT_BDR_MSG	0x17	/* Bus Device Reset msg received */
244180811Sstas#define AT_CDB		0x3D	/* CDB received */
245181602Sraj
246181602Sraj/*
247180811Sstas * Macros to create and fetch and test concatenated handle and tag value macros
248181602Sraj */
249181602Sraj
250181602Sraj#define	AT_MAKE_TAGID(tid, aep)						\
251181602Sraj	tid = ((aep)->at_handle << 16);					\
252181602Sraj	if ((aep)->at_flags & AT_TQAE)					\
253181602Sraj		(tid) |= ((aep)->at_tag_val + 1)
254181602Sraj
255181602Sraj#define	CT_MAKE_TAGID(tid, ct)						\
256181602Sraj	tid = ((ct)->ct_fwhandle << 16);				\
257181602Sraj	if ((ct)->ct_flags & CT_TQAE)					\
258181602Sraj		(tid) |= ((ct)->ct_tag_val + 1)
259181602Sraj
260181602Sraj#define	AT_HAS_TAG(val)		((val) & 0xffff)
261181602Sraj#define	AT_GET_TAG(val)		AT_HAS_TAG(val) - 1
262180811Sstas#define	AT_GET_HANDLE(val)	((val) >> 16)
263181602Sraj
264180811Sstas/*
265180811Sstas * Accept Target I/O Entry structure, Type 2
266180811Sstas */
267180811Sstas#define ATIO2_CDBLEN	16
268181602Sraj
269180811Sstastypedef struct {
270180811Sstas	isphdr_t	at_header;
271180811Sstas	u_int32_t	at_reserved;
272181602Sraj	u_int8_t	at_lun;		/* lun or reserved */
273180811Sstas	u_int8_t	at_iid;		/* initiator */
274181602Sraj	u_int16_t	at_rxid; 	/* response ID */
275180811Sstas	u_int16_t	at_flags;
276180811Sstas	u_int16_t	at_status;	/* firmware status */
277180811Sstas	u_int8_t	at_reserved1;
278180811Sstas	u_int8_t	at_taskcodes;
279180811Sstas	u_int8_t	at_taskflags;
280180811Sstas	u_int8_t	at_execodes;
281180811Sstas	u_int8_t	at_cdb[ATIO2_CDBLEN];	/* received CDB */
282180811Sstas	u_int32_t	at_datalen;		/* allocated data len */
283181602Sraj	u_int16_t	at_scclun;	/* SCC Lun or reserved */
284180811Sstas	u_int16_t	at_reserved2[10];
285181602Sraj	u_int16_t	at_oxid;
286181602Sraj} at2_entry_t;
287180811Sstas
288180811Sstas#define	ATIO2_WWPN_OFFSET	0x2A
289180811Sstas#define	ATIO2_OXID_OFFSET	0x3E
290181602Sraj
291180811Sstas#define	ATIO2_TC_ATTR_MASK	0x7
292180811Sstas#define	ATIO2_TC_ATTR_SIMPLEQ	0
293180811Sstas#define	ATIO2_TC_ATTR_HEADOFQ	1
294180811Sstas#define	ATIO2_TC_ATTR_ORDERED	2
295181602Sraj#define	ATIO2_TC_ATTR_ACAQ	4
296180811Sstas#define	ATIO2_TC_ATTR_UNTAGGED	5
297180811Sstas
298180811Sstas/*
299180811Sstas * Continue Target I/O Entry structure
300181602Sraj * Request from driver. The response from the
301181602Sraj * ISP firmware is the same except that the last 18
302181602Sraj * bytes are overwritten by suggested sense data if
303181602Sraj * the 'autosense valid' bit is set in the status byte.
304181602Sraj */
305181602Srajtypedef struct {
306180811Sstas	isphdr_t	ct_header;
307180811Sstas	u_int16_t	ct_reserved;
308180811Sstas#define	ct_syshandle	ct_reserved	/* we use this */
309181602Sraj	u_int16_t	ct_fwhandle;	/* required by f/w */
310180811Sstas	u_int8_t	ct_lun;	/* lun */
311180811Sstas	u_int8_t	ct_iid;	/* initiator id */
312180811Sstas	u_int8_t	ct_reserved2;
313181602Sraj	u_int8_t	ct_tgt;	/* our target id */
314180811Sstas	u_int32_t	ct_flags;
315181602Sraj	u_int8_t 	ct_status;	/* isp status */
316180811Sstas	u_int8_t 	ct_scsi_status;	/* scsi status */
317181602Sraj	u_int8_t 	ct_tag_val;	/* tag value */
318180811Sstas	u_int8_t 	ct_tag_type;	/* tag type */
319180811Sstas	u_int32_t	ct_xfrlen;	/* transfer length */
320180811Sstas	u_int32_t	ct_resid;	/* residual length */
321181602Sraj	u_int16_t	ct_timeout;
322181602Sraj	u_int16_t	ct_seg_count;
323181602Sraj	ispds_t		ct_dataseg[ISP_RQDSEG];
324181602Sraj} ct_entry_t;
325181602Sraj
326181602Sraj/*
327181602Sraj * For some of the dual port SCSI adapters, port (bus #) is reported
328181602Sraj * in the MSbit of ct_iid. Bit fields are a bit too awkward here.
329181602Sraj *
330181602Sraj * Note that this does not apply to FC adapters at all which can and
331181602Sraj * do report IIDs between 129 && 255 (these represent devices that have
332180811Sstas * logged in across a SCSI fabric).
333181602Sraj */
334180811Sstas#define	GET_IID_VAL(x)		(x & 0x3f)
335181602Sraj#define	GET_BUS_VAL(x)		((x >> 7) & 0x1)
336180811Sstas#define	SET_IID_VAL(y, x)	(y | (x & 0x3f))
337180811Sstas#define	SET_BUS_VAL(y, x)	(y | ((x & 0x1) << 7))
338181602Sraj
339181602Sraj/*
340181602Sraj * ct_flags values
341180811Sstas */
342181602Sraj#define CT_TQAE		0x00000002	/* bit  1, Tagged Queue Action enable */
343181602Sraj#define CT_DATA_IN	0x00000040	/* bits 6&7, Data direction */
344180811Sstas#define CT_DATA_OUT	0x00000080	/* bits 6&7, Data direction */
345180811Sstas#define CT_NO_DATA	0x000000C0	/* bits 6&7, Data direction */
346180811Sstas#define	CT_CCINCR	0x00000100	/* bit 8, autoincrement atio count */
347180811Sstas#define CT_DATAMASK	0x000000C0	/* bits 6&7, Data direction */
348181602Sraj#define	CT_INISYNCWIDE	0x00004000	/* bit 14, Do Sync/Wide Negotiation */
349181602Sraj#define CT_NODISC	0x00008000	/* bit 15, Disconnects disabled */
350181602Sraj#define CT_DSDP		0x01000000	/* bit 24, Disable Save Data Pointers */
351181602Sraj#define CT_SENDRDP	0x04000000	/* bit 26, Send Restore Pointers msg */
352180811Sstas#define CT_SENDSTATUS	0x80000000	/* bit 31, Send SCSI status byte */
353180811Sstas
354181602Sraj/*
355181602Sraj * ct_status values
356181602Sraj * - set by the firmware when it returns the CTIO
357181602Sraj */
358181602Sraj#define CT_OK		0x01	/* completed without error */
359#define CT_ABORTED	0x02	/* aborted by host */
360#define CT_ERR		0x04	/* see sense data for error */
361#define CT_INVAL	0x06	/* request for disabled lun */
362#define CT_NOPATH	0x07	/* invalid ITL nexus */
363#define	CT_INVRXID	0x08	/* (FC only) Invalid RX_ID */
364#define	CT_DATA_OVER	0x09	/* (FC only) Data Overrun */
365#define CT_RSELTMO	0x0A	/* reselection timeout after 2 tries */
366#define CT_TIMEOUT	0x0B	/* timed out */
367#define CT_RESET	0x0E	/* SCSI Bus Reset occurred */
368#define	CT_PARITY	0x0F	/* Uncorrectable Parity Error */
369#define	CT_BUS_ERROR	0x10	/* (FC Only) DMA PCI Error */
370#define	CT_PANIC	0x13	/* Unrecoverable Error */
371#define CT_PHASE_ERROR	0x14	/* Bus phase sequence error */
372#define CT_BDR_MSG	0x17	/* Bus Device Reset msg received */
373#define	CT_DATA_UNDER	0x15	/* (FC only) Data Underrun */
374#define CT_TERMINATED	0x19	/* due to Terminate Transfer mbox cmd */
375#define	CT_PORTNOTAVAIL	0x28	/* port not available */
376#define	CT_LOGOUT	0x29	/* port logout */
377#define	CT_PORTCHANGED	0x2A	/* port changed */
378#define	CT_IDE		0x33	/* Initiator Detected Error */
379#define CT_NOACK	0x35	/* Outstanding Immed. Notify. entry */
380
381/*
382 * When the firmware returns a CTIO entry, it may overwrite the last
383 * part of the structure with sense data. This starts at offset 0x2E
384 * into the entry, which is in the middle of ct_dataseg[1]. Rather
385 * than define a new struct for this, I'm just using the sense data
386 * offset.
387 */
388#define CTIO_SENSE_OFFSET	0x2E
389
390/*
391 * Entry length in u_longs. All entries are the same size so
392 * any one will do as the numerator.
393 */
394#define UINT32_ENTRY_SIZE	(sizeof(at_entry_t)/sizeof(u_int32_t))
395
396/*
397 * QLA2100 CTIO (type 2) entry
398 */
399#define	MAXRESPLEN	26
400typedef struct {
401	isphdr_t	ct_header;
402	u_int16_t	ct_reserved;
403	u_int16_t	ct_fwhandle;	/* just to match CTIO */
404	u_int8_t	ct_lun;	/* lun */
405	u_int8_t	ct_iid;	/* initiator id */
406	u_int16_t	ct_rxid; /* response ID */
407	u_int16_t	ct_flags;
408	u_int16_t 	ct_status;	/* isp status */
409	u_int16_t	ct_timeout;
410	u_int16_t	ct_seg_count;
411	u_int32_t	ct_reloff;	/* relative offset */
412	int32_t		ct_resid;	/* residual length */
413	union {
414		/*
415		 * The three different modes that the target driver
416		 * can set the CTIO2 up as.
417		 *
418		 * The first is for sending FCP_DATA_IUs as well as
419		 * (optionally) sending a terminal SCSI status FCP_RSP_IU.
420		 *
421		 * The second is for sending SCSI sense data in an FCP_RSP_IU.
422		 * Note that no FCP_DATA_IUs will be sent.
423		 *
424		 * The third is for sending FCP_RSP_IUs as built specifically
425		 * in system memory as located by the isp_dataseg.
426		 */
427		struct {
428			u_int32_t _reserved;
429			u_int16_t _reserved2;
430			u_int16_t ct_scsi_status;
431			u_int32_t ct_xfrlen;
432			ispds_t ct_dataseg[ISP_RQDSEG_T2];
433		} m0;
434		struct {
435			u_int16_t _reserved;
436			u_int16_t _reserved2;
437			u_int16_t ct_senselen;
438			u_int16_t ct_scsi_status;
439			u_int16_t ct_resplen;
440			u_int8_t  ct_resp[MAXRESPLEN];
441		} m1;
442		struct {
443			u_int32_t _reserved;
444			u_int16_t _reserved2;
445			u_int16_t _reserved3;
446			u_int32_t ct_datalen;
447			ispds_t ct_fcp_rsp_iudata;
448		} m2;
449		/*
450		 * CTIO2 returned from F/W...
451		 */
452		struct {
453			u_int32_t _reserved[4];
454			u_int16_t ct_scsi_status;
455			u_int8_t  ct_sense[QLTM_SENSELEN];
456		} fw;
457	} rsp;
458} ct2_entry_t;
459
460/*
461 * ct_flags values for CTIO2
462 */
463#define	CT2_FLAG_MMASK	0x0003
464#define	CT2_FLAG_MODE0	0x0000
465#define	CT2_FLAG_MODE1	0x0001
466#define	CT2_FLAG_MODE2	0x0002
467#define CT2_DATA_IN	CT_DATA_IN
468#define CT2_DATA_OUT	CT_DATA_OUT
469#define CT2_NO_DATA	CT_NO_DATA
470#define CT2_DATAMASK	CT_DATAMASK
471#define	CT2_CCINCR	0x0100
472#define	CT2_FASTPOST	0x0200
473#define CT2_SENDSTATUS	0x8000
474
475/*
476 * ct_status values are (mostly) the same as that for ct_entry.
477 */
478
479/*
480 * ct_scsi_status values- the low 8 bits are the normal SCSI status
481 * we know and love. The upper 8 bits are validity markers for FCP_RSP_IU
482 * fields.
483 */
484#define	CT2_RSPLEN_VALID	0x0100
485#define	CT2_SNSLEN_VALID	0x0200
486#define	CT2_DATA_OVER		0x0400
487#define	CT2_DATA_UNDER		0x0800
488
489/*
490 * Macros for packing/unpacking the above structures
491 */
492
493#ifdef	__sparc__
494#define	ISP_SBUS_SWOZZLE(isp, src, dst, taga, tagb)	\
495	if (isp->isp_bustype == ISP_BT_SBUS) {	\
496		u_int8_t tmp = src -> taga;	\
497		dst -> taga =  dst -> tagb;	\
498		src -> tagb =  tmp;		\
499	} else { \
500		dst -> taga =  src -> taga;	\
501		dst -> tagb =  src -> taga;	\
502	}
503#else
504#define	ISP_SBUS_SWOZZLE(isp, src, dst, taga, tagb)	\
505		dst -> taga =  src -> taga;	\
506		dst -> tagb =  src -> taga
507#endif
508
509#define	MCIDF(d, s)	if ((void *) d != (void *)s) MEMCPY(d, s, QENTRY_LEN)
510
511/* This is really only for SBus cards on a sparc */
512#ifdef	__sparc__
513#define	ISP_SWIZ_ATIO(isp, vdst, vsrc)					\
514{									\
515	at_entry_t *src = (at_entry_t *) vsrc;				\
516	at_entry_t *dst = (at_entry_t *) vdst;				\
517	dst->at_header = src->at_header;				\
518	dst->at_reserved = src->at_reserved;				\
519	dst->at_handle = src->at_handle;				\
520	ISP_SBUS_SWOZZLE(isp, src, dst, at_lun, at_iid);		\
521	ISP_SBUS_SWOZZLE(isp, src, dst, at_cdblen, at_tgt);		\
522	dst->at_flags = src->at_flags;					\
523	ISP_SBUS_SWOZZLE(isp, src, dst, at_status, at_scsi_status);	\
524	ISP_SBUS_SWOZZLE(isp, src, dst, at_tag_val, at_tag_type);	\
525	MEMCPY(dst->at_cdb, src->at_cdb, ATIO_CDBLEN);			\
526	MEMCPY(dst->at_sense, src->at_sense, QLTM_SENSELEN);		\
527}
528#define	ISP_SWIZ_ATIO2(isp, vdst, vsrc)					\
529{									\
530	at2_entry_t *src = (at2_entry_t *) vsrc;			\
531	at2_entry_t *dst = (at2_entry_t *) vdst;			\
532	dst->at_reserved = src->at_reserved;				\
533	ISP_SBUS_SWOZZLE(isp, src, dst, at_lun, at_iid);		\
534	dst->at_rxid = src->at_rxid;					\
535	dst->at_flags = src->at_flags;					\
536	dst->at_status = src->at_status;				\
537	ISP_SBUS_SWOZZLE(isp, src, dst, at_reserved1, at_taskcodes);	\
538	ISP_SBUS_SWOZZLE(isp, src, dst, at_taskflags, at_execodes);	\
539	MEMCPY(dst->at_cdb, src->at_cdb, ATIO2_CDBLEN);			\
540	dst->at_datalen = src->at_datalen;				\
541	dst->at_scclun = src->at_scclun;				\
542	MEMCPY(dst->at_reserved2, src->at_reserved2, sizeof dst->at_reserved2);\
543	dst->at_oxid = src->at_oxid;					\
544}
545#define	ISP_SWIZ_CTIO(isp, vdst, vsrc)					\
546{									\
547	ct_entry_t *src = (ct_entry_t *) vsrc;				\
548	ct_entry_t *dst = (ct_entry_t *) vdst;				\
549	dst->ct_header = src->ct_header;				\
550	dst->ct_syshandle = src->ct_syshandle;				\
551	dst->ct_fwhandle = src->ct_fwhandle;				\
552	dst->ct_fwhandle = src->ct_fwhandle;				\
553	ISP_SBUS_SWOZZLE(isp, src, dst, ct_lun, ct_iid);		\
554	ISP_SBUS_SWOZZLE(isp, src, dst, ct_reserved2, ct_tgt);		\
555	dst->ct_flags = src->ct_flags;					\
556	ISP_SBUS_SWOZZLE(isp, src, dst, ct_status, ct_scsi_status);	\
557	ISP_SBUS_SWOZZLE(isp, src, dst, ct_tag_val, ct_tag_type);	\
558	dst->ct_xfrlen = src->ct_xfrlen;				\
559	dst->ct_resid = src->ct_resid;					\
560	dst->ct_timeout = src->ct_timeout;				\
561	dst->ct_seg_count = src->ct_seg_count;				\
562	MEMCPY(dst->ct_dataseg, src->ct_dataseg, sizeof (dst->ct_dataseg)); \
563}
564#define	ISP_SWIZ_CTIO2(isp, vdst, vsrc)					\
565{									\
566	ct2_entry_t *src = (ct2_entry_t *) vsrc;			\
567	ct2_entry_t *dst = (ct2_entry_t *) vdst;			\
568	dst->ct_header = src->ct_header;				\
569	dst->ct_syshandle = src->ct_syshandle;				\
570	dst->ct_fwhandle = src->ct_fwhandle;				\
571	dst->ct_fwhandle = src->ct_fwhandle;				\
572	ISP_SBUS_SWOZZLE(isp, src, dst, ct_lun, ct_iid);		\
573	dst->ct_rxid = src->ct_rxid;					\
574	dst->ct_flags = src->ct_flags;					\
575	dst->ct_status = src->ct_status;				\
576	dst->ct_timeout = src->ct_timeout;				\
577	dst->ct_seg_count = src->ct_seg_count;				\
578	dst->ct_reloff = src->ct_reloff;				\
579	dst->ct_resid = src->ct_resid;					\
580	dst->rsp = src->rsp;						\
581}
582#define	ISP_SWIZ_ENABLE_LUN(isp, vdst, vsrc)				\
583{									\
584	lun_entry_t *src = (lun_entry_t *)vsrc;				\
585	lun_entry_t *dst = (lun_entry_t *)vdst;				\
586	dst->le_header = src->le_header;				\
587	dst->le_reserved2 = src->le_reserved2;				\
588	ISP_SBUS_SWOZZLE(isp, src, dst, le_lun, le_rsvd);		\
589	ISP_SBUS_SWOZZLE(isp, src, dst, le_ops, le_tgt);		\
590	dst->le_flags = src->le_flags;					\
591	ISP_SBUS_SWOZZLE(isp, src, dst, le_status, le_reserved2);	\
592	ISP_SBUS_SWOZZLE(isp, src, dst, le_cmd_count, le_in_count);	\
593	ISP_SBUS_SWOZZLE(isp, src, dst, le_cdb6len, le_cdb7len);	\
594	dst->le_timeout = src->le_timeout;				\
595	dst->le_reserved = src->le_reserved;				\
596}
597#define	ISP_SWIZ_NOTIFY(isp, vdst, vsrc)				\
598{									\
599	in_entry_type *src = (in_entry_t *)vsrc;			\
600	in_entry_type *dst = (in_entry_t *)vdst;			\
601	dst->in_header = src->in_header;				\
602	dst->in_reserved2 = src->in_reserved2;				\
603	ISP_SBUS_SWOZZLE(isp, src, dst, in_lun, in_iid);		\
604	ISP_SBUS_SWOZZLE(isp, src, dst, in_reserved2, in_tgt);		\
605	dst->in_flags = src->in_flags;					\
606	ISP_SBUS_SWOZZLE(isp, src, dst, in_status, in_rsvd2);		\
607	ISP_SBUS_SWOZZLE(isp, src, dst, in_tag_val, in_tag_type);	\
608	dst->in_seqid = src->in_seqid;					\
609	MEMCPY(dst->in_msg, src->in_msg, IN_MSGLEN);			\
610	MEMCPY(dst->in_reserved, src->in_reserved, IN_RESERVED);	\
611	MEMCPY(dst->in_sense, src->in_sense, QLTM_SENSELEN);		\
612}
613#define	ISP_SWIZ_NOTIFY_FC(isp, vdst, vsrc)				\
614{									\
615	in_fcentry_type *src = (in_fcentry_t *)vsrc;			\
616	in_fcentry_type *dst = (in_fcentry_t *)vdst;			\
617	dst->in_header = src->in_header;				\
618	dst->in_reserved2 = src->in_reserved2;				\
619	ISP_SBUS_SWOZZLE(isp, src, dst, in_lun, in_iid);		\
620	dst->in_scclun = src->in_scclun;				\
621	dst->in_reserved2 = src->in_reserved2;				\
622	dst->in_status = src->in_status;				\
623	dst->in_task_flags = src->in_task_flags;			\
624	dst->in_seqid = src->in_seqid;					\
625}
626#define	ISP_SWIZ_NOT_ACK(isp, vdst, vsrc)				\
627{									\
628	na_entry_t *src = (na_entry_t *)vsrc;				\
629	na_entry_t *dst = (na_entry_t *)vdst;				\
630	dst->na_header = src->na_header;				\
631	dst->na_reserved = src->na_reserved;				\
632	ISP_SBUS_SWOZZLE(isp, src, dst, na_lun, na_iid);		\
633	dst->na_reserved2 = src->na_reserved2;				\
634	ISP_SBUS_SWOZZLE(isp, src, dst, na_reserved, na_tgt);		\
635	dst->na_flags = src->na_flags;					\
636	ISP_SBUS_SWOZZLE(isp, src, dst, na_status, na_event);		\
637	dst->na_seqid = src->na_seqid;					\
638	MEMCPY(dst->na_reserved3, src->na_reserved3, NA_RSVDLEN);	\
639}
640#define	ISP_SWIZ_NOT_ACK_FC(isp, vdst, vsrc)				\
641{									\
642	na_fcentry_t *src = (na_fcentry_t *)vsrc;			\
643	na_fcentry_t *dst = (na_fcentry_t *)vdst;			\
644	dst->na_header = src->na_header;				\
645	dst->na_reserved = src->na_reserved;				\
646	ISP_SBUS_SWOZZLE(isp, src, dst, na_lun, na_iid);		\
647	dst->na_scclun = src->na_scclun;				\
648	dst->na_flags = src->na_flags;					\
649	dst->na_reserved2 = src->na_reserved2;				\
650	dst->na_status = src->na_status;				\
651	dst->na_task_flags = src->na_task_flags;			\
652	dst->na_seqid = src->na_seqid;					\
653	MEMCPY(dst->na_reserved3, src->na_reserved3, NA2_RSVDLEN);	\
654}
655#else
656#define	ISP_SWIZ_ATIO(isp, d, s)	MCIDF(d, s)
657#define	ISP_SWIZ_ATIO2(isp, d, s)	MCIDF(d, s)
658#define	ISP_SWIZ_CTIO(isp, d, s)	MCIDF(d, s)
659#define	ISP_SWIZ_CTIO2(isp, d, s)	MCIDF(d, s)
660#define	ISP_SWIZ_ENABLE_LUN(isp, d, s)	MCIDF(d, s)
661#define	ISP_SWIZ_ATIO2(isp, d, s)	MCIDF(d, s)
662#define	ISP_SWIZ_CTIO2(isp, d, s)	MCIDF(d, s)
663#define	ISP_SWIZ_NOTIFY(isp, d, s)	MCIDF(d, s)
664#define	ISP_SWIZ_NOTIFY_FC(isp, d, s)	MCIDF(d, s)
665#define	ISP_SWIZ_NOT_ACK(isp, d, s)	MCIDF(d, s)
666#define	ISP_SWIZ_NOT_ACK_FC(isp, d, s)	MCIDF(d, s)
667#endif
668
669/*
670 * Debug macros
671 */
672
673#define	ISP_TDQE(isp, msg, idx, arg)	\
674    if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg)
675
676/*
677 * The functions below are target mode functions that
678 * are generally internal to the Qlogic driver.
679 */
680
681/*
682 * This function handles new response queue entry appropriate for target mode.
683 */
684int isp_target_notify(struct ispsoftc *, void *, u_int16_t *);
685
686/*
687 * Enable/Disable/Modify a logical unit.
688 * (softc, cmd, bus, tgt, lun, cmd_cnt, inotify_cnt, opaque)
689 */
690#define	DFLT_CMND_CNT	32
691#define	DFLT_INOT_CNT	4
692int isp_lun_cmd(struct ispsoftc *, int, int, int, int, int, int, u_int32_t);
693
694/*
695 * General request queue 'put' routine for target mode entries.
696 */
697int isp_target_put_entry(struct ispsoftc *isp, void *);
698
699/*
700 * General routine to put back an ATIO entry-
701 * used for replenishing f/w resource counts.
702 * The argument is a pointer to a source ATIO
703 * or ATIO2.
704 */
705int isp_target_put_atio(struct ispsoftc *, void *);
706
707/*
708 * General routine to send a final CTIO for a command- used mostly for
709 * local responses.
710 */
711int isp_endcmd(struct ispsoftc *, void *, u_int32_t, u_int16_t);
712#define	ECMD_SVALID	0x100
713
714/*
715 * Handle an asynchronous event
716 */
717
718void isp_target_async(struct ispsoftc *, int, int);
719
720#endif	/* _ISP_TARGET_H */
721