The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/isp_target.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 222eeab8bb3b79c4a7f0209bd1f08d93


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.