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