1/*-
2 *  Copyright (c) 1997-2009 by Matthew Jacob
3 *  All rights reserved.
4 *
5 *  Redistribution and use in source and binary forms, with or without
6 *  modification, are permitted provided that the following conditions
7 *  are met:
8 *
9 *  1. Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 *  2. Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *
15 *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *  SUCH DAMAGE.
26 *
27 */
28/*
29 * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
30 */
31/*
32 * Bug fixes gratefully acknowledged from:
33 *	Oded Kedem <oded@kashya.com>
34 */
35/*
36 * Include header file appropriate for platform we're building on.
37 */
38
39#ifdef	__NetBSD__
40#include <dev/ic/isp_netbsd.h>
41#endif
42#ifdef	__FreeBSD__
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD: stable/10/sys/dev/isp/isp_target.c 316173 2017-03-29 19:25:42Z mav $");
45#include <dev/isp/isp_freebsd.h>
46#endif
47#ifdef	__OpenBSD__
48#include <dev/ic/isp_openbsd.h>
49#endif
50#ifdef	__linux__
51#include "isp_linux.h"
52#endif
53
54#ifdef	ISP_TARGET_MODE
55static const char atiocope[] = "ATIO returned for LUN %x because it was in the middle of Bus Device Reset on bus %d";
56static const char atior[] = "ATIO returned for LUN %x from handle 0x%x because a Bus Reset occurred on bus %d";
57static const char rqo[] = "%s: Request Queue Overflow";
58
59static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *);
60static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *);
61static void isp_handle_abts(ispsoftc_t *, abts_t *);
62static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *);
63static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
64static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *);
65static void isp_handle_notify(ispsoftc_t *, in_fcentry_t *);
66static void isp_handle_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *);
67
68/*
69 * The Qlogic driver gets an interrupt to look at response queue entries.
70 * Some of these are status completions for initiatior mode commands, but
71 * if target mode is enabled, we get a whole wad of response queue entries
72 * to be handled here.
73 *
74 * Basically the split into 3 main groups: Lun Enable/Modification responses,
75 * SCSI Command processing, and Immediate Notification events.
76 *
77 * You start by writing a request queue entry to enable target mode (and
78 * establish some resource limitations which you can modify later).
79 * The f/w responds with a LUN ENABLE or LUN MODIFY response with
80 * the status of this action. If the enable was successful, you can expect...
81 *
82 * Response queue entries with SCSI commands encapsulate show up in an ATIO
83 * (Accept Target IO) type- sometimes with enough info to stop the command at
84 * this level. Ultimately the driver has to feed back to the f/w's request
85 * queue a sequence of CTIOs (continue target I/O) that describe data to
86 * be moved and/or status to be sent) and finally finishing with sending
87 * to the f/w's response queue an ATIO which then completes the handshake
88 * with the f/w for that command. There's a lot of variations on this theme,
89 * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel
90 * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic
91 * gist of it.
92 *
93 * The third group that can show up in the response queue are Immediate
94 * Notification events. These include things like notifications of SCSI bus
95 * resets, or Bus Device Reset messages or other messages received. This
96 * a classic oddbins area. It can get  a little weird because you then turn
97 * around and acknowledge the Immediate Notify by writing an entry onto the
98 * request queue and then the f/w turns around and gives you an acknowledgement
99 * to *your* acknowledgement on the response queue (the idea being to let
100 * the f/w tell you when the event is *really* over I guess).
101 *
102 */
103
104
105/*
106 * A new response queue entry has arrived. The interrupt service code
107 * has already swizzled it into the platform dependent from canonical form.
108 *
109 * Because of the way this driver is designed, unfortunately most of the
110 * actual synchronization work has to be done in the platform specific
111 * code- we have no synchroniation primitives in the common code.
112 */
113
114int
115isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
116{
117	union {
118		at2_entry_t	*at2iop;
119		at2e_entry_t	*at2eiop;
120		at7_entry_t	*at7iop;
121		ct2_entry_t	*ct2iop;
122		ct2e_entry_t	*ct2eiop;
123		ct7_entry_t	*ct7iop;
124		lun_entry_t	*lunenp;
125		in_fcentry_t	*inot_fcp;
126		in_fcentry_e_t	*inote_fcp;
127		in_fcentry_24xx_t *inot_24xx;
128		na_fcentry_t	*nack_fcp;
129		na_fcentry_e_t	*nacke_fcp;
130		na_fcentry_24xx_t *nack_24xx;
131		isphdr_t	*hp;
132		abts_t		*abts;
133		abts_rsp_t	*abts_rsp;
134		els_t		*els;
135		void *		*vp;
136#define	at2iop		unp.at2iop
137#define	at2eiop		unp.at2eiop
138#define	at7iop		unp.at7iop
139#define	ct2iop		unp.ct2iop
140#define	ct2eiop		unp.ct2eiop
141#define	ct7iop		unp.ct7iop
142#define	lunenp		unp.lunenp
143#define	inot_fcp	unp.inot_fcp
144#define	inote_fcp	unp.inote_fcp
145#define	inot_24xx	unp.inot_24xx
146#define	nack_fcp	unp.nack_fcp
147#define	nacke_fcp	unp.nacke_fcp
148#define	nack_24xx	unp.nack_24xx
149#define	abts		unp.abts
150#define	abts_rsp	unp.abts_rsp
151#define els		unp.els
152#define	hdrp		unp.hp
153	} unp;
154	uint8_t local[QENTRY_LEN];
155	int type, len, level, rval = 1;
156
157	type = isp_get_response_type(isp, (isphdr_t *)vptr);
158	unp.vp = vptr;
159
160	ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr);
161
162	switch (type) {
163	case RQSTYPE_ATIO:
164		isp_get_atio7(isp, at7iop, (at7_entry_t *) local);
165		at7iop = (at7_entry_t *) local;
166		/*
167		 * Check for and do something with commands whose
168		 * IULEN extends past a single queue entry.
169		 */
170		len = at7iop->at_ta_len & 0x0fff;
171		if (len > (QENTRY_LEN - 8)) {
172			len -= (QENTRY_LEN - 8);
173			isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len);
174			while (len > 0) {
175				*optrp =  ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp));
176				len -= QENTRY_LEN;
177			}
178		}
179		/*
180		 * Check for a task management function
181		 */
182		if (at7iop->at_cmnd.fcp_cmnd_task_management) {
183			isp_got_tmf_24xx(isp, at7iop);
184			break;
185		}
186		/*
187		 * Just go straight to outer layer for this one.
188		 */
189		isp_async(isp, ISPASYNC_TARGET_ACTION, local);
190		break;
191
192	case RQSTYPE_ATIO2:
193		if (ISP_CAP_2KLOGIN(isp)) {
194			isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local);
195		} else {
196			isp_get_atio2(isp, at2iop, (at2_entry_t *) local);
197		}
198		isp_handle_atio2(isp, (at2_entry_t *) local);
199		break;
200
201	case RQSTYPE_CTIO3:
202	case RQSTYPE_CTIO2:
203		if (ISP_CAP_2KLOGIN(isp)) {
204			isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local);
205		} else {
206			isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local);
207		}
208		isp_handle_ctio2(isp, (ct2_entry_t *) local);
209		break;
210
211	case RQSTYPE_CTIO7:
212		isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local);
213		isp_handle_ctio7(isp, (ct7_entry_t *) local);
214		break;
215
216	case RQSTYPE_NOTIFY:
217		if (IS_24XX(isp)) {
218			isp_get_notify_24xx(isp, inot_24xx, (in_fcentry_24xx_t *)local);
219			isp_handle_notify_24xx(isp, (in_fcentry_24xx_t *)local);
220			break;
221		}
222		if (ISP_CAP_2KLOGIN(isp))
223			isp_get_notify_fc_e(isp, inote_fcp, (in_fcentry_e_t *)local);
224		else
225			isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local);
226		isp_handle_notify(isp, (in_fcentry_t *)local);
227		break;
228
229	case RQSTYPE_NOTIFY_ACK:
230		/*
231		 * The ISP is acknowledging our acknowledgement of an
232		 * Immediate Notify entry for some asynchronous event.
233		 */
234		if (IS_24XX(isp)) {
235			isp_get_notify_ack_24xx(isp, nack_24xx, (na_fcentry_24xx_t *) local);
236			nack_24xx = (na_fcentry_24xx_t *) local;
237			if (nack_24xx->na_status != NA_OK) {
238				level = ISP_LOGINFO;
239			} else {
240				level = ISP_LOGTDEBUG1;
241			}
242			isp_prt(isp, level, "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", nack_24xx->na_status, nack_24xx->na_status_subcode, nack_24xx->na_rxid);
243		} else {
244			if (ISP_CAP_2KLOGIN(isp)) {
245				isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local);
246			} else {
247				isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local);
248			}
249			nack_fcp = (na_fcentry_t *)local;
250			if (nack_fcp->na_status != NA_OK) {
251				level = ISP_LOGINFO;
252			} else {
253				level = ISP_LOGTDEBUG1;
254			}
255			isp_prt(isp, level, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid);
256		}
257		break;
258
259	case RQSTYPE_ABTS_RCVD:
260		isp_get_abts(isp, abts, (abts_t *)local);
261		isp_handle_abts(isp, (abts_t *)local);
262		break;
263	case RQSTYPE_ABTS_RSP:
264		isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local);
265		abts_rsp = (abts_rsp_t *) local;
266		if (abts_rsp->abts_rsp_status) {
267			level = ISP_LOGINFO;
268		} else {
269			level = ISP_LOGTDEBUG0;
270		}
271		isp_prt(isp, level, "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status,
272		    abts_rsp->abts_rsp_payload.rsp.subcode1, abts_rsp->abts_rsp_payload.rsp.subcode2);
273		break;
274	default:
275		isp_prt(isp, ISP_LOGERR, "%s: unknown entry type 0x%x", __func__, type);
276		rval = 0;
277		break;
278	}
279#undef	atiop
280#undef	at2iop
281#undef	at2eiop
282#undef	at7iop
283#undef	ctiop
284#undef	ct2iop
285#undef	ct2eiop
286#undef	ct7iop
287#undef	lunenp
288#undef	inotp
289#undef	inot_fcp
290#undef	inote_fcp
291#undef	inot_24xx
292#undef	nackp
293#undef	nack_fcp
294#undef	nacke_fcp
295#undef	hack_24xx
296#undef	abts
297#undef	abts_rsp
298#undef	els
299#undef	hdrp
300	return (rval);
301}
302
303int
304isp_target_put_entry(ispsoftc_t *isp, void *ap)
305{
306	void *outp;
307	uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
308
309	outp = isp_getrqentry(isp);
310	if (outp == NULL) {
311		isp_prt(isp, ISP_LOGWARN, rqo, __func__);
312		return (-1);
313	}
314	switch (etype) {
315	case RQSTYPE_NOTIFY_ACK:
316		if (IS_24XX(isp))
317			isp_put_notify_24xx_ack(isp, (na_fcentry_24xx_t *)ap,
318			    (na_fcentry_24xx_t *)outp);
319		else if (ISP_CAP_2KLOGIN(isp))
320			isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *)ap,
321			    (na_fcentry_e_t *)outp);
322		else
323			isp_put_notify_ack_fc(isp, ap, (na_fcentry_t *)outp);
324		break;
325	case RQSTYPE_ATIO2:
326		if (ISP_CAP_2KLOGIN(isp))
327			isp_put_atio2e(isp, (at2e_entry_t *)ap,
328			    (at2e_entry_t *)outp);
329		else
330			isp_put_atio2(isp, (at2_entry_t *)ap,
331			    (at2_entry_t *)outp);
332		break;
333	case RQSTYPE_CTIO2:
334		if (ISP_CAP_2KLOGIN(isp))
335			isp_put_ctio2e(isp, (ct2e_entry_t *)ap,
336			    (ct2e_entry_t *)outp);
337		else
338			isp_put_ctio2(isp, (ct2_entry_t *)ap,
339			    (ct2_entry_t *)outp);
340		break;
341	case RQSTYPE_CTIO7:
342		isp_put_ctio7(isp, (ct7_entry_t *)ap, (ct7_entry_t *)outp);
343		break;
344	case RQSTYPE_ABTS_RSP:
345		isp_put_abts_rsp(isp, (abts_rsp_t *)ap, (abts_rsp_t *)outp);
346		break;
347	default:
348		isp_prt(isp, ISP_LOGERR, "%s: Unknown type 0x%x", __func__, etype);
349		return (-1);
350	}
351	ISP_TDQE(isp, __func__, isp->isp_reqidx, ap);
352	ISP_SYNC_REQUEST(isp);
353	return (0);
354}
355
356int
357isp_target_put_atio(ispsoftc_t *isp, void *arg)
358{
359	at2_entry_t *aep = arg;
360	union {
361		at2_entry_t _atio2;
362		at2e_entry_t _atio2e;
363	} atun;
364
365	ISP_MEMZERO(&atun, sizeof atun);
366	atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
367	atun._atio2.at_header.rqs_entry_count = 1;
368	if (ISP_CAP_SCCFW(isp)) {
369		atun._atio2.at_scclun = aep->at_scclun;
370	} else {
371		atun._atio2.at_lun = (uint8_t) aep->at_lun;
372	}
373	if (ISP_CAP_2KLOGIN(isp)) {
374		atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid;
375	} else {
376		atun._atio2.at_iid = aep->at_iid;
377	}
378	atun._atio2.at_rxid = aep->at_rxid;
379	atun._atio2.at_status = CT_OK;
380	return (isp_target_put_entry(isp, &atun));
381}
382
383/*
384 * Command completion- both for handling cases of no resources or
385 * no blackhole driver, or other cases where we have to, inline,
386 * finish the command sanely, or for normal command completion.
387 *
388 * The 'completion' code value has the scsi status byte in the low 8 bits.
389 * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have
390 * the sense key and  bits 16..23 have the ASCQ and bits 24..31 have the ASC
391 * values.
392 *
393 * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't
394 * NB: inline SCSI sense reporting. As such, we lose this information. XXX.
395 *
396 * For both parallel && fibre channel, we use the feature that does
397 * an automatic resource autoreplenish so we don't have then later do
398 * put of an atio to replenish the f/w's resource count.
399 */
400
401int
402isp_endcmd(ispsoftc_t *isp, ...)
403{
404	uint32_t code, hdl;
405	uint8_t sts;
406	union {
407		ct2_entry_t _ctio2;
408		ct2e_entry_t _ctio2e;
409		ct7_entry_t _ctio7;
410	} un;
411	va_list ap;
412	int vpidx, nphdl;
413
414	ISP_MEMZERO(&un, sizeof un);
415
416	if (IS_24XX(isp)) {
417		at7_entry_t *aep;
418		ct7_entry_t *cto = &un._ctio7;
419
420		va_start(ap, isp);
421		aep = va_arg(ap, at7_entry_t *);
422		nphdl = va_arg(ap, int);
423		/*
424		 * Note that vpidx may equal 0xff (unknown) here
425		 */
426		vpidx = va_arg(ap, int);
427		code = va_arg(ap, uint32_t);
428		hdl = va_arg(ap, uint32_t);
429		va_end(ap);
430		isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] chan %d code %x", __func__, aep->at_rxid, vpidx, code);
431
432		sts = code & 0xff;
433		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
434		cto->ct_header.rqs_entry_count = 1;
435		cto->ct_nphdl = nphdl;
436		cto->ct_rxid = aep->at_rxid;
437		cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
438		cto->ct_iid_hi = aep->at_hdr.s_id[0];
439		cto->ct_oxid = aep->at_hdr.ox_id;
440		cto->ct_scsi_status = sts;
441		cto->ct_vpidx = vpidx;
442		cto->ct_flags = CT7_NOACK;
443		if (code & ECMD_TERMINATE) {
444			cto->ct_flags |= CT7_TERMINATE;
445		} else if (code & ECMD_SVALID) {
446			cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
447			cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
448			cto->ct_senselen = min(16, MAXRESPLEN_24XX);
449			ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp));
450			cto->rsp.m1.ct_resp[0] = 0xf0;
451			cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
452			cto->rsp.m1.ct_resp[7] = 8;
453			cto->rsp.m1.ct_resp[12] = (code >> 16) & 0xff;
454			cto->rsp.m1.ct_resp[13] = (code >> 24) & 0xff;
455		} else if (code & ECMD_RVALID) {
456			cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
457			cto->ct_scsi_status |= (FCP_RSPLEN_VALID << 8);
458			cto->rsp.m1.ct_resplen = 4;
459			ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp));
460			cto->rsp.m1.ct_resp[0] = (code >> 12) & 0xf;
461			cto->rsp.m1.ct_resp[1] = (code >> 16) & 0xff;
462			cto->rsp.m1.ct_resp[2] = (code >> 24) & 0xff;
463			cto->rsp.m1.ct_resp[3] = 0;
464		} else {
465			cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
466		}
467		if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl != 0) {
468			cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
469			cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
470		}
471		cto->ct_syshandle = hdl;
472	} else {
473		at2_entry_t *aep;
474		ct2_entry_t *cto = &un._ctio2;
475
476		va_start(ap, isp);
477		aep = va_arg(ap, at2_entry_t *);
478		/* nphdl and vpidx are unused here. */
479		nphdl = va_arg(ap, int);
480		vpidx = va_arg(ap, int);
481		code = va_arg(ap, uint32_t);
482		hdl = va_arg(ap, uint32_t);
483		va_end(ap);
484
485		isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] code %x", __func__, aep->at_rxid, code);
486
487		sts = code & 0xff;
488		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
489		cto->ct_header.rqs_entry_count = 1;
490		if (ISP_CAP_SCCFW(isp) == 0) {
491			cto->ct_lun = aep->at_lun;
492		}
493		if (ISP_CAP_2KLOGIN(isp)) {
494			un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid;
495		} else {
496			cto->ct_iid = aep->at_iid;
497		}
498		cto->ct_rxid = aep->at_rxid;
499		cto->rsp.m1.ct_scsi_status = sts;
500		cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1;
501		if (hdl == 0) {
502			cto->ct_flags |= CT2_CCINCR;
503		}
504		if (aep->at_datalen) {
505			cto->ct_resid = aep->at_datalen;
506			cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
507		}
508		if (sts == SCSI_CHECK && (code & ECMD_SVALID)) {
509			cto->rsp.m1.ct_resp[0] = 0xf0;
510			cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
511			cto->rsp.m1.ct_resp[7] = 8;
512			cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
513			cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
514			cto->rsp.m1.ct_senselen = 16;
515			cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
516		}
517		cto->ct_syshandle = hdl;
518	}
519	return (isp_target_put_entry(isp, &un));
520}
521
522/*
523 * These are either broadcast events or specifically CTIO fast completion
524 */
525
526void
527isp_target_async(ispsoftc_t *isp, int bus, int event)
528{
529	isp_notify_t notify;
530
531	ISP_MEMZERO(&notify, sizeof (isp_notify_t));
532	notify.nt_hba = isp;
533	notify.nt_wwn = INI_ANY;
534	notify.nt_nphdl = NIL_HANDLE;
535	notify.nt_sid = PORT_ANY;
536	notify.nt_did = PORT_ANY;
537	notify.nt_tgt = TGT_ANY;
538	notify.nt_channel = bus;
539	notify.nt_lun = LUN_ANY;
540	notify.nt_tagval = TAG_ANY;
541	notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
542
543	switch (event) {
544	case ASYNC_LOOP_UP:
545	case ASYNC_PTPMODE:
546		isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP UP", __func__);
547		notify.nt_ncode = NT_LINK_UP;
548		isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
549		break;
550	case ASYNC_LOOP_DOWN:
551		isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP DOWN", __func__);
552		notify.nt_ncode = NT_LINK_DOWN;
553		isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
554		break;
555	case ASYNC_LIP_ERROR:
556	case ASYNC_LIP_NOS_OLS_RECV:
557	case ASYNC_LIP_OCCURRED:
558	case ASYNC_LOOP_RESET:
559		isp_prt(isp, ISP_LOGTDEBUG0, "%s: LIP RESET", __func__);
560		notify.nt_ncode = NT_LIP_RESET;
561		isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
562		break;
563	case ASYNC_BUS_RESET:
564	case ASYNC_TIMEOUT_RESET:	/* XXX: where does this come from ? */
565		isp_prt(isp, ISP_LOGTDEBUG0, "%s: BUS RESET", __func__);
566		notify.nt_ncode = NT_BUS_RESET;
567		isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
568		break;
569	case ASYNC_DEVICE_RESET:
570		isp_prt(isp, ISP_LOGTDEBUG0, "%s: DEVICE RESET", __func__);
571		notify.nt_ncode = NT_TARGET_RESET;
572		isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
573		break;
574	case ASYNC_CTIO_DONE:
575	{
576		uint8_t storage[QENTRY_LEN];
577		isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO DONE", __func__);
578		memset(storage, 0, QENTRY_LEN);
579		if (IS_24XX(isp)) {
580			ct7_entry_t *ct = (ct7_entry_t *) storage;
581			ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
582			ct->ct_nphdl = CT7_OK;
583			ct->ct_syshandle = bus;
584			ct->ct_flags = CT7_SENDSTATUS;
585		} else {
586            		/* This should also suffice for 2K login code */
587			ct2_entry_t *ct = (ct2_entry_t *) storage;
588			ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
589			ct->ct_status = CT_OK;
590			ct->ct_syshandle = bus;
591			ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST;
592		}
593		isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
594		break;
595	}
596	default:
597		isp_prt(isp, ISP_LOGERR, "%s: unknown event 0x%x", __func__, event);
598		break;
599	}
600}
601
602/*
603 * Synthesize a message from the task management flags in a FCP_CMND_IU.
604 */
605static void
606isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
607{
608	isp_notify_t notify;
609	static const char f1[] = "%s from N-port handle 0x%x lun %x seq 0x%x";
610	static const char f2[] = "unknown %s 0x%x lun %x N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
611	uint16_t seqid, nphdl;
612
613	ISP_MEMZERO(&notify, sizeof (isp_notify_t));
614	notify.nt_hba = isp;
615	notify.nt_wwn = INI_ANY;
616	if (ISP_CAP_2KLOGIN(isp)) {
617		notify.nt_nphdl = ((in_fcentry_e_t *)inp)->in_iid;
618		nphdl = ((in_fcentry_e_t *)inp)->in_iid;
619		seqid = ((in_fcentry_e_t *)inp)->in_seqid;
620	} else {
621		notify.nt_nphdl = inp->in_iid;
622		nphdl = inp->in_iid;
623		seqid = inp->in_seqid;
624	}
625	notify.nt_sid = PORT_ANY;
626	notify.nt_did = PORT_ANY;
627
628	/* nt_tgt set in outer layers */
629	if (ISP_CAP_SCCFW(isp)) {
630		notify.nt_lun = inp->in_scclun;
631	} else {
632		notify.nt_lun = inp->in_lun;
633	}
634	notify.nt_tagval = seqid;
635	notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
636	notify.nt_need_ack = 1;
637	notify.nt_lreserved = inp;
638
639	if (inp->in_status != IN_MSG_RECEIVED) {
640		isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, nphdl, inp->in_task_flags, inp->in_seqid);
641		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp);
642		return;
643	}
644
645	if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) {
646		isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", nphdl, notify.nt_lun, inp->in_seqid);
647		notify.nt_ncode = NT_ABORT_TASK_SET;
648	} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {
649		isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", nphdl, notify.nt_lun, inp->in_seqid);
650		notify.nt_ncode = NT_CLEAR_TASK_SET;
651	} else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) {
652		isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", nphdl, notify.nt_lun, inp->in_seqid);
653		notify.nt_ncode = NT_LUN_RESET;
654	} else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {
655		isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", nphdl, notify.nt_lun, inp->in_seqid);
656		notify.nt_ncode = NT_TARGET_RESET;
657	} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {
658		isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", nphdl, notify.nt_lun, inp->in_seqid);
659		notify.nt_ncode = NT_CLEAR_ACA;
660	} else {
661		isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, nphdl, inp->in_task_flags,  inp->in_seqid);
662		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp);
663		return;
664	}
665	isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
666}
667
668static void
669isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
670{
671	isp_notify_t notify;
672	static const char f1[] = "%s from PortID 0x%06x lun %x seq 0x%08x";
673	static const char f2[] = "unknown Task Flag 0x%x lun %x PortID 0x%x tag 0x%08x";
674	fcportdb_t *lp;
675	uint16_t chan;
676	uint32_t sid, did;
677
678	ISP_MEMZERO(&notify, sizeof (isp_notify_t));
679	notify.nt_hba = isp;
680	notify.nt_wwn = INI_ANY;
681	notify.nt_lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(aep->at_cmnd.fcp_cmnd_lun));
682	notify.nt_tagval = aep->at_rxid;
683	notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
684	notify.nt_lreserved = aep;
685	sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
686	did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2];
687	if (ISP_CAP_MULTI_ID(isp) && isp->isp_nchan > 1) {
688		/* Channel has to be derived from D_ID */
689		isp_find_chan_by_did(isp, did, &chan);
690		if (chan == ISP_NOCHAN) {
691			isp_prt(isp, ISP_LOGWARN,
692			    "%s: D_ID 0x%x not found on any channel",
693			    __func__, did);
694			isp_endcmd(isp, aep, NIL_HANDLE, ISP_NOCHAN,
695			    ECMD_TERMINATE, 0);
696			return;
697		}
698	} else {
699		chan = 0;
700	}
701	if (isp_find_pdb_by_portid(isp, chan, sid, &lp))
702		notify.nt_nphdl = lp->handle;
703	else
704		notify.nt_nphdl = NIL_HANDLE;
705	notify.nt_sid = sid;
706	notify.nt_did = did;
707	notify.nt_channel = chan;
708	if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_QUERY_TASK_SET) {
709		isp_prt(isp, ISP_LOGINFO, f1, "QUERY TASK SET", sid, notify.nt_lun, aep->at_rxid);
710		notify.nt_ncode = NT_QUERY_TASK_SET;
711	} else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_ABORT_TASK_SET) {
712		isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", sid, notify.nt_lun, aep->at_rxid);
713		notify.nt_ncode = NT_ABORT_TASK_SET;
714	} else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_TASK_SET) {
715		isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", sid, notify.nt_lun, aep->at_rxid);
716		notify.nt_ncode = NT_CLEAR_TASK_SET;
717	} else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_QUERY_ASYNC_EVENT) {
718		isp_prt(isp, ISP_LOGINFO, f1, "QUERY ASYNC EVENT", sid, notify.nt_lun, aep->at_rxid);
719		notify.nt_ncode = NT_QUERY_ASYNC_EVENT;
720	} else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_LUN_RESET) {
721		isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", sid, notify.nt_lun, aep->at_rxid);
722		notify.nt_ncode = NT_LUN_RESET;
723	} else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_TGT_RESET) {
724		isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", sid, notify.nt_lun, aep->at_rxid);
725		notify.nt_ncode = NT_TARGET_RESET;
726	} else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_ACA) {
727		isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", sid, notify.nt_lun, aep->at_rxid);
728		notify.nt_ncode = NT_CLEAR_ACA;
729	} else {
730		isp_prt(isp, ISP_LOGWARN, f2, aep->at_cmnd.fcp_cmnd_task_management, notify.nt_lun, sid, aep->at_rxid);
731		notify.nt_ncode = NT_UNKNOWN;
732		isp_endcmd(isp, aep, notify.nt_nphdl, chan, ECMD_RVALID | (0x4 << 12), 0);
733		return;
734	}
735	isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
736}
737
738int
739isp_notify_ack(ispsoftc_t *isp, void *arg)
740{
741	char storage[QENTRY_LEN];
742
743	/*
744	 * This is in case a Task Management Function ends up here.
745	 */
746	if (IS_24XX(isp) && ((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO) {
747		at7_entry_t *aep = arg;
748		return (isp_endcmd(isp, aep, NIL_HANDLE, 0, 0, 0));
749	}
750
751	ISP_MEMZERO(storage, QENTRY_LEN);
752	if (IS_24XX(isp)) {
753		in_fcentry_24xx_t *in = arg;
754		na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage;
755
756		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
757		na->na_header.rqs_entry_count = 1;
758		na->na_nphdl = in->in_nphdl;
759		na->na_flags = in->in_flags;
760		na->na_status = in->in_status;
761		na->na_status_subcode = in->in_status_subcode;
762		na->na_fwhandle = in->in_fwhandle;
763		na->na_rxid = in->in_rxid;
764		na->na_oxid = in->in_oxid;
765		na->na_vpidx = in->in_vpidx;
766		if (in->in_status == IN24XX_SRR_RCVD) {
767			na->na_srr_rxid = in->in_srr_rxid;
768			na->na_srr_reloff_hi = in->in_srr_reloff_hi;
769			na->na_srr_reloff_lo = in->in_srr_reloff_lo;
770			na->na_srr_iu = in->in_srr_iu;
771			/*
772			 * Whether we're accepting the SRR or rejecting
773			 * it is determined by looking at the in_reserved
774			 * field in the original notify structure.
775			 */
776			if (in->in_reserved) {
777				na->na_srr_flags = 1;
778				na->na_srr_reject_vunique = 0;
779				/* Unable to perform this command at this time. */
780				na->na_srr_reject_code = 9;
781				/* Unable to supply the requested data. */
782				na->na_srr_reject_explanation = 0x2a;
783			}
784		}
785	} else {
786		in_fcentry_t *in = arg;
787		na_fcentry_t *na = (na_fcentry_t *) storage;
788		int iid;
789
790		ISP_MEMCPY(storage, arg, sizeof (isphdr_t));
791		if (ISP_CAP_2KLOGIN(isp)) {
792			iid = ((in_fcentry_e_t *)in)->in_iid;
793			((na_fcentry_e_t *)na)->na_iid = iid;
794		} else {
795			iid = in->in_iid;
796			na->na_iid = iid;
797		}
798		na->na_task_flags = in->in_task_flags & TASK_FLAGS_RESERVED_MASK;
799		na->na_seqid = in->in_seqid;
800		na->na_status = in->in_status;
801		na->na_flags = NAFC_RCOUNT;
802		/* We do not modify resource counts for LIP resets */
803		if (in->in_status == IN_RESET)
804			na->na_flags = NAFC_RST_CLRD;
805		if (in->in_status == IN_MSG_RECEIVED) {
806			na->na_flags |= NAFC_TVALID;
807			na->na_response = 0;	/* XXX SUCCEEDED XXX */
808		}
809		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
810		na->na_header.rqs_entry_count = 1;
811		isp_prt(isp, ISP_LOGTDEBUG0, "notify ack handle %x seqid %x flags %x tflags %x response %x", iid, na->na_seqid,
812		    na->na_flags, na->na_task_flags, na->na_response);
813	}
814	return (isp_target_put_entry(isp, &storage));
815}
816
817int
818isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno)
819{
820	char storage[QENTRY_LEN];
821	uint16_t tmpw;
822	uint8_t tmpb;
823	abts_t *abts = arg;
824	abts_rsp_t *rsp = (abts_rsp_t *) storage;
825
826	if (!IS_24XX(isp)) {
827		isp_prt(isp, ISP_LOGERR, "%s: called for non-24XX card", __func__);
828		return (0);
829	}
830
831	if (abts->abts_header.rqs_entry_type != RQSTYPE_ABTS_RCVD) {
832		isp_prt(isp, ISP_LOGERR, "%s: called for non-ABTS entry (0x%x)", __func__, abts->abts_header.rqs_entry_type);
833		return (0);
834	}
835
836	ISP_MEMCPY(rsp, abts, QENTRY_LEN);
837	rsp->abts_rsp_header.rqs_entry_type = RQSTYPE_ABTS_RSP;
838
839	/*
840	 * Swap destination and source for response.
841	 */
842	rsp->abts_rsp_r_ctl = BA_ACC;
843	tmpw = rsp->abts_rsp_did_lo;
844	tmpb = rsp->abts_rsp_did_hi;
845	rsp->abts_rsp_did_lo = rsp->abts_rsp_sid_lo;
846	rsp->abts_rsp_did_hi = rsp->abts_rsp_sid_hi;
847	rsp->abts_rsp_sid_lo = tmpw;
848	rsp->abts_rsp_sid_hi = tmpb;
849
850	rsp->abts_rsp_f_ctl_hi ^= 0x80; 	/* invert Exchange Context */
851	rsp->abts_rsp_f_ctl_hi &= ~0x7f;	/* clear Sequence Initiator and other bits */
852	rsp->abts_rsp_f_ctl_hi |= 0x10;		/* abort the whole exchange */
853	rsp->abts_rsp_f_ctl_hi |= 0x8;		/* last data frame of sequence */
854	rsp->abts_rsp_f_ctl_hi |= 0x1;		/* transfer Sequence Initiative */
855	rsp->abts_rsp_f_ctl_lo = 0;
856
857	if (errno == 0) {
858		uint16_t rx_id, ox_id;
859
860		rx_id = rsp->abts_rsp_rx_id;
861		ox_id = rsp->abts_rsp_ox_id;
862		ISP_MEMZERO(&rsp->abts_rsp_payload.ba_acc, sizeof (rsp->abts_rsp_payload.ba_acc));
863                isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS of 0x%x being BA_ACC'd", rsp->abts_rsp_rxid_abts, rsp->abts_rsp_rxid_task);
864                rsp->abts_rsp_payload.ba_acc.aborted_rx_id = rx_id;
865                rsp->abts_rsp_payload.ba_acc.aborted_ox_id = ox_id;
866                rsp->abts_rsp_payload.ba_acc.high_seq_cnt = 0xffff;
867	} else {
868		ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_acc));
869		switch (errno) {
870		case ENOMEM:
871			rsp->abts_rsp_payload.ba_rjt.reason = 5;	/* Logical Unit Busy */
872			break;
873		default:
874			rsp->abts_rsp_payload.ba_rjt.reason = 9;	/* Unable to perform command request */
875			break;
876		}
877	}
878	return (isp_target_put_entry(isp, rsp));
879}
880
881static void
882isp_handle_abts(ispsoftc_t *isp, abts_t *abts)
883{
884	isp_notify_t notify, *nt = &notify;
885	fcportdb_t *lp;
886	uint16_t chan;
887	uint32_t sid, did;
888
889	did = (abts->abts_did_hi << 16) | abts->abts_did_lo;
890	sid = (abts->abts_sid_hi << 16) | abts->abts_sid_lo;
891	ISP_MEMZERO(nt, sizeof (isp_notify_t));
892
893	nt->nt_hba = isp;
894	nt->nt_did = did;
895	nt->nt_nphdl = abts->abts_nphdl;
896	nt->nt_sid = sid;
897	if (ISP_CAP_MULTI_ID(isp) && isp->isp_nchan > 1) {
898		/* Channel has to be derived from D_ID */
899		isp_find_chan_by_did(isp, did, &chan);
900		if (chan == ISP_NOCHAN) {
901			isp_prt(isp, ISP_LOGWARN,
902			    "%s: D_ID 0x%x not found on any channel",
903			    __func__, did);
904			isp_acknak_abts(isp, abts, ENXIO);
905			return;
906		}
907	} else
908		chan = 0;
909	nt->nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
910	if (isp_find_pdb_by_handle(isp, chan, abts->abts_nphdl, &lp))
911		nt->nt_wwn = lp->port_wwn;
912	else
913		nt->nt_wwn = INI_ANY;
914	nt->nt_lun = LUN_ANY;
915	nt->nt_need_ack = 1;
916	nt->nt_tagval = abts->abts_rxid_task;
917	nt->nt_tagval |= (((uint64_t) abts->abts_rxid_abts) << 32);
918	isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS from N-Port handle 0x%x"
919	    " Port 0x%06x for task 0x%x (rx_id 0x%04x ox_id 0x%04x)",
920	    abts->abts_rxid_abts, abts->abts_nphdl, sid, abts->abts_rxid_task,
921	    abts->abts_rx_id, abts->abts_ox_id);
922	nt->nt_channel = chan;
923	nt->nt_ncode = NT_ABORT_TASK;
924	nt->nt_lreserved = abts;
925	isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
926}
927
928static void
929isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
930{
931	fcportdb_t *lp;
932	int lun, iid;
933
934	if (ISP_CAP_SCCFW(isp)) {
935		lun = aep->at_scclun;
936	} else {
937		lun = aep->at_lun;
938	}
939
940	if (ISP_CAP_2KLOGIN(isp)) {
941		iid = ((at2e_entry_t *)aep)->at_iid;
942	} else {
943		iid = aep->at_iid;
944	}
945
946	/*
947	 * The firmware status (except for the QLTM_SVALID bit) indicates
948	 * why this ATIO was sent to us.
949	 *
950	 * If QLTM_SVALID is set, the firware has recommended Sense Data.
951	 *
952	 * If the DISCONNECTS DISABLED bit is set in the flags field,
953	 * we're still connected on the SCSI bus - i.e. the initiator
954	 * did not set DiscPriv in the identify message. We don't care
955	 * about this so it's ignored.
956	 */
957
958	switch (aep->at_status & ~QLTM_SVALID) {
959	case AT_PATH_INVALID:
960		/*
961		 * ATIO rejected by the firmware due to disabled lun.
962		 */
963		isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for disabled lun %x", lun);
964		break;
965	case AT_NOCAP:
966		/*
967		 * Requested Capability not available
968		 * We sent an ATIO that overflowed the firmware's
969		 * command resource count.
970		 */
971		isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for lun %x- command count overflow", lun);
972		break;
973
974	case AT_BDR_MSG:
975		/*
976		 * If we send an ATIO to the firmware to increment
977		 * its command resource count, and the firmware is
978		 * recovering from a Bus Device Reset, it returns
979		 * the ATIO with this status. We set the command
980		 * resource count in the Enable Lun entry and no
981		 * not increment it. Therefore we should never get
982		 * this status here.
983		 */
984		isp_prt(isp, ISP_LOGERR, atiocope, lun, 0);
985		break;
986
987	case AT_CDB:		/* Got a CDB */
988
989		/* Make sure we have this inititor in port database. */
990		if (!IS_2100(isp) &&
991		    (isp_find_pdb_by_handle(isp, 0, iid, &lp) == 0 ||
992		     lp->state == FC_PORTDB_STATE_ZOMBIE)) {
993		        fcparam *fcp = FCPARAM(isp, 0);
994			uint64_t wwpn =
995				(((uint64_t) aep->at_wwpn[0]) << 48) |
996				(((uint64_t) aep->at_wwpn[1]) << 32) |
997				(((uint64_t) aep->at_wwpn[2]) << 16) |
998				(((uint64_t) aep->at_wwpn[3]) <<  0);
999			isp_add_wwn_entry(isp, 0, wwpn, INI_NONE,
1000			    iid, PORT_ANY, 0);
1001			if (fcp->isp_loopstate > LOOP_LTEST_DONE)
1002				fcp->isp_loopstate = LOOP_LTEST_DONE;
1003			isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 0,
1004			    ISPASYNC_CHANGE_PDB, iid, 0x06, 0xff);
1005		}
1006
1007		/* Punt to platform specific layer. */
1008		isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
1009		break;
1010
1011	case AT_RESET:
1012		/*
1013		 * A bus reset came along an blew away this command. Why
1014		 * they do this in addition the async event code stuff,
1015		 * I dunno.
1016		 *
1017		 * Ignore it because the async event will clear things
1018		 * up for us.
1019		 */
1020		isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0);
1021		break;
1022
1023
1024	default:
1025		isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from handle %d for lun %x", aep->at_status, iid, lun);
1026		(void) isp_target_put_atio(isp, aep);
1027		break;
1028	}
1029}
1030
1031static void
1032isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
1033{
1034	void *xs;
1035	int pl = ISP_LOGTDEBUG2;
1036	char *fmsg = NULL;
1037
1038	if (ct->ct_syshandle) {
1039		xs = isp_find_xs(isp, ct->ct_syshandle);
1040		if (xs == NULL) {
1041			pl = ISP_LOGALL;
1042		}
1043	} else {
1044		xs = NULL;
1045	}
1046
1047	switch (ct->ct_status & ~QLTM_SVALID) {
1048	case CT_BUS_ERROR:
1049		isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
1050		/* FALL Through */
1051	case CT_DATA_OVER:
1052	case CT_DATA_UNDER:
1053	case CT_OK:
1054		/*
1055		 * There are generally 2 possibilities as to why we'd get
1056		 * this condition:
1057		 * 	We sent or received data.
1058		 * 	We sent status & command complete.
1059		 */
1060
1061		break;
1062
1063	case CT_BDR_MSG:
1064		/*
1065		 * Target Reset function received.
1066		 *
1067		 * The firmware generates an async mailbox interrupt to
1068		 * notify us of this and returns outstanding CTIOs with this
1069		 * status. These CTIOs are handled in that same way as
1070		 * CT_ABORTED ones, so just fall through here.
1071		 */
1072		fmsg = "TARGET RESET";
1073		/*FALLTHROUGH*/
1074	case CT_RESET:
1075		if (fmsg == NULL)
1076			fmsg = "LIP Reset";
1077		/*FALLTHROUGH*/
1078	case CT_ABORTED:
1079		/*
1080		 * When an Abort message is received the firmware goes to
1081		 * Bus Free and returns all outstanding CTIOs with the status
1082		 * set, then sends us an Immediate Notify entry.
1083		 */
1084		if (fmsg == NULL) {
1085			fmsg = "ABORT";
1086		}
1087
1088		isp_prt(isp, ISP_LOGTDEBUG0, "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
1089		break;
1090
1091	case CT_INVAL:
1092		/*
1093		 * CTIO rejected by the firmware - invalid data direction.
1094		 */
1095		isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data direction");
1096		break;
1097
1098	case CT_RSELTMO:
1099		fmsg = "failure to reconnect to initiator";
1100		/*FALLTHROUGH*/
1101	case CT_TIMEOUT:
1102		if (fmsg == NULL)
1103			fmsg = "command";
1104		isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
1105		break;
1106
1107	case CT_ERR:
1108		fmsg = "Completed with Error";
1109		/*FALLTHROUGH*/
1110	case CT_LOGOUT:
1111		if (fmsg == NULL)
1112			fmsg = "Port Logout";
1113		/*FALLTHROUGH*/
1114	case CT_PORTUNAVAIL:
1115		if (fmsg == NULL)
1116			fmsg = "Port not available";
1117		/*FALLTHROUGH*/
1118	case CT_PORTCHANGED:
1119		if (fmsg == NULL)
1120			fmsg = "Port Changed";
1121		/*FALLTHROUGH*/
1122	case CT_NOACK:
1123		if (fmsg == NULL)
1124			fmsg = "unacknowledged Immediate Notify pending";
1125		isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
1126		break;
1127
1128	case CT_INVRXID:
1129		/*
1130		 * CTIO rejected by the firmware because an invalid RX_ID.
1131		 * Just print a message.
1132		 */
1133		isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
1134		break;
1135
1136	default:
1137		isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", ct->ct_status & ~QLTM_SVALID);
1138		break;
1139	}
1140
1141	if (xs == NULL) {
1142		/*
1143		 * There may be more than one CTIO for a data transfer,
1144		 * or this may be a status CTIO we're not monitoring.
1145		 *
1146		 * The assumption is that they'll all be returned in the
1147		 * order we got them.
1148		 */
1149		if (ct->ct_syshandle == 0) {
1150			if ((ct->ct_flags & CT2_SENDSTATUS) == 0) {
1151				isp_prt(isp, pl, "intermediate CTIO completed ok");
1152			} else {
1153				isp_prt(isp, pl, "unmonitored CTIO completed ok");
1154			}
1155		} else {
1156			isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
1157		}
1158	} else {
1159		if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
1160			ISP_DMAFREE(isp, xs, ct->ct_syshandle);
1161		}
1162		if (ct->ct_flags & CT2_SENDSTATUS) {
1163			/*
1164			 * Sent status and command complete.
1165			 *
1166			 * We're now really done with this command, so we
1167			 * punt to the platform dependent layers because
1168			 * only there can we do the appropriate command
1169			 * complete thread synchronization.
1170			 */
1171			isp_prt(isp, pl, "status CTIO complete");
1172		} else {
1173			/*
1174			 * Final CTIO completed. Release DMA resources and
1175			 * notify platform dependent layers.
1176			 */
1177			isp_prt(isp, pl, "data CTIO complete");
1178		}
1179		isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
1180		/*
1181		 * The platform layer will destroy the handle if appropriate.
1182		 */
1183	}
1184}
1185
1186static void
1187isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
1188{
1189	void *xs;
1190	int pl = ISP_LOGTDEBUG2;
1191	char *fmsg = NULL;
1192
1193	if (ct->ct_syshandle) {
1194		xs = isp_find_xs(isp, ct->ct_syshandle);
1195		if (xs == NULL) {
1196			pl = ISP_LOGALL;
1197		}
1198	} else {
1199		xs = NULL;
1200	}
1201
1202	switch (ct->ct_nphdl) {
1203	case CT7_BUS_ERROR:
1204		isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
1205		/* FALL Through */
1206	case CT7_DATA_OVER:
1207	case CT7_DATA_UNDER:
1208	case CT7_OK:
1209		/*
1210		 * There are generally 2 possibilities as to why we'd get
1211		 * this condition:
1212		 * 	We sent or received data.
1213		 * 	We sent status & command complete.
1214		 */
1215
1216		break;
1217
1218	case CT7_RESET:
1219		if (fmsg == NULL) {
1220			fmsg = "LIP Reset";
1221		}
1222		/*FALLTHROUGH*/
1223	case CT7_ABORTED:
1224		/*
1225		 * When an Abort message is received the firmware goes to
1226		 * Bus Free and returns all outstanding CTIOs with the status
1227		 * set, then sends us an Immediate Notify entry.
1228		 */
1229		if (fmsg == NULL) {
1230			fmsg = "ABORT";
1231		}
1232		isp_prt(isp, ISP_LOGTDEBUG0, "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
1233		break;
1234
1235	case CT7_TIMEOUT:
1236		if (fmsg == NULL) {
1237			fmsg = "command";
1238		}
1239		isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
1240		break;
1241
1242	case CT7_ERR:
1243		fmsg = "Completed with Error";
1244		/*FALLTHROUGH*/
1245	case CT7_LOGOUT:
1246		if (fmsg == NULL) {
1247			fmsg = "Port Logout";
1248		}
1249		/*FALLTHROUGH*/
1250	case CT7_PORTUNAVAIL:
1251		if (fmsg == NULL) {
1252			fmsg = "Port not available";
1253		}
1254		/*FALLTHROUGH*/
1255	case CT7_PORTCHANGED:
1256		if (fmsg == NULL) {
1257			fmsg = "Port Changed";
1258		}
1259		isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
1260		break;
1261
1262	case CT7_INVRXID:
1263		/*
1264		 * CTIO rejected by the firmware because an invalid RX_ID.
1265		 * Just print a message.
1266		 */
1267		isp_prt(isp, ISP_LOGWARN, "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
1268		break;
1269
1270	case CT7_REASSY_ERR:
1271		isp_prt(isp, ISP_LOGWARN, "reassembly error");
1272		break;
1273
1274	case CT7_SRR:
1275		isp_prt(isp, ISP_LOGTDEBUG0, "SRR received");
1276		break;
1277
1278	default:
1279		isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", ct->ct_nphdl);
1280		break;
1281	}
1282
1283	if (xs == NULL) {
1284		/*
1285		 * There may be more than one CTIO for a data transfer,
1286		 * or this may be a status CTIO we're not monitoring.
1287		 *
1288		 * The assumption is that they'll all be returned in the
1289		 * order we got them.
1290		 */
1291		if (ct->ct_syshandle == 0) {
1292			if (ct->ct_flags & CT7_TERMINATE) {
1293				isp_prt(isp, ISP_LOGINFO, "termination of [RX_ID 0x%x] complete", ct->ct_rxid);
1294			} else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) {
1295				isp_prt(isp, pl, "intermediate CTIO completed ok");
1296			} else {
1297				isp_prt(isp, pl, "unmonitored CTIO completed ok");
1298			}
1299		} else {
1300			isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_nphdl);
1301		}
1302	} else {
1303		if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) {
1304			ISP_DMAFREE(isp, xs, ct->ct_syshandle);
1305		}
1306		if (ct->ct_flags & CT7_SENDSTATUS) {
1307			/*
1308			 * Sent status and command complete.
1309			 *
1310			 * We're now really done with this command, so we
1311			 * punt to the platform dependent layers because
1312			 * only there can we do the appropriate command
1313			 * complete thread synchronization.
1314			 */
1315			isp_prt(isp, pl, "status CTIO complete");
1316		} else {
1317			/*
1318			 * Final CTIO completed. Release DMA resources and
1319			 * notify platform dependent layers.
1320			 */
1321			isp_prt(isp, pl, "data CTIO complete");
1322		}
1323		isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
1324		/*
1325		 * The platform layer will destroy the handle if appropriate.
1326		 */
1327	}
1328}
1329
1330static void
1331isp_handle_notify(ispsoftc_t *isp, in_fcentry_t *inp)
1332{
1333	fcportdb_t *lp;
1334	uint64_t wwn;
1335	uint32_t sid;
1336	uint16_t nphdl, status;
1337	isp_notify_t notify;
1338
1339	status = inp->in_status;
1340	isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify, status=0x%x seqid=0x%x",
1341	    status, inp->in_seqid);
1342	switch (status) {
1343	case IN_MSG_RECEIVED:
1344	case IN_IDE_RECEIVED:
1345		isp_got_msg_fc(isp, inp);
1346		return;
1347	case IN_RSRC_UNAVAIL:
1348		isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs");
1349		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp);
1350		return;
1351	}
1352
1353	if (ISP_CAP_2KLOGIN(isp))
1354		nphdl = ((in_fcentry_e_t *)inp)->in_iid;
1355	else
1356		nphdl = inp->in_iid;
1357	if (isp_find_pdb_by_handle(isp, 0, nphdl, &lp)) {
1358		wwn = lp->port_wwn;
1359		sid = lp->portid;
1360	} else {
1361		wwn = INI_ANY;
1362		sid = PORT_ANY;
1363	}
1364
1365	ISP_MEMZERO(&notify, sizeof (isp_notify_t));
1366	notify.nt_hba = isp;
1367	notify.nt_wwn = wwn;
1368	notify.nt_tgt = FCPARAM(isp, 0)->isp_wwpn;
1369	notify.nt_nphdl = nphdl;
1370	notify.nt_sid = sid;
1371	notify.nt_did = PORT_ANY;
1372	if (ISP_CAP_SCCFW(isp))
1373		notify.nt_lun = inp->in_scclun;
1374	else
1375		notify.nt_lun = inp->in_lun;
1376	notify.nt_tagval = inp->in_seqid;
1377	notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
1378	notify.nt_need_ack = 1;
1379	notify.nt_channel = 0;
1380	notify.nt_lreserved = inp;
1381
1382	switch (status) {
1383	case IN_RESET:
1384		notify.nt_ncode = NT_BUS_RESET;
1385		break;
1386	case IN_PORT_LOGOUT:
1387		notify.nt_ncode = NT_LOGOUT;
1388		break;
1389	case IN_ABORT_TASK:
1390		notify.nt_ncode = NT_ABORT_TASK;
1391		break;
1392	case IN_GLOBAL_LOGO:
1393		notify.nt_ncode = NT_GLOBAL_LOGOUT;
1394		break;
1395	case IN_PORT_CHANGED:
1396		notify.nt_ncode = NT_CHANGED;
1397		break;
1398	default:
1399		isp_prt(isp, ISP_LOGINFO, "%s: unhandled status (0x%x)",
1400		    __func__, status);
1401		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp);
1402		return;
1403	}
1404	isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
1405}
1406
1407static void
1408isp_handle_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot)
1409{
1410	uint8_t chan;
1411	uint16_t nphdl, prli_options = 0;
1412	uint32_t portid;
1413	fcportdb_t *lp;
1414	char *msg = NULL;
1415	uint8_t *ptr = (uint8_t *)inot;
1416	uint64_t wwpn = INI_NONE, wwnn = INI_NONE;
1417	isp_notify_t notify;
1418	char buf[16];
1419
1420	nphdl = inot->in_nphdl;
1421	if (nphdl != NIL_HANDLE) {
1422		portid = inot->in_portid_hi << 16 | inot->in_portid_lo;
1423	} else {
1424		portid = PORT_ANY;
1425	}
1426
1427	chan = ISP_GET_VPIDX(isp, inot->in_vpidx);
1428	if (chan >= isp->isp_nchan &&
1429	    inot->in_status != IN24XX_LIP_RESET &&
1430	    inot->in_status != IN24XX_LINK_RESET &&
1431	    inot->in_status != IN24XX_LINK_FAILED) {
1432		isp_prt(isp, ISP_LOGWARN, "%s: Received INOT with status %x on VP %x",
1433		    __func__, inot->in_status, chan);
1434		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
1435		return;
1436	}
1437
1438	switch (inot->in_status) {
1439	case IN24XX_ELS_RCVD:
1440	{
1441		/*
1442		 * Note that we're just getting notification that an ELS was
1443		 * received (possibly with some associated information sent
1444		 * upstream).  This is *not* the same as being given the ELS
1445		 * frame to accept or reject.
1446		 */
1447		switch (inot->in_status_subcode) {
1448		case LOGO:
1449			msg = "LOGO";
1450			wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]);
1451			isp_del_wwn_entry(isp, chan, wwpn, nphdl, portid);
1452			break;
1453		case PRLO:
1454			msg = "PRLO";
1455			break;
1456		case PLOGI:
1457			msg = "PLOGI";
1458			wwnn = be64dec(&ptr[IN24XX_PLOGI_WWNN_OFF]);
1459			wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]);
1460			isp_add_wwn_entry(isp, chan, wwpn, wwnn,
1461			    nphdl, portid, prli_options);
1462			break;
1463		case PRLI:
1464			msg = "PRLI";
1465			prli_options = inot->in_prli_options;
1466			if (inot->in_flags & IN24XX_FLAG_PN_NN_VALID)
1467				wwnn = be64dec(&ptr[IN24XX_PRLI_WWNN_OFF]);
1468			wwpn = be64dec(&ptr[IN24XX_PRLI_WWPN_OFF]);
1469			isp_add_wwn_entry(isp, chan, wwpn, wwnn,
1470			    nphdl, portid, prli_options);
1471			break;
1472		case PDISC:
1473			msg = "PDISC";
1474			break;
1475		case ADISC:
1476			msg = "ADISC";
1477			break;
1478		default:
1479			ISP_SNPRINTF(buf, sizeof (buf), "ELS 0x%x",
1480			    inot->in_status_subcode);
1481			msg = buf;
1482			break;
1483		}
1484		if (inot->in_flags & IN24XX_FLAG_PUREX_IOCB) {
1485			isp_prt(isp, ISP_LOGERR, "%s Chan %d ELS N-port handle %x"
1486			    " PortID 0x%06x marked as needing a PUREX response",
1487			    msg, chan, nphdl, portid);
1488			break;
1489		}
1490		isp_prt(isp, ISP_LOGTDEBUG0, "%s Chan %d ELS N-port handle %x"
1491		    " PortID 0x%06x RX_ID 0x%x OX_ID 0x%x", msg, chan, nphdl,
1492		    portid, inot->in_rxid, inot->in_oxid);
1493		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
1494		break;
1495	}
1496
1497	case IN24XX_PORT_LOGOUT:
1498		msg = "PORT LOGOUT";
1499		if (isp_find_pdb_by_handle(isp, chan, nphdl, &lp))
1500			isp_del_wwn_entry(isp, chan, lp->port_wwn, nphdl, lp->portid);
1501		/* FALLTHROUGH */
1502	case IN24XX_PORT_CHANGED:
1503		if (msg == NULL)
1504			msg = "PORT CHANGED";
1505		/* FALLTHROUGH */
1506	case IN24XX_LIP_RESET:
1507		if (msg == NULL)
1508			msg = "LIP RESET";
1509		isp_prt(isp, ISP_LOGINFO, "Chan %d %s (sub-status 0x%x) for "
1510		    "N-port handle 0x%x",
1511		    chan, msg, inot->in_status_subcode, nphdl);
1512
1513		/*
1514		 * All subcodes here are irrelevant. What is relevant
1515		 * is that we need to terminate all active commands from
1516		 * this initiator (known by N-port handle).
1517		 */
1518		/* XXX IMPLEMENT XXX */
1519		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
1520		break;
1521
1522	case IN24XX_SRR_RCVD:
1523#ifdef	ISP_TARGET_MODE
1524		ISP_MEMZERO(&notify, sizeof (isp_notify_t));
1525		notify.nt_hba = isp;
1526		notify.nt_wwn = INI_ANY;
1527		notify.nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
1528		notify.nt_nphdl = nphdl;
1529		notify.nt_sid = portid;
1530		notify.nt_did = PORT_ANY;
1531		notify.nt_lun = LUN_ANY;
1532		notify.nt_tagval = inot->in_rxid;
1533		notify.nt_tagval |= ((uint64_t)inot->in_srr_rxid << 32);
1534		notify.nt_need_ack = 1;
1535		notify.nt_channel = chan;
1536		notify.nt_lreserved = inot;
1537		notify.nt_ncode = NT_SRR;
1538		isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
1539		break;
1540#else
1541		if (msg == NULL)
1542			msg = "SRR RCVD";
1543		/* FALLTHROUGH */
1544#endif
1545	case IN24XX_LINK_RESET:
1546		if (msg == NULL)
1547			msg = "LINK RESET";
1548	case IN24XX_LINK_FAILED:
1549		if (msg == NULL)
1550			msg = "LINK FAILED";
1551	default:
1552		isp_prt(isp, ISP_LOGWARN, "Chan %d %s", chan, msg);
1553		isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
1554		break;
1555	}
1556}
1557#endif
1558