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.37 2021/12/12 13:05:14 andvar Exp $ */
    2 /*-
    3  *  Copyright (c) 1997-2008 by Matthew Jacob
    4  *  All rights reserved.
    5  * 
    6  *  Redistribution and use in source and binary forms, with or without
    7  *  modification, are permitted provided that the following conditions
    8  *  are met:
    9  * 
   10  *  1. Redistributions of source code must retain the above copyright
   11  *     notice, this list of conditions and the following disclaimer.
   12  *  2. Redistributions in binary form must reproduce the above copyright
   13  *     notice, this list of conditions and the following disclaimer in the
   14  *     documentation and/or other materials provided with the distribution.
   15  * 
   16  *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   20  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  *  SUCH DAMAGE.
   27  * 
   28  * 
   29  *  Alternatively, this software may be distributed under the terms of the
   30  *  the GNU Public License ("GPL") with platforms where the prevalant license
   31  *  is the GNU Public License:
   32  * 
   33  *   This program is free software; you can redistribute it and/or modify
   34  *   it under the terms of The Version 2 GNU General Public License as published
   35  *   by the Free Software Foundation.
   36  * 
   37  *   This program is distributed in the hope that it will be useful,
   38  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   39  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40  *   GNU General Public License for more details.
   41  *  
   42  *   You should have received a copy of the GNU General Public License
   43  *   along with this program; if not, write to the Free Software
   44  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   45  * 
   46  * 
   47  *  Matthew Jacob
   48  *  Feral Software
   49  *  421 Laurel Avenue
   50  *  Menlo Park, CA 94025
   51  *  USA
   52  * 
   53  *  gplbsd at feral com
   54  */
   55 /*
   56  * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
   57  */
   58 /*
   59  * Bug fixes gratefully acknowledged from:
   60  *      Oded Kedem <oded@kashya.com>
   61  */
   62 /*
   63  * Include header file appropriate for platform we're building on.
   64  */
   65 
   66 #ifdef  __NetBSD__
   67 #include <sys/cdefs.h> 
   68 __KERNEL_RCSID(0, "$NetBSD: isp_target.c,v 1.37 2021/12/12 13:05:14 andvar Exp $");
   69 #include <dev/ic/isp_netbsd.h>
   70 #endif
   71 #ifdef  __FreeBSD__
   72 #include <sys/cdefs.h>
   73 __FBSDID("$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[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset on bus %d";
   85 static const char atior[] = "ATIO returned on for lun %d on from loopid %d because a Bus Reset occurred on bus %d";
   86 static const char rqo[] = "%s: Request Queue Overflow";
   87 
   88 static void isp_got_msg(ispsoftc_t *, in_entry_t *);
   89 static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *);
   90 static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *);
   91 static void isp_handle_atio(ispsoftc_t *, at_entry_t *);
   92 static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *);
   93 static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *);
   94 static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
   95 static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *);
   96 static void isp_handle_24xx_inotify(ispsoftc_t *, in_fcentry_24xx_t *);
   97 
   98 /*
   99  * The Qlogic driver gets an interrupt to look at response queue entries.
  100  * Some of these are status completions for initiator mode commands, but
  101  * if target mode is enabled, we get a whole wad of response queue entries
  102  * to be handled here.
  103  *
  104  * Basically the split into 3 main groups: Lun Enable/Modification responses,
  105  * SCSI Command processing, and Immediate Notification events.
  106  *
  107  * You start by writing a request queue entry to enable target mode (and
  108  * establish some resource limitations which you can modify later).
  109  * The f/w responds with a LUN ENABLE or LUN MODIFY response with
  110  * the status of this action. If the enable was successful, you can expect...
  111  *
  112  * Response queue entries with SCSI commands encapsulate show up in an ATIO
  113  * (Accept Target IO) type- sometimes with enough info to stop the command at
  114  * this level. Ultimately the driver has to feed back to the f/w's request
  115  * queue a sequence of CTIOs (continue target I/O) that describe data to
  116  * be moved and/or status to be sent) and finally finishing with sending
  117  * to the f/w's response queue an ATIO which then completes the handshake
  118  * with the f/w for that command. There's a lot of variations on this theme,
  119  * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel
  120  * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic
  121  * gist of it.
  122  *
  123  * The third group that can show up in the response queue are Immediate
  124  * Notification events. These include things like notifications of SCSI bus
  125  * resets, or Bus Device Reset messages or other messages received. This
  126  * a classic oddbins area. It can get a little weird because you then turn
  127  * around and acknowledge the Immediate Notify by writing an entry onto the
  128  * request queue and then the f/w turns around and gives you an acknowledgement
  129  * to *your* acknowledgement on the response queue (the idea being to let
  130  * the f/w tell you when the event is *really* over I guess).
  131  *
  132  */
  133 
  134 
  135 /*
  136  * A new response queue entry has arrived. The interrupt service code
  137  * has already swizzled it into the platform dependent from canonical form.
  138  *
  139  * Because of the way this driver is designed, unfortunately most of the
  140  * actual synchronization work has to be done in the platform specific
  141  * code- we have no synchronization primitives in the common code.
  142  */
  143 
  144 int
  145 isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
  146 {
  147         uint16_t status;
  148         uint32_t seqid;
  149         union {
  150                 at_entry_t      *atiop;
  151                 at2_entry_t     *at2iop;
  152                 at2e_entry_t    *at2eiop;
  153                 at7_entry_t     *at7iop;
  154                 ct_entry_t      *ctiop;
  155                 ct2_entry_t     *ct2iop;
  156                 ct2e_entry_t    *ct2eiop;
  157                 ct7_entry_t     *ct7iop;
  158                 lun_entry_t     *lunenp;
  159                 in_entry_t      *inotp;
  160                 in_fcentry_t    *inot_fcp;
  161                 in_fcentry_e_t  *inote_fcp;
  162                 in_fcentry_24xx_t *inot_24xx;
  163                 na_entry_t      *nackp;
  164                 na_fcentry_t    *nack_fcp;
  165                 na_fcentry_e_t  *nacke_fcp;
  166                 na_fcentry_24xx_t *nack_24xx;
  167                 isphdr_t        *hp;
  168                 abts_t          *abts;
  169                 abts_rsp_t      *abts_rsp;
  170                 els_t           *els;
  171                 void *          *vp;
  172 #define atiop           unp.atiop
  173 #define at2iop          unp.at2iop
  174 #define at2eiop         unp.at2eiop
  175 #define at7iop          unp.at7iop
  176 #define ctiop           unp.ctiop
  177 #define ct2iop          unp.ct2iop
  178 #define ct2eiop         unp.ct2eiop
  179 #define ct7iop          unp.ct7iop
  180 #define lunenp          unp.lunenp
  181 #define inotp           unp.inotp
  182 #define inot_fcp        unp.inot_fcp
  183 #define inote_fcp       unp.inote_fcp
  184 #define inot_24xx       unp.inot_24xx
  185 #define nackp           unp.nackp
  186 #define nack_fcp        unp.nack_fcp
  187 #define nacke_fcp       unp.nacke_fcp
  188 #define nack_24xx       unp.nack_24xx
  189 #define abts            unp.abts
  190 #define abts_rsp        unp.abts_rsp
  191 #define els             unp.els
  192 #define hdrp            unp.hp
  193         } unp;
  194         uint8_t local[QENTRY_LEN];
  195         uint16_t iid;
  196         int bus, type, level, rval = 1;
  197         isp_notify_t notify;
  198 
  199         type = isp_get_response_type(isp, (isphdr_t *)vptr);
  200         unp.vp = vptr;
  201 
  202         ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr);
  203 
  204         switch (type) {
  205         case RQSTYPE_ATIO:
  206                 if (IS_24XX(isp)) {
  207                         int len;
  208 
  209                         isp_get_atio7(isp, at7iop, (at7_entry_t *) local);
  210                         at7iop = (at7_entry_t *) local;
  211                         /*
  212                          * Check for and do something with commands whose
  213                          * IULEN extends past a single queue entry.
  214                          */
  215                         len = at7iop->at_ta_len & 0xfffff;
  216                         if (len > (QENTRY_LEN - 8)) {
  217                                 len -= (QENTRY_LEN - 8);
  218                                 isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len);
  219                                 while (len > 0) {
  220                                         *optrp =  ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp));
  221                                         len -= QENTRY_LEN;
  222                                 }
  223                         }
  224                         /*
  225                          * Check for a task management function
  226                          */
  227                         if (at7iop->at_cmnd.fcp_cmnd_task_management) {
  228                                 isp_got_tmf_24xx(isp, at7iop);
  229                                 break;
  230                         }
  231                         /*
  232                          * Just go straight to outer layer for this one.
  233                          */
  234                         isp_async(isp, ISPASYNC_TARGET_ACTION, local);
  235                 } else {
  236                         isp_get_atio(isp, atiop, (at_entry_t *) local);
  237                         isp_handle_atio(isp, (at_entry_t *) local);
  238                 }
  239                 break;
  240 
  241         case RQSTYPE_CTIO:
  242                 isp_get_ctio(isp, ctiop, (ct_entry_t *) local);
  243                 isp_handle_ctio(isp, (ct_entry_t *) local);
  244                 break;
  245 
  246         case RQSTYPE_ATIO2:
  247                 if (ISP_CAP_2KLOGIN(isp)) {
  248                         isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local);
  249                 } else {
  250                         isp_get_atio2(isp, at2iop, (at2_entry_t *) local);
  251                 }
  252                 isp_handle_atio2(isp, (at2_entry_t *) local);
  253                 break;
  254 
  255         case RQSTYPE_CTIO3:
  256         case RQSTYPE_CTIO2:
  257                 if (ISP_CAP_2KLOGIN(isp)) {
  258                         isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local);
  259                 } else {
  260                         isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local);
  261                 }
  262                 isp_handle_ctio2(isp, (ct2_entry_t *) local);
  263                 break;
  264 
  265         case RQSTYPE_CTIO7:
  266                 isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local);
  267                 isp_handle_ctio7(isp, (ct7_entry_t *) local);
  268                 break;
  269 
  270         case RQSTYPE_ENABLE_LUN:
  271         case RQSTYPE_MODIFY_LUN:
  272                 isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local);
  273                 isp_async(isp, ISPASYNC_TARGET_ACTION, local);
  274                 break;
  275 
  276         case RQSTYPE_NOTIFY:
  277                 bus = 0;
  278                 if (IS_24XX(isp)) {
  279                         isp_get_notify_24xx(isp, inot_24xx, (in_fcentry_24xx_t *)local);
  280                         inot_24xx = (in_fcentry_24xx_t *) local;
  281                         isp_handle_24xx_inotify(isp, inot_24xx);
  282                         break;
  283                 }
  284                 if (IS_FC(isp)) {
  285                         if (ISP_CAP_2KLOGIN(isp)) {
  286                                 in_fcentry_e_t *ecp = (in_fcentry_e_t *)local;
  287                                 isp_get_notify_fc_e(isp, inote_fcp, ecp);
  288                                 iid = ecp->in_iid;
  289                                 status = ecp->in_status;
  290                                 seqid = ecp->in_seqid;
  291                         } else {
  292                                 in_fcentry_t *fcp = (in_fcentry_t *)local;
  293                                 isp_get_notify_fc(isp, inot_fcp, fcp);
  294                                 iid = fcp->in_iid;
  295                                 status = fcp->in_status;
  296                                 seqid = fcp->in_seqid;
  297                         }
  298                 } else {
  299                         in_entry_t *inp = (in_entry_t *)local;
  300                         isp_get_notify(isp, inotp, inp);
  301                         status = inp->in_status & 0xff;
  302                         seqid = inp->in_seqid;
  303                         iid = inp->in_iid;
  304                         if (IS_DUALBUS(isp)) {
  305                                 bus = GET_BUS_VAL(inp->in_iid);
  306                                 SET_BUS_VAL(inp->in_iid, 0);
  307                         }
  308                 }
  309 
  310                 isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus, status, seqid);
  311 
  312                 switch (status) {
  313                 case IN_MSG_RECEIVED:
  314                 case IN_IDE_RECEIVED:
  315                         if (IS_FC(isp)) {
  316                                 isp_got_msg_fc(isp, (in_fcentry_t *)local);
  317                         } else {
  318                                 isp_got_msg(isp, (in_entry_t *)local);
  319                         }
  320                         break;
  321                 case IN_RSRC_UNAVAIL:
  322                         isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs");
  323                         (void) isp_notify_ack(isp, local);
  324                         break;
  325 
  326                 case IN_RESET:
  327                         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
  328                         notify.nt_hba = isp;
  329                         notify.nt_wwn = INI_ANY;
  330                         notify.nt_tgt = TGT_ANY;
  331                         notify.nt_nphdl = iid;
  332                         notify.nt_sid = PORT_ANY;
  333                         notify.nt_did = PORT_ANY;
  334                         notify.nt_lun = LUN_ANY;
  335                         notify.nt_tagval = TAG_ANY;
  336                         notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
  337                         notify.nt_ncode = NT_BUS_RESET;
  338                         notify.nt_need_ack = 1;
  339                         notify.nt_lreserved = local;
  340                         isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  341                         break;
  342 
  343                 case IN_PORT_LOGOUT:
  344                         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
  345                         notify.nt_hba = isp;
  346                         notify.nt_wwn = INI_ANY;
  347                         notify.nt_nphdl = iid;
  348                         notify.nt_sid = PORT_ANY;
  349                         notify.nt_did = PORT_ANY;
  350                         notify.nt_ncode = NT_LOGOUT;
  351                         notify.nt_need_ack = 1;
  352                         notify.nt_lreserved = local;
  353                         isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  354                         break;
  355 
  356                 case IN_ABORT_TASK:
  357                         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
  358                         notify.nt_hba = isp;
  359                         notify.nt_wwn = INI_ANY;
  360                         notify.nt_nphdl = iid;
  361                         notify.nt_sid = PORT_ANY;
  362                         notify.nt_did = PORT_ANY;
  363                         notify.nt_ncode = NT_ABORT_TASK;
  364                         notify.nt_need_ack = 1;
  365                         notify.nt_lreserved = local;
  366                         isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  367                         break;
  368 
  369                 case IN_GLOBAL_LOGO:
  370                         isp_prt(isp, ISP_LOGTINFO, "%s: all ports logged out", __func__);
  371                         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
  372                         notify.nt_hba = isp;
  373                         notify.nt_wwn = INI_ANY;
  374                         notify.nt_nphdl = NIL_HANDLE;
  375                         notify.nt_sid = PORT_ANY;
  376                         notify.nt_did = PORT_ANY;
  377                         notify.nt_ncode = NT_GLOBAL_LOGOUT;
  378                         isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  379                         (void) isp_notify_ack(isp, local);
  380                         break;
  381 
  382                 case IN_PORT_CHANGED:
  383                         isp_prt(isp, ISP_LOGTINFO, "%s: port changed", __func__);
  384                         (void) isp_notify_ack(isp, local);
  385                         break;
  386 
  387                 default:
  388                         ISP_SNPRINTF(local, sizeof local, "%s: unknown status to RQSTYPE_NOTIFY (0x%x)", __func__, status);
  389                         isp_print_bytes(isp, local, QENTRY_LEN, vptr);
  390                         (void) isp_notify_ack(isp, local);
  391                         break;
  392                 }
  393                 break;
  394 
  395         case RQSTYPE_NOTIFY_ACK:
  396                 /*
  397                  * The ISP is acknowledging our acknowledgement of an
  398                  * Immediate Notify entry for some asynchronous event.
  399                  */
  400                 if (IS_24XX(isp)) {
  401                         isp_get_notify_ack_24xx(isp, nack_24xx, (na_fcentry_24xx_t *) local);
  402                         nack_24xx = (na_fcentry_24xx_t *) local;
  403                         if (nack_24xx->na_status != NA_OK) {
  404                                 level = ISP_LOGINFO;
  405                         } else {
  406                                 level = ISP_LOGTDEBUG1;
  407                         }
  408                         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);
  409                 } else if (IS_FC(isp)) {
  410                         if (ISP_CAP_2KLOGIN(isp)) {
  411                                 isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local);
  412                         } else {
  413                                 isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local);
  414                         }
  415                         nack_fcp = (na_fcentry_t *)local;
  416                         if (nack_fcp->na_status != NA_OK) {
  417                                 level = ISP_LOGINFO;
  418                         } else {
  419                                 level = ISP_LOGTDEBUG1;
  420                         }
  421                         isp_prt(isp, level, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid);
  422                 } else {
  423                         isp_get_notify_ack(isp, nackp, (na_entry_t *)local);
  424                         nackp = (na_entry_t *)local;
  425                         if (nackp->na_status != NA_OK) {
  426                                 level = ISP_LOGINFO;
  427                         } else {
  428                                 level = ISP_LOGTDEBUG1;
  429                         }
  430                         isp_prt(isp, level, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp->na_event, nackp->na_status, nackp->na_seqid);
  431                 }
  432                 break;
  433 
  434         case RQSTYPE_ABTS_RCVD:
  435                 isp_get_abts(isp, abts, (abts_t *)local);
  436                 isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
  437                 break;
  438         case RQSTYPE_ABTS_RSP:
  439                 isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local);
  440                 abts_rsp = (abts_rsp_t *) local;
  441                 if (abts_rsp->abts_rsp_status) {
  442                         level = ISP_LOGINFO;
  443                 } else {
  444                         level = ISP_LOGTDEBUG0;
  445                 }
  446                 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,
  447                     abts_rsp->abts_rsp_payload.rsp.subcode1, abts_rsp->abts_rsp_payload.rsp.subcode2);
  448                 break;
  449         default:
  450                 isp_prt(isp, ISP_LOGERR, "%s: unknown entry type 0x%x", __func__, type);
  451                 rval = 0;
  452                 break;
  453         }
  454 #undef  atiop
  455 #undef  at2iop
  456 #undef  at2eiop
  457 #undef  at7iop
  458 #undef  ctiop
  459 #undef  ct2iop
  460 #undef  ct2eiop
  461 #undef  ct7iop
  462 #undef  lunenp
  463 #undef  inotp
  464 #undef  inot_fcp
  465 #undef  inote_fcp
  466 #undef  inot_24xx
  467 #undef  nackp
  468 #undef  nack_fcp
  469 #undef  nacke_fcp
  470 #undef  hack_24xx
  471 #undef  abts
  472 #undef  abts_rsp
  473 #undef  els
  474 #undef  hdrp
  475         return (rval);
  476 }
  477 
  478 
  479 /*
  480  * Toggle (on/off) target mode for bus/target/lun.
  481  *
  482  * The caller has checked for overlap and legality.
  483  *
  484  * Note that not all of bus, target or lun can be paid attention to.
  485  * Note also that this action will not be complete until the f/w writes
  486  * a response entry. The caller is responsible for synchronizing with this.
  487  */
  488 int
  489 isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int lun, int cmd_cnt, int inot_cnt)
  490 {
  491         lun_entry_t el;
  492         void *outp;
  493 
  494         ISP_MEMZERO(&el, sizeof (el));
  495         if (IS_DUALBUS(isp)) {
  496                 el.le_rsvd = (bus & 0x1) << 7;
  497         }
  498         el.le_cmd_count = cmd_cnt;
  499         el.le_in_count = inot_cnt;
  500         if (cmd == RQSTYPE_ENABLE_LUN) {
  501                 if (IS_SCSI(isp)) {
  502                         el.le_flags = LUN_TQAE|LUN_DISAD;
  503                         el.le_cdb6len = 12;
  504                         el.le_cdb7len = 12;
  505                 }
  506         } else if (cmd == -RQSTYPE_ENABLE_LUN) {
  507                 cmd = RQSTYPE_ENABLE_LUN;
  508                 el.le_cmd_count = 0;
  509                 el.le_in_count = 0;
  510         } else if (cmd == -RQSTYPE_MODIFY_LUN) {
  511                 cmd = RQSTYPE_MODIFY_LUN;
  512                 el.le_ops = LUN_CCDECR | LUN_INDECR;
  513         } else {
  514                 el.le_ops = LUN_CCINCR | LUN_ININCR;
  515         }
  516         el.le_header.rqs_entry_type = cmd;
  517         el.le_header.rqs_entry_count = 1;
  518         if (IS_SCSI(isp)) {
  519                 el.le_tgt = SDPARAM(isp, bus)->isp_initiator_id;
  520                 el.le_lun = lun;
  521         } else if (ISP_CAP_SCCFW(isp) == 0) {
  522                 el.le_lun = lun;
  523         }
  524         el.le_timeout = 30;
  525 
  526         outp = isp_getrqentry(isp);
  527         if (outp == NULL) {
  528                 isp_prt(isp, ISP_LOGERR, rqo, __func__);
  529                 return (-1);
  530         }
  531         isp_put_enable_lun(isp, &el, outp);
  532         ISP_TDQE(isp, "isp_lun_cmd", isp->isp_reqidx, &el);
  533         ISP_SYNC_REQUEST(isp);
  534         return (0);
  535 }
  536 
  537 int
  538 isp_target_put_entry(ispsoftc_t *isp, void *ap)
  539 {
  540         void *outp;
  541         uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
  542 
  543         outp = isp_getrqentry(isp);
  544         if (outp == NULL) {
  545                 isp_prt(isp, ISP_LOGWARN, rqo, __func__); 
  546                 return (-1);
  547         }
  548         switch (etype) {
  549         case RQSTYPE_ATIO:
  550                 isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp);
  551                 break;
  552         case RQSTYPE_ATIO2:
  553                 if (ISP_CAP_2KLOGIN(isp)) {
  554                         isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp);
  555                 } else {
  556                         isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp);
  557                 }
  558                 break;
  559         case RQSTYPE_CTIO:
  560                 isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp);
  561                 break;
  562         case RQSTYPE_CTIO2:
  563                 if (ISP_CAP_2KLOGIN(isp)) {
  564                         isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp);
  565                 } else {
  566                         isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp);
  567                 }
  568                 break;
  569         case RQSTYPE_CTIO7:
  570                 isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp);
  571                 break;
  572         default:
  573                 isp_prt(isp, ISP_LOGERR, "%s: Unknown type 0x%x", __func__, etype);
  574                 return (-1);
  575         }
  576         ISP_TDQE(isp, __func__, isp->isp_reqidx, ap);
  577         ISP_SYNC_REQUEST(isp);
  578         return (0);
  579 }
  580 
  581 int
  582 isp_target_put_atio(ispsoftc_t *isp, void *arg)
  583 {
  584         union {
  585                 at_entry_t _atio;
  586                 at2_entry_t _atio2;
  587                 at2e_entry_t _atio2e;
  588         } atun;
  589 
  590         ISP_MEMZERO(&atun, sizeof atun);
  591         if (IS_FC(isp)) {
  592                 at2_entry_t *aep = arg;
  593                 atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
  594                 atun._atio2.at_header.rqs_entry_count = 1;
  595                 if (ISP_CAP_SCCFW(isp)) {
  596                         atun._atio2.at_scclun = aep->at_scclun;
  597                 } else {
  598                         atun._atio2.at_lun = (uint8_t) aep->at_lun;
  599                 }
  600                 if (ISP_CAP_2KLOGIN(isp)) {
  601                         atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid;
  602                 } else {
  603                         atun._atio2.at_iid = aep->at_iid;
  604                 }
  605                 atun._atio2.at_rxid = aep->at_rxid;
  606                 atun._atio2.at_status = CT_OK;
  607         } else {
  608                 at_entry_t *aep = arg;
  609                 atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO;
  610                 atun._atio.at_header.rqs_entry_count = 1;
  611                 atun._atio.at_handle = aep->at_handle;
  612                 atun._atio.at_iid = aep->at_iid;
  613                 atun._atio.at_tgt = aep->at_tgt;
  614                 atun._atio.at_lun = aep->at_lun;
  615                 atun._atio.at_tag_type = aep->at_tag_type;
  616                 atun._atio.at_tag_val = aep->at_tag_val;
  617                 atun._atio.at_status = (aep->at_flags & AT_TQAE);
  618                 atun._atio.at_status |= CT_OK;
  619         }
  620         return (isp_target_put_entry(isp, &atun));
  621 }
  622 
  623 /*
  624  * Command completion- both for handling cases of no resources or
  625  * no blackhole driver, or other cases where we have to, inline,
  626  * finish the command sanely, or for normal command completion.
  627  *
  628  * The 'completion' code value has the scsi status byte in the low 8 bits.
  629  * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have
  630  * the sense key and  bits 16..23 have the ASCQ and bits 24..31 have the ASC
  631  * values.
  632  *
  633  * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't
  634  * NB: inline SCSI sense reporting. As such, we lose this information. XXX.
  635  *
  636  * For both parallel && fibre channel, we use the feature that does
  637  * an automatic resource autoreplenish so we don't have then later do
  638  * put of an atio to replenish the f/w's resource count.
  639  */
  640 
  641 int
  642 isp_endcmd(ispsoftc_t *isp, ...)
  643 {
  644         uint32_t code, hdl;
  645         uint8_t sts;
  646         union {
  647                 ct_entry_t _ctio;
  648                 ct2_entry_t _ctio2;
  649                 ct2e_entry_t _ctio2e;
  650                 ct7_entry_t _ctio7;
  651         } un;
  652         va_list ap;
  653 
  654         ISP_MEMZERO(&un, sizeof un);
  655 
  656         if (IS_24XX(isp)) {
  657                 int vpidx, nphdl;
  658                 at7_entry_t *aep;
  659                 ct7_entry_t *cto = &un._ctio7;
  660 
  661                 va_start(ap, isp);
  662                 aep = va_arg(ap, at7_entry_t *);
  663                 nphdl = va_arg(ap, int);
  664                 /*
  665                  * Note that vpidx may equal 0xff (unknown) here
  666                  */
  667                 vpidx = va_arg(ap, int);
  668                 code = va_arg(ap, uint32_t);
  669                 hdl = va_arg(ap, uint32_t);
  670                 va_end(ap);
  671                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] chan %d code %x", __func__, aep->at_rxid, vpidx, code);
  672 
  673                 sts = code & 0xff;
  674                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
  675                 cto->ct_header.rqs_entry_count = 1;
  676                 cto->ct_nphdl = nphdl;
  677                 cto->ct_rxid = aep->at_rxid;
  678                 cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
  679                 cto->ct_iid_hi = aep->at_hdr.s_id[0];
  680                 cto->ct_oxid = aep->at_hdr.ox_id;
  681                 cto->ct_scsi_status = sts;
  682                 cto->ct_vpidx = vpidx;
  683                 cto->ct_flags = CT7_NOACK;
  684                 if (code & ECMD_TERMINATE) {
  685                         cto->ct_flags |= CT7_TERMINATE;
  686                 } else if (code & ECMD_SVALID) {
  687                         cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
  688                         cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
  689                         cto->rsp.m1.ct_resplen = cto->ct_senselen = uimin(16, MAXRESPLEN_24XX);
  690                         ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp));
  691                         cto->rsp.m1.ct_resp[0] = 0xf0;
  692                         cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
  693                         cto->rsp.m1.ct_resp[7] = 8;
  694                         cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
  695                         cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
  696                 } else {
  697                         cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
  698                 }
  699                 if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) {
  700                         cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
  701                         if (cto->ct_resid < 0) {
  702                                  cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
  703                         } else if (cto->ct_resid > 0) {
  704                                  cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
  705                         }
  706                 }
  707                 cto->ct_syshandle = hdl;
  708         } else if (IS_FC(isp)) {
  709                 at2_entry_t *aep;
  710                 ct2_entry_t *cto = &un._ctio2;
  711 
  712                 va_start(ap, isp);
  713                 aep = va_arg(ap, at2_entry_t *);
  714                 code = va_arg(ap, uint32_t);
  715                 hdl = va_arg(ap, uint32_t);
  716                 va_end(ap);
  717 
  718                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] code %x", __func__, aep->at_rxid, code);
  719 
  720                 sts = code & 0xff;
  721                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
  722                 cto->ct_header.rqs_entry_count = 1;
  723                 if (ISP_CAP_SCCFW(isp) == 0) {
  724                         cto->ct_lun = aep->at_lun;
  725                 }
  726                 if (ISP_CAP_2KLOGIN(isp)) {
  727                         un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid;
  728                 } else {
  729                         cto->ct_iid = aep->at_iid;
  730                 }
  731                 cto->ct_rxid = aep->at_rxid;
  732                 cto->rsp.m1.ct_scsi_status = sts;
  733                 cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1;
  734                 if (hdl == 0) {
  735                         cto->ct_flags |= CT2_CCINCR;
  736                 }
  737                 if (aep->at_datalen) {
  738                         cto->ct_resid = aep->at_datalen;
  739                         cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
  740                 }
  741                 if (sts == SCSI_CHECK && (code & ECMD_SVALID)) {
  742                         cto->rsp.m1.ct_resp[0] = 0xf0;
  743                         cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
  744                         cto->rsp.m1.ct_resp[7] = 8;
  745                         cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
  746                         cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
  747                         cto->rsp.m1.ct_senselen = 16;
  748                         cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
  749                 }
  750                 cto->ct_syshandle = hdl;
  751         } else {
  752                 at_entry_t *aep;
  753                 ct_entry_t *cto = &un._ctio;
  754 
  755                 va_start(ap, isp);
  756                 aep = va_arg(ap, at_entry_t *);
  757                 code = va_arg(ap, uint32_t);
  758                 hdl = va_arg(ap, uint32_t);
  759                 va_end(ap);
  760                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: [IID %d] code %x", __func__, aep->at_iid, code);
  761                 sts = code;
  762 
  763                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
  764                 cto->ct_header.rqs_entry_count = 1;
  765                 cto->ct_fwhandle = aep->at_handle;
  766                 cto->ct_iid = aep->at_iid;
  767                 cto->ct_tgt = aep->at_tgt;
  768                 cto->ct_lun = aep->at_lun;
  769                 cto->ct_tag_type = aep->at_tag_type;
  770                 cto->ct_tag_val = aep->at_tag_val;
  771                 if (aep->at_flags & AT_TQAE) {
  772                         cto->ct_flags |= CT_TQAE;
  773                 }
  774                 cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA;
  775                 if (hdl == 0) {
  776                         cto->ct_flags |= CT_CCINCR;
  777                 }
  778                 cto->ct_scsi_status = sts;
  779                 cto->ct_syshandle = hdl;
  780         }
  781         return (isp_target_put_entry(isp, &un));
  782 }
  783 
  784 /*
  785  * These are either broadcast events or specifically CTIO fast completion
  786  */
  787 
  788 int
  789 isp_target_async(ispsoftc_t *isp, int bus, int event)
  790 {
  791         isp_notify_t notify;
  792 
  793         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
  794         notify.nt_hba = isp;
  795         notify.nt_wwn = INI_ANY;
  796         notify.nt_nphdl = NIL_HANDLE;
  797         notify.nt_sid = PORT_ANY;
  798         notify.nt_did = PORT_ANY;
  799         notify.nt_tgt = TGT_ANY;
  800         notify.nt_channel = bus;
  801         notify.nt_lun = LUN_ANY;
  802         notify.nt_tagval = TAG_ANY;
  803         notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
  804 
  805         switch (event) {
  806         case ASYNC_LOOP_UP:
  807         case ASYNC_PTPMODE:
  808                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP UP", __func__);
  809                 notify.nt_ncode = NT_LINK_UP;
  810                 isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  811                 break;
  812         case ASYNC_LOOP_DOWN:
  813                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP DOWN", __func__);
  814                 notify.nt_ncode = NT_LINK_DOWN;
  815                 isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  816                 break;
  817         case ASYNC_LIP_ERROR:
  818         case ASYNC_LIP_F8:
  819         case ASYNC_LIP_OCCURRED:
  820         case ASYNC_LOOP_RESET:
  821                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: LIP RESET", __func__);
  822                 notify.nt_ncode = NT_LIP_RESET;
  823                 isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  824                 break;
  825         case ASYNC_BUS_RESET:
  826         case ASYNC_TIMEOUT_RESET:       /* XXX: where does this come from ? */
  827                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: BUS RESET", __func__);
  828                 notify.nt_ncode = NT_BUS_RESET;
  829                 isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  830                 break;
  831         case ASYNC_DEVICE_RESET:
  832                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: DEVICE RESET", __func__);
  833                 notify.nt_ncode = NT_TARGET_RESET;
  834                 isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  835                 break;
  836         case ASYNC_CTIO_DONE:
  837         {
  838                 uint8_t storage[QENTRY_LEN];
  839                 isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO DONE", __func__);
  840                 memset(storage, 0, QENTRY_LEN);
  841                 if (IS_24XX(isp)) {
  842                         ct7_entry_t *ct = (ct7_entry_t *) storage;
  843                         ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
  844                         ct->ct_nphdl = CT7_OK;
  845                         ct->ct_syshandle = bus;
  846                         ct->ct_flags = CT7_SENDSTATUS;
  847                 } else if (IS_FC(isp)) {
  848                         /* This should also suffice for 2K login code */
  849                         ct2_entry_t *ct = (ct2_entry_t *) storage;
  850                         ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
  851                         ct->ct_status = CT_OK;
  852                         ct->ct_syshandle = bus;
  853                         ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST;
  854                 } else {
  855                         ct_entry_t *ct = (ct_entry_t *) storage;
  856                         ct->ct_header.rqs_entry_type = RQSTYPE_CTIO;
  857                         ct->ct_status = CT_OK;
  858                         ct->ct_syshandle = bus;
  859                         /* we skip fwhandle here */
  860                         ct->ct_fwhandle = 0;
  861                         ct->ct_flags = CT_SENDSTATUS;
  862                 }
  863                 isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
  864                 break;
  865         }
  866         default:
  867                 isp_prt(isp, ISP_LOGERR, "%s: unknown event 0x%x", __func__, event);
  868                 if (isp->isp_state == ISP_RUNSTATE) {
  869                         (void) isp_notify_ack(isp, NULL);
  870                 }
  871                 break;
  872         }
  873         return (0);
  874 }
  875 
  876 
  877 /*
  878  * Process a received message.
  879  * The ISP firmware can handle most messages, there are only
  880  * a few that we need to deal with:
  881  * - abort: clean up the current command
  882  * - abort tag and clear queue
  883  */
  884 
  885 static void
  886 isp_got_msg(ispsoftc_t *isp, in_entry_t *inp)
  887 {
  888         isp_notify_t notify;
  889         uint8_t status = inp->in_status & ~QLTM_SVALID;
  890 
  891         ISP_MEMZERO(&notify, sizeof (notify));
  892         notify.nt_hba = isp;
  893         notify.nt_wwn = INI_ANY;
  894         notify.nt_nphdl = GET_IID_VAL(inp->in_iid);
  895         notify.nt_sid = PORT_ANY;
  896         notify.nt_did = PORT_ANY;
  897         notify.nt_channel = GET_BUS_VAL(inp->in_iid);
  898         notify.nt_tgt = inp->in_tgt;
  899         notify.nt_lun = inp->in_lun;
  900         IN_MAKE_TAGID(notify.nt_tagval, inp);
  901         notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
  902         notify.nt_lreserved = inp;
  903 
  904         if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) {
  905                 switch (inp->in_msg[0]) {
  906                 case MSG_ABORT:
  907                         notify.nt_ncode = NT_ABORT_TASK_SET;
  908                         break;
  909                 case MSG_BUS_DEV_RESET:
  910                         notify.nt_ncode = NT_TARGET_RESET;
  911                         break;
  912                 case MSG_ABORT_TAG:
  913                         notify.nt_ncode = NT_ABORT_TASK;
  914                         break;
  915                 case MSG_CLEAR_QUEUE:
  916                         notify.nt_ncode = NT_CLEAR_TASK_SET;
  917                         break;
  918                 case MSG_REL_RECOVERY:
  919                         notify.nt_ncode = NT_CLEAR_ACA;
  920                         break;
  921                 case MSG_TERM_IO_PROC:
  922                         notify.nt_ncode = NT_ABORT_TASK;
  923                         break;
  924                 case MSG_LUN_RESET:
  925                         notify.nt_ncode = NT_LUN_RESET;
  926                         break;
  927                 default:
  928                         isp_prt(isp, ISP_LOGERR, "%s: unhandled message 0x%x", __func__, inp->in_msg[0]);
  929                         (void) isp_notify_ack(isp, inp);
  930                         return;
  931                 }
  932                 isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
  933         } else {
  934                 isp_prt(isp, ISP_LOGERR, "%s: unknown immediate notify status 0x%x", __func__, inp->in_status);
  935                 (void) isp_notify_ack(isp, inp);
  936         }
  937 }
  938 
  939 /*
  940  * Synthesize a message from the task management flags in a FCP_CMND_IU.
  941  */
  942 static void
  943 isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
  944 {
  945         isp_notify_t notify;
  946         static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
  947         static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
  948         uint16_t seqid, loopid;
  949 
  950         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
  951         notify.nt_hba = isp;
  952         notify.nt_wwn = INI_ANY;
  953         if (ISP_CAP_2KLOGIN(isp)) {
  954                 notify.nt_nphdl = ((in_fcentry_e_t *)inp)->in_iid;
  955                 loopid = ((in_fcentry_e_t *)inp)->in_iid;
  956                 seqid = ((in_fcentry_e_t *)inp)->in_seqid;
  957         } else {
  958                 notify.nt_nphdl = inp->in_iid;
  959                 loopid = inp->in_iid;
  960                 seqid = inp->in_seqid;
  961         }
  962         notify.nt_sid = PORT_ANY;
  963         notify.nt_did = PORT_ANY;
  964 
  965         /* nt_tgt set in outer layers */
  966         if (ISP_CAP_SCCFW(isp)) {
  967                 notify.nt_lun = inp->in_scclun;
  968         } else {
  969                 notify.nt_lun = inp->in_lun;
  970         }
  971         notify.nt_tagval = seqid;
  972         notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
  973         notify.nt_need_ack = 1;
  974         notify.nt_lreserved = inp;
  975 
  976         if (inp->in_status != IN_MSG_RECEIVED) {
  977                 isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid);
  978                 (void) isp_notify_ack(isp, inp);
  979                 return;
  980         }
  981 
  982         if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) {
  983                 isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", loopid, notify.nt_lun, inp->in_seqid);
  984                 notify.nt_ncode = NT_ABORT_TASK_SET;
  985         } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {
  986                 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", loopid, notify.nt_lun, inp->in_seqid);
  987                 notify.nt_ncode = NT_CLEAR_TASK_SET;
  988         } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) {
  989                 isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", loopid, notify.nt_lun, inp->in_seqid);
  990                 notify.nt_ncode = NT_LUN_RESET;
  991         } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {
  992                 isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", loopid, notify.nt_lun, inp->in_seqid);
  993                 notify.nt_ncode = NT_TARGET_RESET;
  994         } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {
  995                 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", loopid, notify.nt_lun, inp->in_seqid);
  996                 notify.nt_ncode = NT_CLEAR_ACA;
  997         } else {
  998                 isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags,  inp->in_seqid);
  999                 (void) isp_notify_ack(isp, inp);
 1000                 return;
 1001         }
 1002         isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
 1003 }
 1004 
 1005 static void
 1006 isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
 1007 {
 1008         isp_notify_t notify;
 1009         static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%08x";
 1010         static const char f2[] = "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x";
 1011         uint16_t chan;
 1012         uint32_t sid, did;
 1013 
 1014         ISP_MEMZERO(&notify, sizeof (isp_notify_t));
 1015         notify.nt_hba = isp;
 1016         notify.nt_wwn = INI_ANY;
 1017         notify.nt_lun = (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | (aep->at_cmnd.fcp_cmnd_lun[1]);
 1018         notify.nt_tagval = aep->at_rxid;
 1019         notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
 1020         notify.nt_lreserved = aep;
 1021         sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] <<  8) | (aep->at_hdr.s_id[2]);
 1022 
 1023         /* Channel has to derived from D_ID */
 1024         did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2];
 1025         for (chan = 0; chan < isp->isp_nchan; chan++) {
 1026                 if (FCPARAM(isp, chan)->isp_portid == did) {
 1027                         break;
 1028                 }
 1029         }
 1030         if (chan == isp->isp_nchan) {
 1031                 isp_prt(isp, ISP_LOGWARN, "%s: D_ID 0x%x not found on any channel", __func__, did);
 1032                 /* just drop on the floor */
 1033                 return;
 1034         }
 1035         notify.nt_nphdl = NIL_HANDLE; /* unknown here */
 1036         notify.nt_sid = sid;
 1037         notify.nt_did = did;
 1038         notify.nt_channel = chan;
 1039         if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_ABORT_TASK_SET) {
 1040                 isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", sid, notify.nt_lun, aep->at_rxid);
 1041                 notify.nt_ncode = NT_ABORT_TASK_SET;
 1042         } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_TASK_SET) {
 1043                 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", sid, notify.nt_lun, aep->at_rxid);
 1044                 notify.nt_ncode = NT_CLEAR_TASK_SET;
 1045         } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_LUN_RESET) {
 1046                 isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", sid, notify.nt_lun, aep->at_rxid);
 1047                 notify.nt_ncode = NT_LUN_RESET;
 1048         } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_TGT_RESET) {
 1049                 isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", sid, notify.nt_lun, aep->at_rxid);
 1050                 notify.nt_ncode = NT_TARGET_RESET;
 1051         } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_ACA) {
 1052                 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", sid, notify.nt_lun, aep->at_rxid);
 1053                 notify.nt_ncode = NT_CLEAR_ACA;
 1054         } else {
 1055                 isp_prt(isp, ISP_LOGWARN, f2, aep->at_cmnd.fcp_cmnd_task_management, notify.nt_lun, sid, aep->at_rxid);
 1056                 notify.nt_ncode = NT_UNKNOWN;
 1057                 return;
 1058         }
 1059         isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
 1060 }
 1061 
 1062 int
 1063 isp_notify_ack(ispsoftc_t *isp, void *arg)
 1064 {
 1065         char storage[QENTRY_LEN];
 1066         void *outp;
 1067 
 1068         /*
 1069          * This is in case a Task Management Function ends up here.
 1070          */
 1071         if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) {
 1072                 at7_entry_t *aep = arg;
 1073                 return (isp_endcmd(isp, aep, NIL_HANDLE, 0, 0, 0));
 1074         }
 1075 
 1076         outp = isp_getrqentry(isp);
 1077         if (outp == NULL) {
 1078                 isp_prt(isp, ISP_LOGWARN, rqo, __func__);
 1079                 return (1);
 1080         }
 1081 
 1082         ISP_MEMZERO(storage, QENTRY_LEN);
 1083 
 1084         if (IS_24XX(isp)) {
 1085                 na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage;
 1086                 if (arg) {
 1087                         in_fcentry_24xx_t *in = arg;
 1088                         na->na_nphdl = in->in_nphdl;
 1089                         na->na_flags = in->in_flags & IN24XX_FLAG_PUREX_IOCB;
 1090                         na->na_status = in->in_status;
 1091                         na->na_status_subcode = in->in_status_subcode;
 1092                         na->na_rxid = in->in_rxid;
 1093                         na->na_oxid = in->in_oxid;
 1094                         na->na_vpidx = in->in_vpidx;
 1095                         if (in->in_status == IN24XX_SRR_RCVD) {
 1096                                 na->na_srr_rxid = in->in_srr_rxid;
 1097                                 na->na_srr_reloff_hi = in->in_srr_reloff_hi;
 1098                                 na->na_srr_reloff_lo = in->in_srr_reloff_lo;
 1099                                 na->na_srr_iu = in->in_srr_iu;
 1100                                 na->na_srr_flags = 1;
 1101                                 na->na_srr_reject_vunique = 0;
 1102                                 na->na_srr_reject_explanation = 1;
 1103                                 na->na_srr_reject_code = 1;
 1104                         }
 1105                 }
 1106                 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
 1107                 na->na_header.rqs_entry_count = 1;
 1108                 isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp);
 1109         } else if (IS_FC(isp)) {
 1110                 na_fcentry_t *na = (na_fcentry_t *) storage;
 1111                 int iid = 0;
 1112 
 1113                 if (arg) {
 1114                         in_fcentry_t *inp = arg;
 1115                         ISP_MEMCPY(storage, arg, sizeof (isphdr_t));
 1116                         if (ISP_CAP_2KLOGIN(isp)) {
 1117                                 ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid;
 1118                                 iid = ((na_fcentry_e_t *)na)->na_iid;
 1119                         } else {
 1120                                 na->na_iid = inp->in_iid;
 1121                                 iid = na->na_iid;
 1122                         }
 1123                         na->na_task_flags = inp->in_task_flags & TASK_FLAGS_RESERVED_MASK;
 1124                         na->na_seqid = inp->in_seqid;
 1125                         na->na_flags = NAFC_RCOUNT;
 1126                         na->na_status = inp->in_status;
 1127                         if (inp->in_status == IN_RESET) {
 1128                                 na->na_flags |= NAFC_RST_CLRD;
 1129                         }
 1130                         if (inp->in_status == IN_MSG_RECEIVED) {
 1131                                 na->na_flags |= NAFC_TVALID;
 1132                                 na->na_response = 0;    /* XXX SUCCEEDED XXX */
 1133                         }
 1134                 } else {
 1135                         na->na_flags = NAFC_RST_CLRD;
 1136                 }
 1137                 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
 1138                 na->na_header.rqs_entry_count = 1;
 1139                 if (ISP_CAP_2KLOGIN(isp)) {
 1140                         isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp);
 1141                 } else {
 1142                         isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);
 1143                 }
 1144                 isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x flags %x tflags %x response %x", iid, na->na_seqid,
 1145                     na->na_flags, na->na_task_flags, na->na_response);
 1146         } else {
 1147                 na_entry_t *na = (na_entry_t *) storage;
 1148                 if (arg) {
 1149                         in_entry_t *inp = arg;
 1150                         ISP_MEMCPY(storage, arg, sizeof (isphdr_t));
 1151                         na->na_iid = inp->in_iid;
 1152                         na->na_lun = inp->in_lun;
 1153                         na->na_tgt = inp->in_tgt;
 1154                         na->na_seqid = inp->in_seqid;
 1155                         if (inp->in_status == IN_RESET) {
 1156                                 na->na_event = NA_RST_CLRD;
 1157                         }
 1158                 } else {
 1159                         na->na_event = NA_RST_CLRD;
 1160                 }
 1161                 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
 1162                 na->na_header.rqs_entry_count = 1;
 1163                 isp_put_notify_ack(isp, na, (na_entry_t *)outp);
 1164                 isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event);
 1165         }
 1166         ISP_TDQE(isp, "isp_notify_ack", isp->isp_reqidx, storage);
 1167         ISP_SYNC_REQUEST(isp);
 1168         return (0);
 1169 }
 1170 
 1171 int
 1172 isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno)
 1173 {
 1174         char storage[QENTRY_LEN];
 1175         uint16_t tmpw;
 1176         uint8_t tmpb;
 1177         abts_t *abts = arg;
 1178         abts_rsp_t *rsp = (abts_rsp_t *) storage;
 1179         void *outp;
 1180 
 1181         if (!IS_24XX(isp)) {
 1182                 isp_prt(isp, ISP_LOGERR, "%s: called for non-24XX card", __func__);
 1183                 return (0);
 1184         }
 1185 
 1186         if (abts->abts_header.rqs_entry_type != RQSTYPE_ABTS_RCVD) {
 1187                 isp_prt(isp, ISP_LOGERR, "%s: called for non-ABTS entry (0x%x)", __func__, abts->abts_header.rqs_entry_type);
 1188                 return (0);
 1189         }
 1190 
 1191         outp = isp_getrqentry(isp);
 1192         if (outp == NULL) {
 1193                 isp_prt(isp, ISP_LOGWARN, rqo, __func__);
 1194                 return (1);
 1195         }
 1196 
 1197         ISP_MEMCPY(rsp, abts, QENTRY_LEN);
 1198         rsp->abts_rsp_header.rqs_entry_type = RQSTYPE_ABTS_RSP;
 1199 
 1200         /*
 1201          * Swap destination and source for response.
 1202          */
 1203         rsp->abts_rsp_r_ctl = BA_ACC;
 1204         tmpw = rsp->abts_rsp_did_lo;
 1205         tmpb = rsp->abts_rsp_did_hi;
 1206         rsp->abts_rsp_did_lo = rsp->abts_rsp_sid_lo;
 1207         rsp->abts_rsp_did_hi = rsp->abts_rsp_sid_hi;
 1208         rsp->abts_rsp_sid_lo = tmpw;
 1209         rsp->abts_rsp_sid_hi = tmpb;
 1210 
 1211         rsp->abts_rsp_f_ctl_hi ^= 0x80;         /* invert Exchange Context */
 1212         rsp->abts_rsp_f_ctl_hi &= ~0x7f;        /* clear Sequence Initiator and other bits */
 1213         rsp->abts_rsp_f_ctl_hi |= 0x10;         /* abort the whole exchange */
 1214         rsp->abts_rsp_f_ctl_hi |= 0x8;          /* last data frame of sequence */
 1215         rsp->abts_rsp_f_ctl_hi |= 0x1;          /* transfer Sequence Initiative */
 1216         rsp->abts_rsp_f_ctl_lo = 0;
 1217 
 1218         if (errno == 0) {
 1219                 uint16_t rx_id, ox_id;
 1220 
 1221                 rx_id = rsp->abts_rsp_rx_id;
 1222                 ox_id = rsp->abts_rsp_ox_id;
 1223                 ISP_MEMZERO(&rsp->abts_rsp_payload.ba_acc, sizeof (rsp->abts_rsp_payload.ba_acc));
 1224                 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);
 1225                 rsp->abts_rsp_payload.ba_acc.aborted_rx_id = rx_id;
 1226                 rsp->abts_rsp_payload.ba_acc.aborted_ox_id = ox_id;
 1227                 rsp->abts_rsp_payload.ba_acc.high_seq_cnt = 0xffff;
 1228         } else {
 1229                 ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_acc));
 1230                 switch (errno) {
 1231                 case ENOMEM:
 1232                         rsp->abts_rsp_payload.ba_rjt.reason = 5;        /* Logical Busy */
 1233                         break;
 1234                 default:
 1235                         rsp->abts_rsp_payload.ba_rjt.reason = 9;        /* Unable to perform command request */
 1236                         break;
 1237                 }
 1238         }
 1239 
 1240         /*
 1241          * The caller will have set response values as appropriate
 1242          * in the ABTS structure just before calling us.
 1243          */
 1244         isp_put_abts_rsp(isp, rsp, (abts_rsp_t *)outp);
 1245         ISP_TDQE(isp, "isp_acknak_abts", isp->isp_reqidx, storage);
 1246         ISP_SYNC_REQUEST(isp);
 1247         return (0);
 1248 }
 1249 
 1250 static void
 1251 isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
 1252 {
 1253         int lun;
 1254         lun = aep->at_lun;
 1255         /*
 1256          * The firmware status (except for the QLTM_SVALID bit) indicates
 1257          * why this ATIO was sent to us.
 1258          *
 1259          * If QLTM_SVALID is set, the firmware has recommended Sense Data.
 1260          *
 1261          * If the DISCONNECTS DISABLED bit is set in the flags field,
 1262          * we're still connected on the SCSI bus - i.e. the initiator
 1263          * did not set DiscPriv in the identify message. We don't care
 1264          * about this so it's ignored.
 1265          */
 1266 
 1267         switch (aep->at_status & ~QLTM_SVALID) {
 1268         case AT_PATH_INVALID:
 1269                 /*
 1270                  * ATIO rejected by the firmware due to disabled lun.
 1271                  */
 1272                 isp_prt(isp, ISP_LOGERR, "rejected ATIO for disabled lun %d", lun);
 1273                 break;
 1274         case AT_NOCAP:
 1275                 /*
 1276                  * Requested Capability not available
 1277                  * We sent an ATIO that overflowed the firmware's
 1278                  * command resource count.
 1279                  */
 1280                 isp_prt(isp, ISP_LOGERR, "rejected ATIO for lun %d because of command count overflow", lun);
 1281                 break;
 1282 
 1283         case AT_BDR_MSG:
 1284                 /*
 1285                  * If we send an ATIO to the firmware to increment
 1286                  * its command resource count, and the firmware is
 1287                  * recovering from a Bus Device Reset, it returns
 1288                  * the ATIO with this status. We set the command
 1289                  * resource count in the Enable Lun entry and do
 1290                  * not increment it. Therefore we should never get
 1291                  * this status here.
 1292                  */
 1293                 isp_prt(isp, ISP_LOGERR, atiocope, lun, GET_BUS_VAL(aep->at_iid));
 1294                 break;
 1295 
 1296         case AT_CDB:            /* Got a CDB */
 1297         case AT_PHASE_ERROR:    /* Bus Phase Sequence Error */
 1298                 /*
 1299                  * Punt to platform specific layer.
 1300                  */
 1301                 isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
 1302                 break;
 1303 
 1304         case AT_RESET:
 1305                 /*
 1306                  * A bus reset came along and blew away this command. Why
 1307                  * they do this in addition the async event code stuff,
 1308                  * I dunno.
 1309                  *
 1310                  * Ignore it because the async event will clear things
 1311                  * up for us.
 1312                  */
 1313                 isp_prt(isp, ISP_LOGWARN, atior, lun, GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid));
 1314                 break;
 1315 
 1316 
 1317         default:
 1318                 isp_prt(isp, ISP_LOGERR, "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun);
 1319                 (void) isp_target_put_atio(isp, aep);
 1320                 break;
 1321         }
 1322 }
 1323 
 1324 static void
 1325 isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
 1326 {
 1327         int lun, iid;
 1328 
 1329         if (ISP_CAP_SCCFW(isp)) {
 1330                 lun = aep->at_scclun;
 1331         } else {
 1332                 lun = aep->at_lun;
 1333         }
 1334 
 1335         if (ISP_CAP_2KLOGIN(isp)) {
 1336                 iid = ((at2e_entry_t *)aep)->at_iid;
 1337         } else {
 1338                 iid = aep->at_iid;
 1339         }
 1340 
 1341         /*
 1342          * The firmware status (except for the QLTM_SVALID bit) indicates
 1343          * why this ATIO was sent to us.
 1344          *
 1345          * If QLTM_SVALID is set, the firmware has recommended Sense Data.
 1346          *
 1347          * If the DISCONNECTS DISABLED bit is set in the flags field,
 1348          * we're still connected on the SCSI bus - i.e. the initiator
 1349          * did not set DiscPriv in the identify message. We don't care
 1350          * about this so it's ignored.
 1351          */
 1352 
 1353         switch (aep->at_status & ~QLTM_SVALID) {
 1354         case AT_PATH_INVALID:
 1355                 /*
 1356                  * ATIO rejected by the firmware due to disabled lun.
 1357                  */
 1358                 isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for disabled lun %d", lun);
 1359                 break;
 1360         case AT_NOCAP:
 1361                 /*
 1362                  * Requested Capability not available
 1363                  * We sent an ATIO that overflowed the firmware's
 1364                  * command resource count.
 1365                  */
 1366                 isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for lun %d- command count overflow", lun);
 1367                 break;
 1368 
 1369         case AT_BDR_MSG:
 1370                 /*
 1371                  * If we send an ATIO to the firmware to increment
 1372                  * its command resource count, and the firmware is
 1373                  * recovering from a Bus Device Reset, it returns
 1374                  * the ATIO with this status. We set the command
 1375                  * resource count in the Enable Lun entry and no
 1376                  * not increment it. Therefore we should never get
 1377                  * this status here.
 1378                  */
 1379                 isp_prt(isp, ISP_LOGERR, atiocope, lun, 0);
 1380                 break;
 1381 
 1382         case AT_CDB:            /* Got a CDB */
 1383                 /*
 1384                  * Punt to platform specific layer.
 1385                  */
 1386                 isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
 1387                 break;
 1388 
 1389         case AT_RESET:
 1390                 /*
 1391                  * A bus reset came along an blew away this command. Why
 1392                  * they do this in addition the async event code stuff,
 1393                  * I dunno.
 1394                  *
 1395                  * Ignore it because the async event will clear things
 1396                  * up for us.
 1397                  */
 1398                 isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0);
 1399                 break;
 1400 
 1401 
 1402         default:
 1403                 isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from loopid %d for lun %d", aep->at_status, iid, lun);
 1404                 (void) isp_target_put_atio(isp, aep);
 1405                 break;
 1406         }
 1407 }
 1408 
 1409 static void
 1410 isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
 1411 {
 1412         void *xs;
 1413         int pl = ISP_LOGTDEBUG2;
 1414         char *fmsg = NULL;
 1415 
 1416         if (ct->ct_syshandle) {
 1417                 xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
 1418                 if (xs == NULL) {
 1419                         pl = ISP_LOGALL;
 1420                 }
 1421         } else {
 1422                 xs = NULL;
 1423         }
 1424 
 1425         switch (ct->ct_status & ~QLTM_SVALID) {
 1426         case CT_OK:
 1427                 /*
 1428                  * There are generally 3 possibilities as to why we'd get
 1429                  * this condition:
 1430                  *      We disconnected after receiving a CDB.
 1431                  *      We sent or received data.
 1432                  *      We sent status & command complete.
 1433                  */
 1434 
 1435                 if (ct->ct_flags & CT_SENDSTATUS) {
 1436                         break;
 1437                 } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) {
 1438                         /*
 1439                          * Nothing to do in this case.
 1440                          */
 1441                         isp_prt(isp, pl, "CTIO- iid %d disconnected OK", ct->ct_iid);
 1442                         return;
 1443                 }
 1444                 break;
 1445 
 1446         case CT_BDR_MSG:
 1447                 /*
 1448                  * Bus Device Reset message received or the SCSI Bus has
 1449                  * been Reset; the firmware has gone to Bus Free.
 1450                  *
 1451                  * The firmware generates an async mailbox interrupt to
 1452                  * notify us of this and returns outstanding CTIOs with this
 1453                  * status. These CTIOs are handled in that same way as
 1454                  * CT_ABORTED ones, so just fall through here.
 1455                  */
 1456                 fmsg = "Bus Device Reset";
 1457                 /*FALLTHROUGH*/
 1458         case CT_RESET:
 1459                 if (fmsg == NULL)
 1460                         fmsg = "Bus Reset";
 1461                 /*FALLTHROUGH*/
 1462         case CT_ABORTED:
 1463                 /*
 1464                  * When an Abort message is received the firmware goes to
 1465                  * Bus Free and returns all outstanding CTIOs with the status
 1466                  * set, then sends us an Immediate Notify entry.
 1467                  */
 1468                 if (fmsg == NULL)
 1469                         fmsg = "ABORT TAG message sent by Initiator";
 1470                 isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg);
 1471                 break;
 1472 
 1473         case CT_INVAL:
 1474                 /*
 1475                  * CTIO rejected by the firmware due to disabled lun.
 1476                  * "Cannot Happen".
 1477                  */
 1478                 isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for disabled lun %d", ct->ct_lun);
 1479                 break;
 1480 
 1481         case CT_NOPATH:
 1482                 /*
 1483                  * CTIO rejected by the firmware due "no path for the
 1484                  * nondisconnecting nexus specified". This means that
 1485                  * we tried to access the bus while a non-disconnecting
 1486                  * command is in process.
 1487                  */
 1488                 isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for bad nexus %d/%d/%d", ct->ct_iid, ct->ct_tgt, ct->ct_lun);
 1489                 break;
 1490 
 1491         case CT_RSELTMO:
 1492                 fmsg = "Reselection";
 1493                 /*FALLTHROUGH*/
 1494         case CT_TIMEOUT:
 1495                 if (fmsg == NULL)
 1496                         fmsg = "Command";
 1497                 isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
 1498                 break;
 1499 
 1500         case    CT_PANIC:
 1501                 if (fmsg == NULL)
 1502                         fmsg = "Unrecoverable Error";
 1503                 /*FALLTHROUGH*/
 1504         case CT_ERR:
 1505                 if (fmsg == NULL)
 1506                         fmsg = "Completed with Error";
 1507                 /*FALLTHROUGH*/
 1508         case CT_PHASE_ERROR:
 1509                 if (fmsg == NULL)
 1510                         fmsg = "Phase Sequence Error";
 1511                 /*FALLTHROUGH*/
 1512         case CT_TERMINATED:
 1513                 if (fmsg == NULL)
 1514                         fmsg = "terminated by TERMINATE TRANSFER";
 1515                 /*FALLTHROUGH*/
 1516         case CT_NOACK:
 1517                 if (fmsg == NULL)
 1518                         fmsg = "unacknowledged Immediate Notify pending";
 1519                 isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
 1520                 break;
 1521         default:
 1522                 isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", ct->ct_status & ~QLTM_SVALID);
 1523                 break;
 1524         }
 1525 
 1526         if (xs == NULL) {
 1527                 /*
 1528                  * There may be more than one CTIO for a data transfer,
 1529                  * or this may be a status CTIO we're not monitoring.
 1530                  *
 1531                  * The assumption is that they'll all be returned in the
 1532                  * order we got them.
 1533                  */
 1534                 if (ct->ct_syshandle == 0) {
 1535                         if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
 1536                                 isp_prt(isp, pl, "intermediate CTIO completed ok");
 1537                         } else {
 1538                                 isp_prt(isp, pl, "unmonitored CTIO completed ok");
 1539                         }
 1540                 } else {
 1541                         isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
 1542                 }
 1543         } else {
 1544                 /*
 1545                  * Final CTIO completed. Release DMA resources and
 1546                  * notify platform dependent layers.
 1547                  */
 1548                 if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
 1549                         ISP_DMAFREE(isp, xs, ct->ct_syshandle);
 1550                 }
 1551                 isp_prt(isp, pl, "final CTIO complete");
 1552                 /*
 1553                  * The platform layer will destroy the handle if appropriate.
 1554                  */
 1555                 isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
 1556         }
 1557 }
 1558 
 1559 static void
 1560 isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
 1561 {
 1562         void *xs;
 1563         int pl = ISP_LOGTDEBUG2;
 1564         char *fmsg = NULL;
 1565 
 1566         if (ct->ct_syshandle) {
 1567                 xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
 1568                 if (xs == NULL) {
 1569                         pl = ISP_LOGALL;
 1570                 }
 1571         } else {
 1572                 xs = NULL;
 1573         }
 1574 
 1575         switch (ct->ct_status & ~QLTM_SVALID) {
 1576         case CT_BUS_ERROR:
 1577                 isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
 1578                 /* FALL Through */
 1579         case CT_DATA_OVER:
 1580         case CT_DATA_UNDER:
 1581         case CT_OK:
 1582                 /*
 1583                  * There are generally 2 possibilities as to why we'd get
 1584                  * this condition:
 1585                  *      We sent or received data.
 1586                  *      We sent status & command complete.
 1587                  */
 1588 
 1589                 break;
 1590 
 1591         case CT_BDR_MSG:
 1592                 /*
 1593                  * Target Reset function received.
 1594                  *
 1595                  * The firmware generates an async mailbox interrupt to
 1596                  * notify us of this and returns outstanding CTIOs with this
 1597                  * status. These CTIOs are handled in that same way as
 1598                  * CT_ABORTED ones, so just fall through here.
 1599                  */
 1600                 fmsg = "TARGET RESET";
 1601                 /*FALLTHROUGH*/
 1602         case CT_RESET:
 1603                 if (fmsg == NULL)
 1604                         fmsg = "LIP Reset";
 1605                 /*FALLTHROUGH*/
 1606         case CT_ABORTED:
 1607                 /*
 1608                  * When an Abort message is received the firmware goes to
 1609                  * Bus Free and returns all outstanding CTIOs with the status
 1610                  * set, then sends us an Immediate Notify entry.
 1611                  */
 1612                 if (fmsg == NULL) {
 1613                         fmsg = "ABORT";
 1614                 }
 1615 
 1616                 isp_prt(isp, ISP_LOGTDEBUG0, "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
 1617                 break;
 1618 
 1619         case CT_INVAL:
 1620                 /*
 1621                  * CTIO rejected by the firmware - invalid data direction.
 1622                  */
 1623                 isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data direction");
 1624                 break;
 1625 
 1626         case CT_RSELTMO:
 1627                 fmsg = "failure to reconnect to initiator";
 1628                 /*FALLTHROUGH*/
 1629         case CT_TIMEOUT:
 1630                 if (fmsg == NULL)
 1631                         fmsg = "command";
 1632                 isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
 1633                 break;
 1634 
 1635         case CT_ERR:
 1636                 fmsg = "Completed with Error";
 1637                 /*FALLTHROUGH*/
 1638         case CT_LOGOUT:
 1639                 if (fmsg == NULL)
 1640                         fmsg = "Port Logout";
 1641                 /*FALLTHROUGH*/
 1642         case CT_PORTUNAVAIL:
 1643                 if (fmsg == NULL)
 1644                         fmsg = "Port not available";
 1645                 /*FALLTHROUGH*/
 1646         case CT_PORTCHANGED:
 1647                 if (fmsg == NULL)
 1648                         fmsg = "Port Changed";
 1649                 /*FALLTHROUGH*/
 1650         case CT_NOACK:
 1651                 if (fmsg == NULL)
 1652                         fmsg = "unacknowledged Immediate Notify pending";
 1653                 isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
 1654                 break;
 1655 
 1656         case CT_INVRXID:
 1657                 /*
 1658                  * CTIO rejected by the firmware because an invalid RX_ID.
 1659                  * Just print a message.
 1660                  */
 1661                 isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
 1662                 break;
 1663 
 1664         default:
 1665                 isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", ct->ct_status & ~QLTM_SVALID);
 1666                 break;
 1667         }
 1668 
 1669         if (xs == NULL) {
 1670                 /*
 1671                  * There may be more than one CTIO for a data transfer,
 1672                  * or this may be a status CTIO we're not monitoring.
 1673                  *
 1674                  * The assumption is that they'll all be returned in the
 1675                  * order we got them.
 1676                  */
 1677                 if (ct->ct_syshandle == 0) {
 1678                         if ((ct->ct_flags & CT2_SENDSTATUS) == 0) {
 1679                                 isp_prt(isp, pl, "intermediate CTIO completed ok");
 1680                         } else {
 1681                                 isp_prt(isp, pl, "unmonitored CTIO completed ok");
 1682                         }
 1683                 } else {
 1684                         isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
 1685                 }
 1686         } else {
 1687                 if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
 1688                         ISP_DMAFREE(isp, xs, ct->ct_syshandle);
 1689                 }
 1690                 if (ct->ct_flags & CT2_SENDSTATUS) {
 1691                         /*
 1692                          * Sent status and command complete.
 1693                          *
 1694                          * We're now really done with this command, so we
 1695                          * punt to the platform dependent layers because
 1696                          * only there can we do the appropriate command
 1697                          * complete thread synchronization.
 1698                          */
 1699                         isp_prt(isp, pl, "status CTIO complete");
 1700                 } else {
 1701                         /*
 1702                          * Final CTIO completed. Release DMA resources and
 1703                          * notify platform dependent layers.
 1704                          */
 1705                         isp_prt(isp, pl, "data CTIO complete");
 1706                 }
 1707                 isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
 1708                 /*
 1709                  * The platform layer will destroy the handle if appropriate.
 1710                  */
 1711         }
 1712 }
 1713 
 1714 static void
 1715 isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
 1716 {
 1717         void *xs;
 1718         int pl = ISP_LOGTDEBUG2;
 1719         char *fmsg = NULL;
 1720 
 1721         if (ct->ct_syshandle) {
 1722                 xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
 1723                 if (xs == NULL) {
 1724                         pl = ISP_LOGALL;
 1725                 }
 1726         } else {
 1727                 xs = NULL;
 1728         }
 1729 
 1730         switch (ct->ct_nphdl) {
 1731         case CT7_BUS_ERROR:
 1732                 isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
 1733                 /* FALL Through */
 1734         case CT7_DATA_OVER:
 1735         case CT7_DATA_UNDER:
 1736         case CT7_OK:
 1737                 /*
 1738                  * There are generally 2 possibilities as to why we'd get
 1739                  * this condition:
 1740                  *      We sent or received data.
 1741                  *      We sent status & command complete.
 1742                  */
 1743 
 1744                 break;
 1745 
 1746         case CT7_RESET:
 1747                 if (fmsg == NULL) {
 1748                         fmsg = "LIP Reset";
 1749                 }
 1750                 /*FALLTHROUGH*/
 1751         case CT7_ABORTED:
 1752                 /*
 1753                  * When an Abort message is received the firmware goes to
 1754                  * Bus Free and returns all outstanding CTIOs with the status
 1755                  * set, then sends us an Immediate Notify entry.
 1756                  */
 1757                 if (fmsg == NULL) {
 1758                         fmsg = "ABORT";
 1759                 }
 1760                 isp_prt(isp, ISP_LOGTDEBUG0, "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
 1761                 break;
 1762 
 1763         case CT7_TIMEOUT:
 1764                 if (fmsg == NULL) {
 1765                         fmsg = "command";
 1766                 }
 1767                 isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
 1768                 break;
 1769 
 1770         case CT7_ERR:
 1771                 fmsg = "Completed with Error";
 1772                 /*FALLTHROUGH*/
 1773         case CT7_LOGOUT:
 1774                 if (fmsg == NULL) {
 1775                         fmsg = "Port Logout";
 1776                 }
 1777                 /*FALLTHROUGH*/
 1778         case CT7_PORTUNAVAIL:
 1779                 if (fmsg == NULL) {
 1780                         fmsg = "Port not available";
 1781                 }
 1782                 /*FALLTHROUGH*/
 1783         case CT7_PORTCHANGED:
 1784                 if (fmsg == NULL) {
 1785                         fmsg = "Port Changed";
 1786                 }
 1787                 isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
 1788                 break;
 1789 
 1790         case CT7_INVRXID:
 1791                 /*
 1792                  * CTIO rejected by the firmware because an invalid RX_ID.
 1793                  * Just print a message.
 1794                  */
 1795                 isp_prt(isp, ISP_LOGWARN, "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
 1796                 break;
 1797 
 1798         case CT7_REASSY_ERR:
 1799                 isp_prt(isp, ISP_LOGWARN, "reassembly error");
 1800                 break;
 1801 
 1802         case CT7_SRR:
 1803                 isp_prt(isp, ISP_LOGWARN, "SRR received");
 1804                 break;
 1805 
 1806         default:
 1807                 isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", ct->ct_nphdl);
 1808                 break;
 1809         }
 1810 
 1811         if (xs == NULL) {
 1812                 /*
 1813                  * There may be more than one CTIO for a data transfer,
 1814                  * or this may be a status CTIO we're not monitoring.
 1815                  *
 1816                  * The assumption is that they'll all be returned in the
 1817                  * order we got them.
 1818                  */
 1819                 if (ct->ct_syshandle == 0) {
 1820                         if (ct->ct_flags & CT7_TERMINATE) {
 1821                                 isp_prt(isp, ISP_LOGINFO, "termination of 0x%x complete", ct->ct_rxid);
 1822                         } else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) {
 1823                                 isp_prt(isp, pl, "intermediate CTIO completed ok");
 1824                         } else {
 1825                                 isp_prt(isp, pl, "unmonitored CTIO completed ok");
 1826                         }
 1827                 } else {
 1828                         isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_nphdl);
 1829                 }
 1830         } else {
 1831                 if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) {
 1832                         ISP_DMAFREE(isp, xs, ct->ct_syshandle);
 1833                 }
 1834                 if (ct->ct_flags & CT7_SENDSTATUS) {
 1835                         /*
 1836                          * Sent status and command complete.
 1837                          *
 1838                          * We're now really done with this command, so we
 1839                          * punt to the platform dependent layers because
 1840                          * only there can we do the appropriate command
 1841                          * complete thread synchronization.
 1842                          */
 1843                         isp_prt(isp, pl, "status CTIO complete");
 1844                 } else {
 1845                         /*
 1846                          * Final CTIO completed. Release DMA resources and
 1847                          * notify platform dependent layers.
 1848                          */
 1849                         isp_prt(isp, pl, "data CTIO complete");
 1850                 }
 1851                 isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
 1852                 /*
 1853                  * The platform layer will destroy the handle if appropriate.
 1854                  */
 1855         }
 1856 }
 1857 
 1858 static void
 1859 isp_handle_24xx_inotify(ispsoftc_t *isp, in_fcentry_24xx_t *inot_24xx)
 1860 {
 1861         uint8_t ochan, chan, lochan, hichan;
 1862 
 1863         /*
 1864          * Check to see whether we got a wildcard channel.
 1865          * If so, we have to iterate over all channels.
 1866          */
 1867         ochan = chan = ISP_GET_VPIDX(isp, inot_24xx->in_vpidx);
 1868         if (chan == 0xff) {
 1869                 lochan = 0;
 1870                 hichan = isp->isp_nchan;
 1871         } else {
 1872                 if (chan >= isp->isp_nchan) {
 1873                         char buf[64];
 1874                         ISP_SNPRINTF(buf, sizeof buf, "%s: bad channel %d for status 0x%x", __func__, chan, inot_24xx->in_status);
 1875                         isp_print_bytes(isp, buf, QENTRY_LEN, inot_24xx);
 1876                         (void) isp_notify_ack(isp, inot_24xx);
 1877                         return;
 1878                 }
 1879                 lochan = chan;
 1880                 hichan = chan + 1;
 1881         }
 1882         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);
 1883         for (chan = lochan; chan < hichan; chan++) {
 1884                 switch (inot_24xx->in_status) {
 1885                 case IN24XX_LIP_RESET:
 1886                 case IN24XX_LINK_RESET:
 1887                 case IN24XX_PORT_LOGOUT:
 1888                 case IN24XX_PORT_CHANGED:
 1889                 case IN24XX_LINK_FAILED:
 1890                 case IN24XX_SRR_RCVD:
 1891                 case IN24XX_ELS_RCVD:
 1892                         inot_24xx->in_vpidx = chan;
 1893                         isp_async(isp, ISPASYNC_TARGET_ACTION, inot_24xx);
 1894                         break;
 1895                 default:
 1896                         isp_prt(isp, ISP_LOGINFO, "%s: unhandled status (0x%x) for chan %d", __func__, inot_24xx->in_status, chan);
 1897                         (void) isp_notify_ack(isp, inot_24xx);
 1898                         break;
 1899                 }
 1900         }
 1901         inot_24xx->in_vpidx = ochan;
 1902 }
 1903 #endif

Cache object: 4dc6e31ee7cc991e38151b8aedd44ead


[ 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.