xref: /dragonfly/sys/dev/disk/isp/isp_target.c (revision 1de703da)
1 /* $FreeBSD: src/sys/dev/isp/isp_target.c,v 1.5.4.10 2002/07/29 04:25:59 mjacob Exp $ */
2 /* $DragonFly: src/sys/dev/disk/isp/isp_target.c,v 1.2 2003/06/17 04:28:27 dillon Exp $ */
3 /*
4  * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
5  *
6  * Copyright (c) 1999, 2000, 2001 by Matthew Jacob
7  * All rights reserved.
8  * mjacob@feral.com
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice immediately at the beginning of the file, without modification,
15  *    this list of conditions, and the following disclaimer.
16  * 2. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Bug fixes gratefully acknowledged from:
34  *	Oded Kedem <oded@kashya.com>
35  */
36 /*
37  * Include header file appropriate for platform we're building on.
38  */
39 
40 #ifdef	__NetBSD__
41 #include <dev/ic/isp_netbsd.h>
42 #endif
43 #ifdef	__FreeBSD__
44 #include <dev/isp/isp_freebsd.h>
45 #endif
46 #ifdef	__OpenBSD__
47 #include <dev/ic/isp_openbsd.h>
48 #endif
49 #ifdef	__linux__
50 #include "isp_linux.h"
51 #endif
52 
53 #ifdef	ISP_TARGET_MODE
54 static const char atiocope[] =
55     "ATIO returned for lun %d because it was in the middle of Bus Device Reset "
56     "on bus %d";
57 static const char atior[] =
58     "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred "
59     "on bus %d";
60 
61 static void isp_got_msg(struct ispsoftc *, int, in_entry_t *);
62 static void isp_got_msg_fc(struct ispsoftc *, int, in_fcentry_t *);
63 static void isp_notify_ack(struct ispsoftc *, void *);
64 static void isp_handle_atio(struct ispsoftc *, at_entry_t *);
65 static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *);
66 static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *);
67 static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *);
68 
69 /*
70  * The Qlogic driver gets an interrupt to look at response queue entries.
71  * Some of these are status completions for initiatior mode commands, but
72  * if target mode is enabled, we get a whole wad of response queue entries
73  * to be handled here.
74  *
75  * Basically the split into 3 main groups: Lun Enable/Modification responses,
76  * SCSI Command processing, and Immediate Notification events.
77  *
78  * You start by writing a request queue entry to enable target mode (and
79  * establish some resource limitations which you can modify later).
80  * The f/w responds with a LUN ENABLE or LUN MODIFY response with
81  * the status of this action. If the enable was successful, you can expect...
82  *
83  * Response queue entries with SCSI commands encapsulate show up in an ATIO
84  * (Accept Target IO) type- sometimes with enough info to stop the command at
85  * this level. Ultimately the driver has to feed back to the f/w's request
86  * queue a sequence of CTIOs (continue target I/O) that describe data to
87  * be moved and/or status to be sent) and finally finishing with sending
88  * to the f/w's response queue an ATIO which then completes the handshake
89  * with the f/w for that command. There's a lot of variations on this theme,
90  * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel
91  * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic
92  * gist of it.
93  *
94  * The third group that can show up in the response queue are Immediate
95  * Notification events. These include things like notifications of SCSI bus
96  * resets, or Bus Device Reset messages or other messages received. This
97  * a classic oddbins area. It can get  a little weird because you then turn
98  * around and acknowledge the Immediate Notify by writing an entry onto the
99  * request queue and then the f/w turns around and gives you an acknowledgement
100  * to *your* acknowledgement on the response queue (the idea being to let
101  * the f/w tell you when the event is *really* over I guess).
102  *
103  */
104 
105 
106 /*
107  * A new response queue entry has arrived. The interrupt service code
108  * has already swizzled it into the platform dependent from canonical form.
109  *
110  * Because of the way this driver is designed, unfortunately most of the
111  * actual synchronization work has to be done in the platform specific
112  * code- we have no synchroniation primitives in the common code.
113  */
114 
115 int
116 isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp)
117 {
118 	u_int16_t status, seqid;
119 	union {
120 		at_entry_t	*atiop;
121 		at2_entry_t	*at2iop;
122 		ct_entry_t	*ctiop;
123 		ct2_entry_t	*ct2iop;
124 		lun_entry_t	*lunenp;
125 		in_entry_t	*inotp;
126 		in_fcentry_t	*inot_fcp;
127 		na_entry_t	*nackp;
128 		na_fcentry_t	*nack_fcp;
129 		isphdr_t	*hp;
130 		void *		*vp;
131 #define	atiop		unp.atiop
132 #define	at2iop		unp.at2iop
133 #define	ctiop		unp.ctiop
134 #define	ct2iop		unp.ct2iop
135 #define	lunenp		unp.lunenp
136 #define	inotp		unp.inotp
137 #define	inot_fcp	unp.inot_fcp
138 #define	nackp		unp.nackp
139 #define	nack_fcp	unp.nack_fcp
140 #define	hdrp		unp.hp
141 	} unp;
142 	u_int8_t local[QENTRY_LEN];
143 	int bus, type, rval = 1;
144 
145 	type = isp_get_response_type(isp, (isphdr_t *)vptr);
146 	unp.vp = vptr;
147 
148 	ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr);
149 
150 	switch(type) {
151 	case RQSTYPE_ATIO:
152 		isp_get_atio(isp, atiop, (at_entry_t *) local);
153 		isp_handle_atio(isp, (at_entry_t *) local);
154 		break;
155 	case RQSTYPE_CTIO:
156 		isp_get_ctio(isp, ctiop, (ct_entry_t *) local);
157 		isp_handle_ctio(isp, (ct_entry_t *) local);
158 		break;
159 	case RQSTYPE_ATIO2:
160 		isp_get_atio2(isp, at2iop, (at2_entry_t *) local);
161 		isp_handle_atio2(isp, (at2_entry_t *) local);
162 		break;
163 	case RQSTYPE_CTIO2:
164 		isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local);
165 		isp_handle_ctio2(isp, (ct2_entry_t *) local);
166 		break;
167 	case RQSTYPE_ENABLE_LUN:
168 	case RQSTYPE_MODIFY_LUN:
169 		isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local);
170 		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, local);
171 		break;
172 
173 	case RQSTYPE_NOTIFY:
174 		/*
175 		 * Either the ISP received a SCSI message it can't
176 		 * handle, or it's returning an Immed. Notify entry
177 		 * we sent. We can send Immed. Notify entries to
178 		 * increment the firmware's resource count for them
179 		 * (we set this initially in the Enable Lun entry).
180 		 */
181 		bus = 0;
182 		if (IS_FC(isp)) {
183 			isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local);
184 			inot_fcp = (in_fcentry_t *) local;
185 			status = inot_fcp->in_status;
186 			seqid = inot_fcp->in_seqid;
187 		} else {
188 			isp_get_notify(isp, inotp, (in_entry_t *)local);
189 			inotp = (in_entry_t *) local;
190 			status = inotp->in_status & 0xff;
191 			seqid = inotp->in_seqid;
192 			if (IS_DUALBUS(isp)) {
193 				bus = GET_BUS_VAL(inotp->in_iid);
194 				SET_BUS_VAL(inotp->in_iid, 0);
195 			}
196 		}
197 		isp_prt(isp, ISP_LOGTDEBUG0,
198 		    "Immediate Notify On Bus %d, status=0x%x seqid=0x%x",
199 		    bus, status, seqid);
200 
201 		/*
202 		 * ACK it right away.
203 		 */
204 		isp_notify_ack(isp, (status == IN_RESET)? NULL : local);
205 		switch (status) {
206 		case IN_RESET:
207 			(void) isp_async(isp, ISPASYNC_BUS_RESET, &bus);
208 			break;
209 		case IN_MSG_RECEIVED:
210 		case IN_IDE_RECEIVED:
211 			if (IS_FC(isp)) {
212 				isp_got_msg_fc(isp, bus, (in_fcentry_t *)local);
213 			} else {
214 				isp_got_msg(isp, bus, (in_entry_t *)local);
215 			}
216 			break;
217 		case IN_RSRC_UNAVAIL:
218 			isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs");
219 			break;
220 		case IN_PORT_LOGOUT:
221 		case IN_ABORT_TASK:
222 		case IN_PORT_CHANGED:
223 		case IN_GLOBAL_LOGO:
224 			(void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
225 			break;
226 		default:
227 			isp_prt(isp, ISP_LOGERR,
228 			    "bad status (0x%x) in isp_target_notify", status);
229 			break;
230 		}
231 		break;
232 
233 	case RQSTYPE_NOTIFY_ACK:
234 		/*
235 		 * The ISP is acknowledging our acknowledgement of an
236 		 * Immediate Notify entry for some asynchronous event.
237 		 */
238 		if (IS_FC(isp)) {
239 			isp_get_notify_ack_fc(isp, nack_fcp,
240 			    (na_fcentry_t *)local);
241 			nack_fcp = (na_fcentry_t *)local;
242 			isp_prt(isp, ISP_LOGTDEBUG1,
243 			    "Notify Ack status=0x%x seqid 0x%x",
244 			    nack_fcp->na_status, nack_fcp->na_seqid);
245 		} else {
246 			isp_get_notify_ack(isp, nackp, (na_entry_t *)local);
247 			nackp = (na_entry_t *)local;
248 			isp_prt(isp, ISP_LOGTDEBUG1,
249 			    "Notify Ack event 0x%x status=0x%x seqid 0x%x",
250 			    nackp->na_event, nackp->na_status, nackp->na_seqid);
251 		}
252 		break;
253 	default:
254 		isp_prt(isp, ISP_LOGERR,
255 		    "Unknown entry type 0x%x in isp_target_notify", type);
256 		rval = 0;
257 		break;
258 	}
259 #undef	atiop
260 #undef	at2iop
261 #undef	ctiop
262 #undef	ct2iop
263 #undef	lunenp
264 #undef	inotp
265 #undef	inot_fcp
266 #undef	nackp
267 #undef	nack_fcp
268 #undef	hdrp
269 	return (rval);
270 }
271 
272 
273 /*
274  * Toggle (on/off) target mode for bus/target/lun
275  *
276  * The caller has checked for overlap and legality.
277  *
278  * Note that not all of bus, target or lun can be paid attention to.
279  * Note also that this action will not be complete until the f/w writes
280  * response entry. The caller is responsible for synchronizing this.
281  */
282 int
283 isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun,
284     int cmd_cnt, int inot_cnt, u_int32_t opaque)
285 {
286 	lun_entry_t el;
287 	u_int16_t nxti, optr;
288 	void *outp;
289 
290 
291 	MEMZERO(&el, sizeof (el));
292 	if (IS_DUALBUS(isp)) {
293 		el.le_rsvd = (bus & 0x1) << 7;
294 	}
295 	el.le_cmd_count = cmd_cnt;
296 	el.le_in_count = inot_cnt;
297 	if (cmd == RQSTYPE_ENABLE_LUN) {
298 		if (IS_SCSI(isp)) {
299 			el.le_flags = LUN_TQAE|LUN_DISAD;
300 			el.le_cdb6len = 12;
301 			el.le_cdb7len = 12;
302 		}
303 	} else if (cmd == -RQSTYPE_ENABLE_LUN) {
304 		cmd = RQSTYPE_ENABLE_LUN;
305 		el.le_cmd_count = 0;
306 		el.le_in_count = 0;
307 	} else if (cmd == -RQSTYPE_MODIFY_LUN) {
308 		cmd = RQSTYPE_MODIFY_LUN;
309 		el.le_ops = LUN_CCDECR | LUN_INDECR;
310 	} else {
311 		el.le_ops = LUN_CCINCR | LUN_ININCR;
312 	}
313 	el.le_header.rqs_entry_type = cmd;
314 	el.le_header.rqs_entry_count = 1;
315 	el.le_reserved = opaque;
316 	if (IS_SCSI(isp)) {
317 		el.le_tgt = tgt;
318 		el.le_lun = lun;
319 	} else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
320 		el.le_lun = lun;
321 	}
322 	el.le_timeout = 2;
323 
324 	if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
325 		isp_prt(isp, ISP_LOGERR,
326 		    "Request Queue Overflow in isp_lun_cmd");
327 		return (-1);
328 	}
329 	ISP_TDQE(isp, "isp_lun_cmd", (int) optr, &el);
330 	isp_put_enable_lun(isp, &el, outp);
331 	ISP_ADD_REQUEST(isp, nxti);
332 	return (0);
333 }
334 
335 
336 int
337 isp_target_put_entry(struct ispsoftc *isp, void *ap)
338 {
339 	void *outp;
340 	u_int16_t nxti, optr;
341 	u_int8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
342 
343 	if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
344 		isp_prt(isp, ISP_LOGWARN,
345 		    "Request Queue Overflow in isp_target_put_entry");
346 		return (-1);
347 	}
348 	switch (etype) {
349 	case RQSTYPE_ATIO:
350 		isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp);
351 		break;
352 	case RQSTYPE_ATIO2:
353 		isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp);
354 		break;
355 	case RQSTYPE_CTIO:
356 		isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp);
357 		break;
358 	case RQSTYPE_CTIO2:
359 		isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp);
360 		break;
361 	default:
362 		isp_prt(isp, ISP_LOGERR,
363 		    "Unknown type 0x%x in isp_put_entry", etype);
364 		return (-1);
365 	}
366 
367 	ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap);;
368 	ISP_ADD_REQUEST(isp, nxti);
369 	return (0);
370 }
371 
372 int
373 isp_target_put_atio(struct ispsoftc *isp, void *arg)
374 {
375 	union {
376 		at_entry_t _atio;
377 		at2_entry_t _atio2;
378 	} atun;
379 
380 	MEMZERO(&atun, sizeof atun);
381 	if (IS_FC(isp)) {
382 		at2_entry_t *aep = arg;
383 		atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
384 		atun._atio2.at_header.rqs_entry_count = 1;
385 		if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
386 			atun._atio2.at_scclun = (u_int16_t) aep->at_scclun;
387 		} else {
388 			atun._atio2.at_lun = (u_int8_t) aep->at_lun;
389 		}
390 		atun._atio2.at_status = CT_OK;
391 	} else {
392 		at_entry_t *aep = arg;
393 		atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO;
394 		atun._atio.at_header.rqs_entry_count = 1;
395 		atun._atio.at_handle = aep->at_handle;
396 		atun._atio.at_iid = aep->at_iid;
397 		atun._atio.at_tgt = aep->at_tgt;
398 		atun._atio.at_lun = aep->at_lun;
399 		atun._atio.at_tag_type = aep->at_tag_type;
400 		atun._atio.at_tag_val = aep->at_tag_val;
401 		atun._atio.at_status = (aep->at_flags & AT_TQAE);
402 		atun._atio.at_status |= CT_OK;
403 	}
404 	return (isp_target_put_entry(isp, &atun));
405 }
406 
407 /*
408  * Command completion- both for handling cases of no resources or
409  * no blackhole driver, or other cases where we have to, inline,
410  * finish the command sanely, or for normal command completion.
411  *
412  * The 'completion' code value has the scsi status byte in the low 8 bits.
413  * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have
414  * the sense key and  bits 16..23 have the ASCQ and bits 24..31 have the ASC
415  * values.
416  *
417  * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't
418  * NB: inline SCSI sense reporting. As such, we lose this information. XXX.
419  *
420  * For both parallel && fibre channel, we use the feature that does
421  * an automatic resource autoreplenish so we don't have then later do
422  * put of an atio to replenish the f/w's resource count.
423  */
424 
425 int
426 isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl)
427 {
428 	int sts;
429 	union {
430 		ct_entry_t _ctio;
431 		ct2_entry_t _ctio2;
432 	} un;
433 
434 	MEMZERO(&un, sizeof un);
435 	sts = code & 0xff;
436 
437 	if (IS_FC(isp)) {
438 		at2_entry_t *aep = arg;
439 		ct2_entry_t *cto = &un._ctio2;
440 
441 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
442 		cto->ct_header.rqs_entry_count = 1;
443 		cto->ct_iid = aep->at_iid;
444 		if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
445 			cto->ct_lun = aep->at_lun;
446 		}
447 		cto->ct_rxid = aep->at_rxid;
448 		cto->rsp.m1.ct_scsi_status = sts & 0xff;
449 		cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1;
450 		if (hdl == 0) {
451 			cto->ct_flags |= CT2_CCINCR;
452 		}
453 		if (aep->at_datalen) {
454 			cto->ct_resid = aep->at_datalen;
455 			cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
456 		}
457 		if ((sts & 0xff) == SCSI_CHECK && (sts & ECMD_SVALID)) {
458 			cto->rsp.m1.ct_resp[0] = 0xf0;
459 			cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
460 			cto->rsp.m1.ct_resp[7] = 8;
461 			cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
462 			cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
463 			cto->rsp.m1.ct_senselen = 16;
464 			cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
465 		}
466 		cto->ct_syshandle = hdl;
467 	} else {
468 		at_entry_t *aep = arg;
469 		ct_entry_t *cto = &un._ctio;
470 
471 		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
472 		cto->ct_header.rqs_entry_count = 1;
473 		cto->ct_fwhandle = aep->at_handle;
474 		cto->ct_iid = aep->at_iid;
475 		cto->ct_tgt = aep->at_tgt;
476 		cto->ct_lun = aep->at_lun;
477 		cto->ct_tag_type = aep->at_tag_type;
478 		cto->ct_tag_val = aep->at_tag_val;
479 		if (aep->at_flags & AT_TQAE) {
480 			cto->ct_flags |= CT_TQAE;
481 		}
482 		cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA;
483 		if (hdl == 0) {
484 			cto->ct_flags |= CT_CCINCR;
485 		}
486 		cto->ct_scsi_status = sts;
487 		cto->ct_syshandle = hdl;
488 	}
489 	return (isp_target_put_entry(isp, &un));
490 }
491 
492 int
493 isp_target_async(struct ispsoftc *isp, int bus, int event)
494 {
495 	tmd_event_t evt;
496 	tmd_msg_t msg;
497 
498 	switch (event) {
499 	/*
500 	 * These three we handle here to propagate an effective bus reset
501 	 * upstream, but these do not require any immediate notify actions
502 	 * so we return when done.
503 	 */
504 	case ASYNC_LIP_F8:
505 	case ASYNC_LIP_OCCURRED:
506 	case ASYNC_LOOP_UP:
507 	case ASYNC_LOOP_DOWN:
508 	case ASYNC_LOOP_RESET:
509 	case ASYNC_PTPMODE:
510 		/*
511 		 * These don't require any immediate notify actions. We used
512 		 * treat them like SCSI Bus Resets, but that was just plain
513 		 * wrong. Let the normal CTIO completion report what occurred.
514 		 */
515                 return (0);
516 
517 	case ASYNC_BUS_RESET:
518 	case ASYNC_TIMEOUT_RESET:
519 		if (IS_FC(isp)) {
520 			return (0); /* we'll be getting an inotify instead */
521 		}
522 		evt.ev_bus = bus;
523 		evt.ev_event = event;
524 		(void) isp_async(isp, ISPASYNC_TARGET_EVENT, &evt);
525 		break;
526 	case ASYNC_DEVICE_RESET:
527 		/*
528 		 * Bus Device Reset resets a specific target, so
529 		 * we pass this as a synthesized message.
530 		 */
531 		MEMZERO(&msg, sizeof msg);
532 		if (IS_FC(isp)) {
533 			msg.nt_iid = FCPARAM(isp)->isp_loopid;
534 		} else {
535 			msg.nt_iid = SDPARAM(isp)->isp_initiator_id;
536 		}
537 		msg.nt_bus = bus;
538 		msg.nt_msg[0] = MSG_BUS_DEV_RESET;
539 		(void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);
540 		break;
541 	default:
542 		isp_prt(isp, ISP_LOGERR,
543 		    "isp_target_async: unknown event 0x%x", event);
544 		break;
545 	}
546 	if (isp->isp_state == ISP_RUNSTATE)
547 		isp_notify_ack(isp, NULL);
548 	return(0);
549 }
550 
551 
552 /*
553  * Process a received message.
554  * The ISP firmware can handle most messages, there are only
555  * a few that we need to deal with:
556  * - abort: clean up the current command
557  * - abort tag and clear queue
558  */
559 
560 static void
561 isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp)
562 {
563 	u_int8_t status = inp->in_status & ~QLTM_SVALID;
564 
565 	if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) {
566 		tmd_msg_t msg;
567 
568 		MEMZERO(&msg, sizeof (msg));
569 		msg.nt_bus = bus;
570 		msg.nt_iid = inp->in_iid;
571 		msg.nt_tgt = inp->in_tgt;
572 		msg.nt_lun = inp->in_lun;
573 		msg.nt_tagtype = inp->in_tag_type;
574 		msg.nt_tagval = inp->in_tag_val;
575 		MEMCPY(msg.nt_msg, inp->in_msg, IN_MSGLEN);
576 		(void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);
577 	} else {
578 		isp_prt(isp, ISP_LOGERR,
579 		    "unknown immediate notify status 0x%x", inp->in_status);
580 	}
581 }
582 
583 /*
584  * Synthesize a message from the task management flags in a FCP_CMND_IU.
585  */
586 static void
587 isp_got_msg_fc(struct ispsoftc *isp, int bus, in_fcentry_t *inp)
588 {
589 	int lun;
590 	static const char f1[] = "%s from iid %d lun %d seq 0x%x";
591 	static const char f2[] =
592 	    "unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n";
593 
594 	if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
595 		lun = inp->in_scclun;
596 	} else {
597 		lun = inp->in_lun;
598 	}
599 
600 	if (inp->in_status != IN_MSG_RECEIVED) {
601 		isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status",
602 		    inp->in_status, lun, inp->in_iid,
603 		    inp->in_task_flags,  inp->in_seqid);
604 	} else {
605 		tmd_msg_t msg;
606 
607 		MEMZERO(&msg, sizeof (msg));
608 		msg.nt_bus = bus;
609 		msg.nt_iid = inp->in_iid;
610 		msg.nt_tagval = inp->in_seqid;
611 		msg.nt_lun = lun;
612 
613 		if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) {
614 			isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK",
615 			    inp->in_iid, msg.nt_lun, inp->in_seqid);
616 			msg.nt_msg[0] = MSG_ABORT_TAG;
617 		} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {
618 			isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",
619 			    inp->in_iid, msg.nt_lun, inp->in_seqid);
620 			msg.nt_msg[0] = MSG_CLEAR_QUEUE;
621 		} else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {
622 			isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",
623 			    inp->in_iid, msg.nt_lun, inp->in_seqid);
624 			msg.nt_msg[0] = MSG_BUS_DEV_RESET;
625 		} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {
626 			isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",
627 			    inp->in_iid, msg.nt_lun, inp->in_seqid);
628 			/* ???? */
629 			msg.nt_msg[0] = MSG_REL_RECOVERY;
630 		} else if (inp->in_task_flags & TASK_FLAGS_TERMINATE_TASK) {
631 			isp_prt(isp, ISP_LOGINFO, f1, "TERMINATE TASK",
632 			    inp->in_iid, msg.nt_lun, inp->in_seqid);
633 			msg.nt_msg[0] = MSG_TERM_IO_PROC;
634 		} else {
635 			isp_prt(isp, ISP_LOGWARN, f2, "task flag",
636 			    inp->in_status, msg.nt_lun, inp->in_iid,
637 			    inp->in_task_flags,  inp->in_seqid);
638 		}
639 		if (msg.nt_msg[0]) {
640 			(void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);
641 		}
642 	}
643 }
644 
645 static void
646 isp_notify_ack(struct ispsoftc *isp, void *arg)
647 {
648 	char storage[QENTRY_LEN];
649 	u_int16_t nxti, optr;
650 	void *outp;
651 
652 	if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
653 		isp_prt(isp, ISP_LOGWARN,
654 		    "Request Queue Overflow For isp_notify_ack");
655 		return;
656 	}
657 
658 	MEMZERO(storage, QENTRY_LEN);
659 
660 	if (IS_FC(isp)) {
661 		na_fcentry_t *na = (na_fcentry_t *) storage;
662 		if (arg) {
663 			in_fcentry_t *inp = arg;
664 			MEMCPY(storage, arg, sizeof (isphdr_t));
665 			na->na_iid = inp->in_iid;
666 			if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
667 				na->na_lun = inp->in_scclun;
668 			} else {
669 				na->na_lun = inp->in_lun;
670 			}
671 			na->na_task_flags = inp->in_task_flags;
672 			na->na_seqid = inp->in_seqid;
673 			na->na_flags = NAFC_RCOUNT;
674 			na->na_status = inp->in_status;
675 			if (inp->in_status == IN_RESET) {
676 				na->na_flags |= NAFC_RST_CLRD;
677 			}
678 		} else {
679 			na->na_flags = NAFC_RST_CLRD;
680 		}
681 		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
682 		na->na_header.rqs_entry_count = 1;
683 		isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);
684 	} else {
685 		na_entry_t *na = (na_entry_t *) storage;
686 		if (arg) {
687 			in_entry_t *inp = arg;
688 			MEMCPY(storage, arg, sizeof (isphdr_t));
689 			na->na_iid = inp->in_iid;
690 			na->na_lun = inp->in_lun;
691 			na->na_tgt = inp->in_tgt;
692 			na->na_seqid = inp->in_seqid;
693 			if (inp->in_status == IN_RESET) {
694 				na->na_event = NA_RST_CLRD;
695 			}
696 		} else {
697 			na->na_event = NA_RST_CLRD;
698 		}
699 		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
700 		na->na_header.rqs_entry_count = 1;
701 		isp_put_notify_ack(isp, na, (na_entry_t *)outp);
702 	}
703 	ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
704 	ISP_ADD_REQUEST(isp, nxti);
705 }
706 
707 static void
708 isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep)
709 {
710 	int lun;
711 	lun = aep->at_lun;
712 	/*
713 	 * The firmware status (except for the QLTM_SVALID bit) indicates
714 	 * why this ATIO was sent to us.
715 	 *
716 	 * If QLTM_SVALID is set, the firware has recommended Sense Data.
717 	 *
718 	 * If the DISCONNECTS DISABLED bit is set in the flags field,
719 	 * we're still connected on the SCSI bus - i.e. the initiator
720 	 * did not set DiscPriv in the identify message. We don't care
721 	 * about this so it's ignored.
722 	 */
723 
724 	switch(aep->at_status & ~QLTM_SVALID) {
725 	case AT_PATH_INVALID:
726 		/*
727 		 * ATIO rejected by the firmware due to disabled lun.
728 		 */
729 		isp_prt(isp, ISP_LOGERR,
730 		    "rejected ATIO for disabled lun %d", lun);
731 		break;
732 	case AT_NOCAP:
733 		/*
734 		 * Requested Capability not available
735 		 * We sent an ATIO that overflowed the firmware's
736 		 * command resource count.
737 		 */
738 		isp_prt(isp, ISP_LOGERR,
739 		    "rejected ATIO for lun %d because of command count"
740 		    " overflow", lun);
741 		break;
742 
743 	case AT_BDR_MSG:
744 		/*
745 		 * If we send an ATIO to the firmware to increment
746 		 * its command resource count, and the firmware is
747 		 * recovering from a Bus Device Reset, it returns
748 		 * the ATIO with this status. We set the command
749 		 * resource count in the Enable Lun entry and do
750 		 * not increment it. Therefore we should never get
751 		 * this status here.
752 		 */
753 		isp_prt(isp, ISP_LOGERR, atiocope, lun,
754 		    GET_BUS_VAL(aep->at_iid));
755 		break;
756 
757 	case AT_CDB:		/* Got a CDB */
758 	case AT_PHASE_ERROR:	/* Bus Phase Sequence Error */
759 		/*
760 		 * Punt to platform specific layer.
761 		 */
762 		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
763 		break;
764 
765 	case AT_RESET:
766 		/*
767 		 * A bus reset came along an blew away this command. Why
768 		 * they do this in addition the async event code stuff,
769 		 * I dunno.
770 		 *
771 		 * Ignore it because the async event will clear things
772 		 * up for us.
773 		 */
774 		isp_prt(isp, ISP_LOGWARN, atior, lun,
775 		    GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid));
776 		break;
777 
778 
779 	default:
780 		isp_prt(isp, ISP_LOGERR,
781 		    "Unknown ATIO status 0x%x from initiator %d for lun %d",
782 		    aep->at_status, aep->at_iid, lun);
783 		(void) isp_target_put_atio(isp, aep);
784 		break;
785 	}
786 }
787 
788 static void
789 isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep)
790 {
791 	int lun;
792 
793 	if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
794 		lun = aep->at_scclun;
795 	} else {
796 		lun = aep->at_lun;
797 	}
798 
799 	/*
800 	 * The firmware status (except for the QLTM_SVALID bit) indicates
801 	 * why this ATIO was sent to us.
802 	 *
803 	 * If QLTM_SVALID is set, the firware has recommended Sense Data.
804 	 *
805 	 * If the DISCONNECTS DISABLED bit is set in the flags field,
806 	 * we're still connected on the SCSI bus - i.e. the initiator
807 	 * did not set DiscPriv in the identify message. We don't care
808 	 * about this so it's ignored.
809 	 */
810 
811 	switch(aep->at_status & ~QLTM_SVALID) {
812 	case AT_PATH_INVALID:
813 		/*
814 		 * ATIO rejected by the firmware due to disabled lun.
815 		 */
816 		isp_prt(isp, ISP_LOGERR,
817 		    "rejected ATIO2 for disabled lun %d", lun);
818 		break;
819 	case AT_NOCAP:
820 		/*
821 		 * Requested Capability not available
822 		 * We sent an ATIO that overflowed the firmware's
823 		 * command resource count.
824 		 */
825 		isp_prt(isp, ISP_LOGERR,
826 		    "rejected ATIO2 for lun %d- command count overflow", lun);
827 		break;
828 
829 	case AT_BDR_MSG:
830 		/*
831 		 * If we send an ATIO to the firmware to increment
832 		 * its command resource count, and the firmware is
833 		 * recovering from a Bus Device Reset, it returns
834 		 * the ATIO with this status. We set the command
835 		 * resource count in the Enable Lun entry and no
836 		 * not increment it. Therefore we should never get
837 		 * this status here.
838 		 */
839 		isp_prt(isp, ISP_LOGERR, atiocope, lun, 0);
840 		break;
841 
842 	case AT_CDB:		/* Got a CDB */
843 		/*
844 		 * Punt to platform specific layer.
845 		 */
846 		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
847 		break;
848 
849 	case AT_RESET:
850 		/*
851 		 * A bus reset came along an blew away this command. Why
852 		 * they do this in addition the async event code stuff,
853 		 * I dunno.
854 		 *
855 		 * Ignore it because the async event will clear things
856 		 * up for us.
857 		 */
858 		isp_prt(isp, ISP_LOGERR, atior, lun, aep->at_iid, 0);
859 		break;
860 
861 
862 	default:
863 		isp_prt(isp, ISP_LOGERR,
864 		    "Unknown ATIO2 status 0x%x from initiator %d for lun %d",
865 		    aep->at_status, aep->at_iid, lun);
866 		(void) isp_target_put_atio(isp, aep);
867 		break;
868 	}
869 }
870 
871 static void
872 isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct)
873 {
874 	void *xs;
875 	int pl = ISP_LOGTDEBUG2;
876 	char *fmsg = NULL;
877 
878 	if (ct->ct_syshandle) {
879 		xs = isp_find_xs(isp, ct->ct_syshandle);
880 		if (xs == NULL)
881 			pl = ISP_LOGALL;
882 	} else {
883 		xs = NULL;
884 	}
885 
886 	switch(ct->ct_status & ~QLTM_SVALID) {
887 	case CT_OK:
888 		/*
889 		 * There are generally 3 possibilities as to why we'd get
890 		 * this condition:
891 		 * 	We disconnected after receiving a CDB.
892 		 * 	We sent or received data.
893 		 * 	We sent status & command complete.
894 		 */
895 
896 		if (ct->ct_flags & CT_SENDSTATUS) {
897 			break;
898 		} else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) {
899 			/*
900 			 * Nothing to do in this case.
901 			 */
902 			isp_prt(isp, pl, "CTIO- iid %d disconnected OK",
903 			    ct->ct_iid);
904 			return;
905 		}
906 		break;
907 
908 	case CT_BDR_MSG:
909 		/*
910 		 * Bus Device Reset message received or the SCSI Bus has
911 		 * been Reset; the firmware has gone to Bus Free.
912 		 *
913 		 * The firmware generates an async mailbox interupt to
914 		 * notify us of this and returns outstanding CTIOs with this
915 		 * status. These CTIOs are handled in that same way as
916 		 * CT_ABORTED ones, so just fall through here.
917 		 */
918 		fmsg = "Bus Device Reset";
919 		/*FALLTHROUGH*/
920 	case CT_RESET:
921 		if (fmsg == NULL)
922 			fmsg = "Bus Reset";
923 		/*FALLTHROUGH*/
924 	case CT_ABORTED:
925 		/*
926 		 * When an Abort message is received the firmware goes to
927 		 * Bus Free and returns all outstanding CTIOs with the status
928 		 * set, then sends us an Immediate Notify entry.
929 		 */
930 		if (fmsg == NULL)
931 			fmsg = "ABORT TAG message sent by Initiator";
932 
933 		isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg);
934 		break;
935 
936 	case CT_INVAL:
937 		/*
938 		 * CTIO rejected by the firmware due to disabled lun.
939 		 * "Cannot Happen".
940 		 */
941 		isp_prt(isp, ISP_LOGERR,
942 		    "Firmware rejected CTIO for disabled lun %d",
943 		    ct->ct_lun);
944 		break;
945 
946 	case CT_NOPATH:
947 		/*
948 		 * CTIO rejected by the firmware due "no path for the
949 		 * nondisconnecting nexus specified". This means that
950 		 * we tried to access the bus while a non-disconnecting
951 		 * command is in process.
952 		 */
953 		isp_prt(isp, ISP_LOGERR,
954 		    "Firmware rejected CTIO for bad nexus %d/%d/%d",
955 		    ct->ct_iid, ct->ct_tgt, ct->ct_lun);
956 		break;
957 
958 	case CT_RSELTMO:
959 		fmsg = "Reselection";
960 		/*FALLTHROUGH*/
961 	case CT_TIMEOUT:
962 		if (fmsg == NULL)
963 			fmsg = "Command";
964 		isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
965 		break;
966 
967 	case	CT_PANIC:
968 		if (fmsg == NULL)
969 			fmsg = "Unrecoverable Error";
970 		/*FALLTHROUGH*/
971 	case CT_ERR:
972 		if (fmsg == NULL)
973 			fmsg = "Completed with Error";
974 		/*FALLTHROUGH*/
975 	case CT_PHASE_ERROR:
976 		if (fmsg == NULL)
977 			fmsg = "Phase Sequence Error";
978 		/*FALLTHROUGH*/
979 	case CT_TERMINATED:
980 		if (fmsg == NULL)
981 			fmsg = "terminated by TERMINATE TRANSFER";
982 		/*FALLTHROUGH*/
983 	case CT_NOACK:
984 		if (fmsg == NULL)
985 			fmsg = "unacknowledged Immediate Notify pending";
986 		isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
987 		break;
988 	default:
989 		isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x",
990 		    ct->ct_status & ~QLTM_SVALID);
991 		break;
992 	}
993 
994 	if (xs == NULL) {
995 		/*
996 		 * There may be more than one CTIO for a data transfer,
997 		 * or this may be a status CTIO we're not monitoring.
998 		 *
999 		 * The assumption is that they'll all be returned in the
1000 		 * order we got them.
1001 		 */
1002 		if (ct->ct_syshandle == 0) {
1003 			if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
1004 				isp_prt(isp, pl,
1005 				    "intermediate CTIO completed ok");
1006 			} else {
1007 				isp_prt(isp, pl,
1008 				    "unmonitored CTIO completed ok");
1009 			}
1010 		} else {
1011 			isp_prt(isp, pl,
1012 			    "NO xs for CTIO (handle 0x%x) status 0x%x",
1013 			    ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
1014 		}
1015 	} else {
1016 		/*
1017 		 * Final CTIO completed. Release DMA resources and
1018 		 * notify platform dependent layers.
1019 		 */
1020 		if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
1021 			ISP_DMAFREE(isp, xs, ct->ct_syshandle);
1022 		}
1023 		isp_prt(isp, pl, "final CTIO complete");
1024 		/*
1025 		 * The platform layer will destroy the handle if appropriate.
1026 		 */
1027 		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
1028 	}
1029 }
1030 
1031 static void
1032 isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct)
1033 {
1034 	XS_T *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 	} else {
1043 		xs = NULL;
1044 	}
1045 
1046 	switch(ct->ct_status & ~QLTM_SVALID) {
1047 	case CT_BUS_ERROR:
1048 		isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
1049 		/* FALL Through */
1050 	case CT_DATA_OVER:
1051 	case CT_DATA_UNDER:
1052 	case CT_OK:
1053 		/*
1054 		 * There are generally 2 possibilities as to why we'd get
1055 		 * this condition:
1056 		 * 	We sent or received data.
1057 		 * 	We sent status & command complete.
1058 		 */
1059 
1060 		break;
1061 
1062 	case CT_BDR_MSG:
1063 		/*
1064 		 * Target Reset function received.
1065 		 *
1066 		 * The firmware generates an async mailbox interupt to
1067 		 * notify us of this and returns outstanding CTIOs with this
1068 		 * status. These CTIOs are handled in that same way as
1069 		 * CT_ABORTED ones, so just fall through here.
1070 		 */
1071 		fmsg = "TARGET RESET Task Management Function Received";
1072 		/*FALLTHROUGH*/
1073 	case CT_RESET:
1074 		if (fmsg == NULL)
1075 			fmsg = "LIP Reset";
1076 		/*FALLTHROUGH*/
1077 	case CT_ABORTED:
1078 		/*
1079 		 * When an Abort message is received the firmware goes to
1080 		 * Bus Free and returns all outstanding CTIOs with the status
1081 		 * set, then sends us an Immediate Notify entry.
1082 		 */
1083 		if (fmsg == NULL)
1084 			fmsg = "ABORT Task Management Function Received";
1085 
1086 		isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg);
1087 		break;
1088 
1089 	case CT_INVAL:
1090 		/*
1091 		 * CTIO rejected by the firmware - invalid data direction.
1092 		 */
1093 		isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data directiond");
1094 		break;
1095 
1096 	case CT_RSELTMO:
1097 		fmsg = "failure to reconnect to initiator";
1098 		/*FALLTHROUGH*/
1099 	case CT_TIMEOUT:
1100 		if (fmsg == NULL)
1101 			fmsg = "command";
1102 		isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
1103 		break;
1104 
1105 	case CT_ERR:
1106 		fmsg = "Completed with Error";
1107 		/*FALLTHROUGH*/
1108 	case CT_LOGOUT:
1109 		if (fmsg == NULL)
1110 			fmsg = "Port Logout";
1111 		/*FALLTHROUGH*/
1112 	case CT_PORTNOTAVAIL:
1113 		if (fmsg == NULL)
1114 			fmsg = "Port not available";
1115 	case CT_PORTCHANGED:
1116 		if (fmsg == NULL)
1117 			fmsg = "Port Changed";
1118 	case CT_NOACK:
1119 		if (fmsg == NULL)
1120 			fmsg = "unacknowledged Immediate Notify pending";
1121 		isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
1122 		break;
1123 
1124 	case CT_INVRXID:
1125 		/*
1126 		 * CTIO rejected by the firmware because an invalid RX_ID.
1127 		 * Just print a message.
1128 		 */
1129 		isp_prt(isp, ISP_LOGERR,
1130 		    "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
1131 		break;
1132 
1133 	default:
1134 		isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x",
1135 		    ct->ct_status & ~QLTM_SVALID);
1136 		break;
1137 	}
1138 
1139 	if (xs == NULL) {
1140 		/*
1141 		 * There may be more than one CTIO for a data transfer,
1142 		 * or this may be a status CTIO we're not monitoring.
1143 		 *
1144 		 * The assumption is that they'll all be returned in the
1145 		 * order we got them.
1146 		 */
1147 		if (ct->ct_syshandle == 0) {
1148 			if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
1149 				isp_prt(isp, pl,
1150 				    "intermediate CTIO completed ok");
1151 			} else {
1152 				isp_prt(isp, pl,
1153 				    "unmonitored CTIO completed ok");
1154 			}
1155 		} else {
1156 			isp_prt(isp, pl,
1157 			    "NO xs for CTIO (handle 0x%x) status 0x%x",
1158 			    ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
1159 		}
1160 	} else {
1161 		if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
1162 			ISP_DMAFREE(isp, xs, ct->ct_syshandle);
1163 		}
1164 		if (ct->ct_flags & CT_SENDSTATUS) {
1165 			/*
1166 			 * Sent status and command complete.
1167 			 *
1168 			 * We're now really done with this command, so we
1169 			 * punt to the platform dependent layers because
1170 			 * only there can we do the appropriate command
1171 			 * complete thread synchronization.
1172 			 */
1173 			isp_prt(isp, pl, "status CTIO complete");
1174 		} else {
1175 			/*
1176 			 * Final CTIO completed. Release DMA resources and
1177 			 * notify platform dependent layers.
1178 			 */
1179 			isp_prt(isp, pl, "data CTIO complete");
1180 		}
1181 		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
1182 		/*
1183 		 * The platform layer will destroy the handle if appropriate.
1184 		 */
1185 	}
1186 }
1187 #endif
1188