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/isp/isp.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  *  Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org>
    5  *  Copyright (c) 1997-2009 by Matthew Jacob
    6  *  All rights reserved.
    7  *
    8  *  Redistribution and use in source and binary forms, with or without
    9  *  modification, are permitted provided that the following conditions
   10  *  are met:
   11  *
   12  *  1. Redistributions of source code must retain the above copyright
   13  *     notice, this list of conditions and the following disclaimer.
   14  *  2. Redistributions in binary form must reproduce the above copyright
   15  *     notice, this list of conditions and the following disclaimer in the
   16  *     documentation and/or other materials provided with the distribution.
   17  *
   18  *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   22  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  *  SUCH DAMAGE.
   29  *
   30  */
   31 
   32 /*
   33  * Machine and OS Independent (well, as best as possible)
   34  * code for the Qlogic ISP SCSI and FC-SCSI adapters.
   35  */
   36 
   37 /*
   38  * Inspiration and ideas about this driver are from Erik Moe's Linux driver
   39  * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
   40  * ideas dredged from the Solaris driver.
   41  */
   42 
   43 /*
   44  * Include header file appropriate for platform we're building on.
   45  */
   46 #ifdef  __NetBSD__
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD$");
   49 #include <dev/ic/isp_netbsd.h>
   50 #endif
   51 #ifdef  __FreeBSD__
   52 #include <sys/cdefs.h>
   53 __FBSDID("$FreeBSD$");
   54 #include <dev/isp/isp_freebsd.h>
   55 #endif
   56 #ifdef  __OpenBSD__
   57 #include <dev/ic/isp_openbsd.h>
   58 #endif
   59 #ifdef  __linux__
   60 #include "isp_linux.h"
   61 #endif
   62 #ifdef  __svr4__
   63 #include "isp_solaris.h"
   64 #endif
   65 
   66 /*
   67  * Local static data
   68  */
   69 static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)";
   70 static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
   71 static const char lipd[] = "Chan %d LIP destroyed %d active commands";
   72 static const char sacq[] = "unable to acquire scratch area";
   73 
   74 static const uint8_t alpa_map[] = {
   75         0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
   76         0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
   77         0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
   78         0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
   79         0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
   80         0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
   81         0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
   82         0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
   83         0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
   84         0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
   85         0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
   86         0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
   87         0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
   88         0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
   89         0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
   90         0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
   91 };
   92 
   93 /*
   94  * Local function prototypes.
   95  */
   96 static int isp_handle_control(ispsoftc_t *, isphdr_t *);
   97 static void isp_handle_rpt_id_acq(ispsoftc_t *, isphdr_t *);
   98 static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *);
   99 static void isp_clear_portdb(ispsoftc_t *, int);
  100 static void isp_mark_portdb(ispsoftc_t *, int);
  101 static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int);
  102 static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *);
  103 static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int);
  104 static void isp_dump_chip_portdb(ispsoftc_t *, int);
  105 static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
  106 static int isp_fclink_test(ispsoftc_t *, int, int);
  107 static int isp_pdb_sync(ispsoftc_t *, int);
  108 static int isp_scan_loop(ispsoftc_t *, int);
  109 static int isp_gid_pt(ispsoftc_t *, int);
  110 static int isp_scan_fabric(ispsoftc_t *, int);
  111 static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
  112 static int isp_register_fc4_type(ispsoftc_t *, int);
  113 static int isp_register_fc4_features_24xx(ispsoftc_t *, int);
  114 static int isp_register_port_name_24xx(ispsoftc_t *, int);
  115 static int isp_register_node_name_24xx(ispsoftc_t *, int);
  116 static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
  117 static int isp_fw_state(ispsoftc_t *, int);
  118 static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
  119 
  120 static void isp_setdfltfcparm(ispsoftc_t *, int);
  121 static int isp_read_nvram(ispsoftc_t *, int);
  122 static int isp_read_nvram_2400(ispsoftc_t *);
  123 static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
  124 static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
  125 
  126 static void
  127 isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
  128 {
  129         fcparam *fcp = FCPARAM(isp, chan);
  130 
  131         if (fcp->isp_fwstate == state)
  132                 return;
  133         isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
  134             "Chan %d Firmware state <%s->%s>", chan,
  135             isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
  136         fcp->isp_fwstate = state;
  137 }
  138 
  139 /*
  140  * Reset Hardware.
  141  *
  142  * Hit the chip over the head, download new f/w if available and set it running.
  143  *
  144  * Locking done elsewhere.
  145  */
  146 
  147 void
  148 isp_reset(ispsoftc_t *isp, int do_load_defaults)
  149 {
  150         mbreg_t mbs;
  151         char *buf;
  152         uint64_t fwt;
  153         uint32_t code_org, val;
  154         int loaded_fw, loops, i, dodnld = 1;
  155         const char *btype = "????";
  156         static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
  157 
  158         isp->isp_state = ISP_NILSTATE;
  159         ISP_DISABLE_INTS(isp);
  160 
  161         /*
  162          * Put the board into PAUSE mode (so we can read the SXP registers
  163          * or write FPM/FBM registers).
  164          */
  165         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
  166         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
  167         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
  168 
  169         switch (isp->isp_type) {
  170         case ISP_HA_FC_2400:
  171                 btype = "2422";
  172                 break;
  173         case ISP_HA_FC_2500:
  174                 btype = "2532";
  175                 break;
  176         case ISP_HA_FC_2600:
  177                 btype = "2600";
  178                 break;
  179         case ISP_HA_FC_2700:
  180                 btype = "2700";
  181                 break;
  182         default:
  183                 break;
  184         }
  185 
  186         /*
  187          * Stop DMA and wait for it to stop.
  188          */
  189         ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
  190         for (loops = 0; loops < 100000; loops++) {
  191                 ISP_DELAY(10);
  192                 val = ISP_READ(isp, BIU2400_CSR);
  193                 if ((val & BIU2400_DMA_ACTIVE) == 0) {
  194                         break;
  195                 }
  196         }
  197         if (val & BIU2400_DMA_ACTIVE)
  198                 isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
  199 
  200         /*
  201          * Hold it in SOFT_RESET and STOP state for 100us.
  202          */
  203         ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
  204         ISP_DELAY(100);
  205         for (loops = 0; loops < 10000; loops++) {
  206                 ISP_DELAY(5);
  207                 val = ISP_READ(isp, OUTMAILBOX0);
  208                 if (val != 0x4)
  209                         break;
  210         }
  211         switch (val) {
  212         case 0x0:
  213                 break;
  214         case 0x4:
  215                 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
  216                 return;
  217         case 0xf:
  218                 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
  219                 return;
  220         default:
  221                 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
  222                 return;
  223         }
  224 
  225         /*
  226          * Reset RISC Processor
  227          */
  228         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
  229         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
  230         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
  231 
  232         /*
  233          * Post-RISC Reset stuff.
  234          */
  235         for (loops = 0; loops < 10000; loops++) {
  236                 ISP_DELAY(5);
  237                 val = ISP_READ(isp, OUTMAILBOX0);
  238                 if (val != 0x4)
  239                         break;
  240         }
  241         switch (val) {
  242         case 0x0:
  243                 break;
  244         case 0x4:
  245                 isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
  246                 return;
  247         case 0xf:
  248                 isp_prt(isp, ISP_LOGERR, "Board configuration error.");
  249                 return;
  250         default:
  251                 isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
  252                 return;
  253         }
  254 
  255         isp->isp_reqidx = isp->isp_reqodx = 0;
  256         isp->isp_resodx = 0;
  257         isp->isp_atioodx = 0;
  258         ISP_WRITE(isp, BIU2400_REQINP, 0);
  259         ISP_WRITE(isp, BIU2400_REQOUTP, 0);
  260         ISP_WRITE(isp, BIU2400_RSPINP, 0);
  261         ISP_WRITE(isp, BIU2400_RSPOUTP, 0);
  262         if (!IS_26XX(isp)) {
  263                 ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
  264                 ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
  265         }
  266         ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
  267         ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
  268 
  269         /*
  270          * Up until this point we've done everything by just reading or
  271          * setting registers. From this point on we rely on at least *some*
  272          * kind of firmware running in the card.
  273          */
  274 
  275         /*
  276          * Do some sanity checking by running a NOP command.
  277          * If it succeeds, the ROM firmware is now running.
  278          */
  279         MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0);
  280         isp_mboxcmd(isp, &mbs);
  281         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  282                 isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
  283                 return;
  284         }
  285 
  286         /*
  287          * Do some operational tests
  288          */
  289         {
  290                 static const uint16_t patterns[MAX_MAILBOX] = {
  291                         0x0000, 0xdead, 0xbeef, 0xffff,
  292                         0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7,
  293                         0x3421, 0xabcd, 0xdcba, 0xfeef,
  294                         0xbead, 0xdebe, 0x2222, 0x3333,
  295                         0x5555, 0x6666, 0x7777, 0xaaaa,
  296                         0xffff, 0xdddd, 0x9999, 0x1fbc,
  297                         0x6666, 0x6677, 0x1122, 0x33ff,
  298                         0x0000, 0x0001, 0x1000, 0x1010,
  299                 };
  300                 int nmbox = ISP_NMBOX(isp);
  301                 MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0);
  302                 for (i = 1; i < nmbox; i++) {
  303                         mbs.param[i] = patterns[i];
  304                 }
  305                 isp_mboxcmd(isp, &mbs);
  306                 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  307                         return;
  308                 }
  309                 for (i = 1; i < nmbox; i++) {
  310                         if (mbs.param[i] != patterns[i]) {
  311                                 isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]);
  312                                 return;
  313                         }
  314                 }
  315         }
  316 
  317         /*
  318          * Download new Firmware, unless requested not to do so.
  319          * This is made slightly trickier in some cases where the
  320          * firmware of the ROM revision is newer than the revision
  321          * compiled into the driver. So, where we used to compare
  322          * versions of our f/w and the ROM f/w, now we just see
  323          * whether we have f/w at all and whether a config flag
  324          * has disabled our download.
  325          */
  326         if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
  327                 dodnld = 0;
  328         } else {
  329 
  330                 /*
  331                  * Set up DMA for the request and response queues.
  332                  * We do this now so we can use the request queue
  333                  * for dma to load firmware from.
  334                  */
  335                 if (ISP_MBOXDMASETUP(isp) != 0) {
  336                         isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
  337                         return;
  338                 }
  339         }
  340 
  341         code_org = ISP_CODE_ORG_2400;
  342         loaded_fw = 0;
  343         if (dodnld) {
  344                 const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
  345                 uint32_t la, wi, wl;
  346 
  347                 /*
  348                  * Keep loading until we run out of f/w.
  349                  */
  350                 code_org = ptr[2];      /* 1st load address is our start addr */
  351                 for (;;) {
  352                         isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
  353 
  354                         wi = 0;
  355                         la = ptr[2];
  356                         wl = ptr[3];
  357                         while (wi < ptr[3]) {
  358                                 uint32_t *cp;
  359                                 uint32_t nw;
  360 
  361                                 nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4);
  362                                 cp = isp->isp_rquest;
  363                                 for (i = 0; i < nw; i++)
  364                                         ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]);
  365                                 MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1);
  366                                 MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0);
  367                                 mbs.param[1] = la;
  368                                 mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
  369                                 mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
  370                                 mbs.param[4] = nw >> 16;
  371                                 mbs.param[5] = nw;
  372                                 mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
  373                                 mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
  374                                 mbs.param[8] = la >> 16;
  375                                 isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la);
  376                                 isp_mboxcmd(isp, &mbs);
  377                                 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  378                                         isp_prt(isp, ISP_LOGERR, "F/W download failed");
  379                                         return;
  380                                 }
  381                                 la += nw;
  382                                 wi += nw;
  383                                 wl -= nw;
  384                         }
  385 
  386                         if (ptr[1] == 0) {
  387                                 break;
  388                         }
  389                         ptr += ptr[3];
  390                 }
  391                 loaded_fw = 1;
  392         } else if (IS_26XX(isp)) {
  393                 isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash");
  394                 MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
  395                 mbs.ibitm = 0x01;
  396                 mbs.obitm = 0x07;
  397                 isp_mboxcmd(isp, &mbs);
  398                 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  399                         isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
  400                         return;
  401                 }
  402         } else {
  403                 isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
  404         }
  405 
  406         /*
  407          * If we loaded firmware, verify its checksum
  408          */
  409         if (loaded_fw) {
  410                 MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
  411                 mbs.param[1] = code_org >> 16;
  412                 mbs.param[2] = code_org;
  413                 isp_mboxcmd(isp, &mbs);
  414                 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  415                         isp_prt(isp, ISP_LOGERR, dcrc);
  416                         return;
  417                 }
  418         }
  419 
  420         /*
  421          * Now start it rolling.
  422          *
  423          * If we didn't actually download f/w,
  424          * we still need to (re)start it.
  425          */
  426         MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
  427         mbs.param[1] = code_org >> 16;
  428         mbs.param[2] = code_org;
  429         if (!IS_26XX(isp))
  430                 mbs.param[3] = loaded_fw ? 0 : 1;
  431         isp_mboxcmd(isp, &mbs);
  432         if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
  433                 return;
  434 
  435         /*
  436          * Ask the chip for the current firmware version.
  437          * This should prove that the new firmware is working.
  438          */
  439         MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
  440         isp_mboxcmd(isp, &mbs);
  441         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  442                 return;
  443         }
  444 
  445         isp->isp_fwrev[0] = mbs.param[1];
  446         isp->isp_fwrev[1] = mbs.param[2];
  447         isp->isp_fwrev[2] = mbs.param[3];
  448         isp->isp_fwattr = mbs.param[6];
  449         isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16;
  450         if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) {
  451                 isp->isp_fwattr |=
  452                     (((uint64_t) mbs.param[16]) << 32) |
  453                     (((uint64_t) mbs.param[17]) << 48);
  454         }
  455 
  456         isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
  457             btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
  458 
  459         fwt = isp->isp_fwattr;
  460         buf = FCPARAM(isp, 0)->isp_scanscratch;
  461         ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:");
  462         if (fwt & ISP2400_FW_ATTR_CLASS2) {
  463                 fwt ^=ISP2400_FW_ATTR_CLASS2;
  464                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf);
  465         }
  466         if (fwt & ISP2400_FW_ATTR_IP) {
  467                 fwt ^=ISP2400_FW_ATTR_IP;
  468                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf);
  469         }
  470         if (fwt & ISP2400_FW_ATTR_MULTIID) {
  471                 fwt ^=ISP2400_FW_ATTR_MULTIID;
  472                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf);
  473         }
  474         if (fwt & ISP2400_FW_ATTR_SB2) {
  475                 fwt ^=ISP2400_FW_ATTR_SB2;
  476                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf);
  477         }
  478         if (fwt & ISP2400_FW_ATTR_T10CRC) {
  479                 fwt ^=ISP2400_FW_ATTR_T10CRC;
  480                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf);
  481         }
  482         if (fwt & ISP2400_FW_ATTR_VI) {
  483                 fwt ^=ISP2400_FW_ATTR_VI;
  484                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf);
  485         }
  486         if (fwt & ISP2400_FW_ATTR_MQ) {
  487                 fwt ^=ISP2400_FW_ATTR_MQ;
  488                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf);
  489         }
  490         if (fwt & ISP2400_FW_ATTR_MSIX) {
  491                 fwt ^=ISP2400_FW_ATTR_MSIX;
  492                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf);
  493         }
  494         if (fwt & ISP2400_FW_ATTR_FCOE) {
  495                 fwt ^=ISP2400_FW_ATTR_FCOE;
  496                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf);
  497         }
  498         if (fwt & ISP2400_FW_ATTR_VP0) {
  499                 fwt ^= ISP2400_FW_ATTR_VP0;
  500                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf);
  501         }
  502         if (fwt & ISP2400_FW_ATTR_EXPFW) {
  503                 fwt ^= ISP2400_FW_ATTR_EXPFW;
  504                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf);
  505         }
  506         if (fwt & ISP2400_FW_ATTR_HOTFW) {
  507                 fwt ^= ISP2400_FW_ATTR_HOTFW;
  508                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf);
  509         }
  510         fwt &= ~ISP2400_FW_ATTR_EXTNDED;
  511         if (fwt & ISP2400_FW_ATTR_EXTVP) {
  512                 fwt ^= ISP2400_FW_ATTR_EXTVP;
  513                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf);
  514         }
  515         if (fwt & ISP2400_FW_ATTR_VN2VN) {
  516                 fwt ^= ISP2400_FW_ATTR_VN2VN;
  517                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf);
  518         }
  519         if (fwt & ISP2400_FW_ATTR_EXMOFF) {
  520                 fwt ^= ISP2400_FW_ATTR_EXMOFF;
  521                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf);
  522         }
  523         if (fwt & ISP2400_FW_ATTR_NPMOFF) {
  524                 fwt ^= ISP2400_FW_ATTR_NPMOFF;
  525                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf);
  526         }
  527         if (fwt & ISP2400_FW_ATTR_DIFCHOP) {
  528                 fwt ^= ISP2400_FW_ATTR_DIFCHOP;
  529                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf);
  530         }
  531         if (fwt & ISP2400_FW_ATTR_SRIOV) {
  532                 fwt ^= ISP2400_FW_ATTR_SRIOV;
  533                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf);
  534         }
  535         if (fwt & ISP2400_FW_ATTR_ASICTMP) {
  536                 fwt ^= ISP2400_FW_ATTR_ASICTMP;
  537                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf);
  538         }
  539         if (fwt & ISP2400_FW_ATTR_ATIOMQ) {
  540                 fwt ^= ISP2400_FW_ATTR_ATIOMQ;
  541                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf);
  542         }
  543         if (fwt) {
  544                 ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
  545                     (uint32_t) (fwt >> 32), (uint32_t) fwt);
  546         }
  547         isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
  548 
  549         /*
  550          * For the maximum number of commands take free exchange control block
  551          * buffer count reported by firmware, limiting it to the maximum of our
  552          * hardcoded handle format (16K now) minus some management reserve.
  553          */
  554         MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
  555         isp_mboxcmd(isp, &mbs);
  556         if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
  557                 return;
  558         isp->isp_maxcmds = MIN(mbs.param[3], ISP_HANDLE_MAX - ISP_HANDLE_RESERVE);
  559         isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
  560 
  561         /*
  562          * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
  563          * Only make this check for non-SCSI cards (I'm not sure firmware attributes
  564          * work for them).
  565          */
  566         if (isp->isp_nchan > 1) {
  567                 if (!ISP_CAP_MULTI_ID(isp)) {
  568                         isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, "
  569                             "only can enable 1 of %d channels", isp->isp_nchan);
  570                         isp->isp_nchan = 1;
  571                 } else if (!ISP_CAP_VP0(isp)) {
  572                         isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
  573                             "feature properly without VP0_Decoupling");
  574                         isp->isp_nchan = 1;
  575                 }
  576         }
  577 
  578         /*
  579          * Final DMA setup after we got isp_maxcmds.
  580          */
  581         if (ISP_MBOXDMASETUP(isp) != 0) {
  582                 isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
  583                 return;
  584         }
  585 
  586         /*
  587          * Setup interrupts.
  588          */
  589         if (ISP_IRQSETUP(isp) != 0) {
  590                 isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
  591                 return;
  592         }
  593         ISP_ENABLE_INTS(isp);
  594 
  595         for (i = 0; i < isp->isp_nchan; i++)
  596                 isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
  597 
  598         isp->isp_state = ISP_RESETSTATE;
  599 
  600         /*
  601          * We get some default values established. As a side
  602          * effect, NVRAM is read here (unless overridden by
  603          * a configuration flag).
  604          */
  605         if (do_load_defaults) {
  606                 for (i = 0; i < isp->isp_nchan; i++)
  607                         isp_setdfltfcparm(isp, i);
  608         }
  609 }
  610 
  611 /*
  612  * Clean firmware shutdown.
  613  */
  614 static int
  615 isp_stop(ispsoftc_t *isp)
  616 {
  617         mbreg_t mbs;
  618 
  619         isp->isp_state = ISP_NILSTATE;
  620         MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
  621         mbs.param[1] = 0;
  622         mbs.param[2] = 0;
  623         mbs.param[3] = 0;
  624         mbs.param[4] = 0;
  625         mbs.param[5] = 0;
  626         mbs.param[6] = 0;
  627         mbs.param[7] = 0;
  628         mbs.param[8] = 0;
  629         isp_mboxcmd(isp, &mbs);
  630         return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
  631 }
  632 
  633 /*
  634  * Hardware shutdown.
  635  */
  636 void
  637 isp_shutdown(ispsoftc_t *isp)
  638 {
  639 
  640         if (isp->isp_state >= ISP_RESETSTATE)
  641                 isp_stop(isp);
  642         ISP_DISABLE_INTS(isp);
  643         ISP_WRITE(isp, BIU2400_ICR, 0);
  644         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
  645 }
  646 
  647 /*
  648  * Initialize Parameters of Hardware to a known state.
  649  *
  650  * Locks are held before coming here.
  651  */
  652 void
  653 isp_init(ispsoftc_t *isp)
  654 {
  655         fcparam *fcp;
  656         isp_icb_2400_t local, *icbp = &local;
  657         mbreg_t mbs;
  658         int chan;
  659         int ownloopid = 0;
  660 
  661         /*
  662          * Check to see whether all channels have *some* kind of role
  663          */
  664         for (chan = 0; chan < isp->isp_nchan; chan++) {
  665                 fcp = FCPARAM(isp, chan);
  666                 if (fcp->role != ISP_ROLE_NONE) {
  667                         break;
  668                 }
  669         }
  670         if (chan == isp->isp_nchan) {
  671                 isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
  672                 return;
  673         }
  674 
  675         isp->isp_state = ISP_INITSTATE;
  676 
  677         /*
  678          * Start with channel 0.
  679          */
  680         fcp = FCPARAM(isp, 0);
  681 
  682         /*
  683          * Turn on LIP F8 async event (1)
  684          */
  685         MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
  686         mbs.param[1] = 1;
  687         isp_mboxcmd(isp, &mbs);
  688         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
  689                 return;
  690         }
  691 
  692         ISP_MEMZERO(icbp, sizeof (*icbp));
  693         icbp->icb_fwoptions1 = fcp->isp_fwoptions;
  694         icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
  695         icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
  696         if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) {
  697                 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
  698                 icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
  699         } else {
  700                 if (fcp->role & ISP_ROLE_TARGET)
  701                         icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
  702                 else
  703                         icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
  704                 if (fcp->role & ISP_ROLE_INITIATOR)
  705                         icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
  706                 else
  707                         icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
  708         }
  709 
  710         icbp->icb_version = ICB_VERSION1;
  711         icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
  712         if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
  713                 isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
  714                 icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
  715         }
  716 
  717         if (!IS_26XX(isp))
  718                 icbp->icb_execthrottle = 0xffff;
  719 
  720 #ifdef  ISP_TARGET_MODE
  721         /*
  722          * Set target exchange count. Take half if we are supporting both roles.
  723          */
  724         if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
  725                 if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0)
  726                         icbp->icb_xchgcnt = MIN(isp->isp_maxcmds / 2, ATPDPSIZE);
  727                 else
  728                         icbp->icb_xchgcnt = isp->isp_maxcmds;
  729         }
  730 #endif
  731 
  732         ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
  733         icbp->icb_hardaddr = fcp->isp_loopid;
  734         if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
  735                 icbp->icb_hardaddr = 0;
  736                 ownloopid = 0;
  737         }
  738 
  739         if (ownloopid)
  740                 icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
  741 
  742         if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
  743                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
  744         }
  745         if (isp->isp_confopts & ISP_CFG_FCTAPE) {
  746                 icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
  747         }
  748 
  749         for (chan = 0; chan < isp->isp_nchan; chan++) {
  750                 if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
  751                         FCPARAM(isp, chan)->fctape_enabled = 1;
  752                 else
  753                         FCPARAM(isp, chan)->fctape_enabled = 0;
  754         }
  755 
  756         switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
  757         case ISP_CFG_LPORT_ONLY:
  758                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
  759                 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
  760                 break;
  761         case ISP_CFG_NPORT_ONLY:
  762                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
  763                 icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
  764                 break;
  765         case ISP_CFG_NPORT:
  766                 /* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
  767         case ISP_CFG_LPORT:
  768                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
  769                 icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
  770                 break;
  771         default:
  772                 /* Let NVRAM settings define it if they are sane */
  773                 switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) {
  774                 case ICB2400_OPT2_LOOP_ONLY:
  775                 case ICB2400_OPT2_PTP_ONLY:
  776                 case ICB2400_OPT2_LOOP_2_PTP:
  777                         break;
  778                 default:
  779                         icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
  780                         icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
  781                 }
  782                 break;
  783         }
  784 
  785         switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
  786         case ICB2400_OPT2_ZIO:
  787         case ICB2400_OPT2_ZIO1:
  788                 icbp->icb_idelaytimer = 0;
  789                 break;
  790         case 0:
  791                 break;
  792         default:
  793                 isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
  794                 icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
  795                 break;
  796         }
  797 
  798         if (IS_26XX(isp)) {
  799                 /* Use handshake to reduce global lock congestion. */
  800                 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
  801                 icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
  802         }
  803 
  804         if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
  805                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
  806         }
  807         if (isp->isp_confopts & ISP_CFG_1GB) {
  808                 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  809                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
  810         } else if (isp->isp_confopts & ISP_CFG_2GB) {
  811                 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  812                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
  813         } else if (isp->isp_confopts & ISP_CFG_4GB) {
  814                 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  815                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
  816         } else if (isp->isp_confopts & ISP_CFG_8GB) {
  817                 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  818                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
  819         } else if (isp->isp_confopts & ISP_CFG_16GB) {
  820                 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  821                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
  822         } else if (isp->isp_confopts & ISP_CFG_32GB) {
  823                 icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  824                 icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
  825         } else {
  826                 switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
  827                 case ICB2400_OPT3_RATE_4GB:
  828                 case ICB2400_OPT3_RATE_8GB:
  829                 case ICB2400_OPT3_RATE_16GB:
  830                 case ICB2400_OPT3_RATE_32GB:
  831                 case ICB2400_OPT3_RATE_AUTO:
  832                         break;
  833                 case ICB2400_OPT3_RATE_2GB:
  834                         if (isp->isp_type <= ISP_HA_FC_2500)
  835                                 break;
  836                         /*FALLTHROUGH*/
  837                 case ICB2400_OPT3_RATE_1GB:
  838                         if (isp->isp_type <= ISP_HA_FC_2400)
  839                                 break;
  840                         /*FALLTHROUGH*/
  841                 default:
  842                         icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
  843                         icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
  844                         break;
  845                 }
  846         }
  847         if (ownloopid == 0) {
  848                 icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
  849         }
  850         icbp->icb_logintime = ICB_LOGIN_TOV;
  851 
  852         if (fcp->isp_wwnn && fcp->isp_wwpn) {
  853                 icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
  854                 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
  855                 MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
  856                 isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwnn >> 32)), ((uint32_t) (fcp->isp_wwnn)),
  857                     ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
  858         } else if (fcp->isp_wwpn) {
  859                 icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
  860                 MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
  861                 isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node to be same as Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
  862         } else {
  863                 isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
  864                 return;
  865         }
  866         icbp->icb_rspnsin = isp->isp_resodx;
  867         icbp->icb_rqstout = isp->isp_reqidx;
  868         icbp->icb_retry_count = fcp->isp_retry_count;
  869 
  870         icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
  871         if (icbp->icb_rqstqlen < 8) {
  872                 isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
  873                 return;
  874         }
  875         icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
  876         if (icbp->icb_rsltqlen < 8) {
  877                 isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
  878                     icbp->icb_rsltqlen);
  879                 return;
  880         }
  881         icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
  882         icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
  883         icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
  884         icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
  885 
  886         icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
  887         icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
  888         icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
  889         icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
  890 
  891 #ifdef  ISP_TARGET_MODE
  892         /* unconditionally set up the ATIO queue if we support target mode */
  893         icbp->icb_atio_in = isp->isp_atioodx;
  894         icbp->icb_atioqlen = ATIO_QUEUE_LEN(isp);
  895         if (icbp->icb_atioqlen < 8) {
  896                 isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
  897                 return;
  898         }
  899         icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
  900         icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
  901         icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
  902         icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
  903         isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
  904             DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
  905 #endif
  906 
  907         if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) {
  908                 icbp->icb_msixresp = 1;
  909                 if (IS_26XX(isp) && isp->isp_nirq >= 3)
  910                         icbp->icb_msixatio = 2;
  911         }
  912 
  913         isp_prt(isp, ISP_LOGDEBUG0, "isp_init: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
  914 
  915         isp_prt(isp, ISP_LOGDEBUG0, "isp_init: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
  916             DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
  917             DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
  918 
  919         if (FC_SCRATCH_ACQUIRE(isp, 0)) {
  920                 isp_prt(isp, ISP_LOGERR, sacq);
  921                 return;
  922         }
  923         ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
  924         isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
  925         if (isp->isp_dblev & ISP_LOGDEBUG1) {
  926                 isp_print_bytes(isp, "isp_init",
  927                     sizeof (*icbp), fcp->isp_scratch);
  928         }
  929 
  930         /*
  931          * Now fill in information about any additional channels
  932          */
  933         if (isp->isp_nchan > 1) {
  934                 isp_icb_2400_vpinfo_t vpinfo, *vdst;
  935                 vp_port_info_t pi, *pdst;
  936                 size_t amt = 0;
  937                 uint8_t *off;
  938 
  939                 vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
  940                 if (ISP_CAP_VP0(isp)) {
  941                         vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
  942                         vpinfo.vp_count = isp->isp_nchan;
  943                         chan = 0;
  944                 } else {
  945                         vpinfo.vp_count = isp->isp_nchan - 1;
  946                         chan = 1;
  947                 }
  948                 off = fcp->isp_scratch;
  949                 off += ICB2400_VPINFO_OFF;
  950                 vdst = (isp_icb_2400_vpinfo_t *) off;
  951                 isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
  952                 amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
  953                 for (; chan < isp->isp_nchan; chan++) {
  954                         fcparam *fcp2;
  955 
  956                         ISP_MEMZERO(&pi, sizeof (pi));
  957                         fcp2 = FCPARAM(isp, chan);
  958                         if (fcp2->role != ISP_ROLE_NONE) {
  959                                 pi.vp_port_options = ICB2400_VPOPT_ENABLED |
  960                                     ICB2400_VPOPT_ENA_SNSLOGIN;
  961                                 if (fcp2->role & ISP_ROLE_INITIATOR)
  962                                         pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
  963                                 if ((fcp2->role & ISP_ROLE_TARGET) == 0)
  964                                         pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
  965                                 if (fcp2->isp_loopid < LOCAL_LOOP_LIM) {
  966                                         pi.vp_port_loopid = fcp2->isp_loopid;
  967                                         if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
  968                                                 pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS;
  969                                 }
  970 
  971                         }
  972                         MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
  973                         MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
  974                         off = fcp->isp_scratch;
  975                         if (ISP_CAP_VP0(isp))
  976                                 off += ICB2400_VPINFO_PORT_OFF(chan);
  977                         else
  978                                 off += ICB2400_VPINFO_PORT_OFF(chan - 1);
  979                         pdst = (vp_port_info_t *) off;
  980                         isp_put_vp_port_info(isp, &pi, pdst);
  981                         amt += ICB2400_VPOPT_WRITE_SIZE;
  982                 }
  983                 if (isp->isp_dblev & ISP_LOGDEBUG1) {
  984                         isp_print_bytes(isp, "isp_init",
  985                             amt - ICB2400_VPINFO_OFF,
  986                             (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF);
  987                 }
  988         }
  989 
  990         /*
  991          * Init the firmware
  992          */
  993         MBSINIT(&mbs, 0, MBLOGALL, 30000000);
  994         if (isp->isp_nchan > 1) {
  995                 mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
  996         } else {
  997                 mbs.param[0] = MBOX_INIT_FIRMWARE;
  998         }
  999         mbs.param[1] = 0;
 1000         mbs.param[2] = DMA_WD1(fcp->isp_scdma);
 1001         mbs.param[3] = DMA_WD0(fcp->isp_scdma);
 1002         mbs.param[6] = DMA_WD3(fcp->isp_scdma);
 1003         mbs.param[7] = DMA_WD2(fcp->isp_scdma);
 1004         isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma));
 1005         MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0);
 1006         isp_mboxcmd(isp, &mbs);
 1007         FC_SCRATCH_RELEASE(isp, 0);
 1008 
 1009         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 1010                 return;
 1011         }
 1012 
 1013         /*
 1014          * Whatever happens, we're now committed to being here.
 1015          */
 1016         isp->isp_state = ISP_RUNSTATE;
 1017 }
 1018 
 1019 static int
 1020 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
 1021 {
 1022         fcparam *fcp = FCPARAM(isp, chan);
 1023         vp_modify_t vp;
 1024         int retval;
 1025 
 1026         /* Build a VP MODIFY command in memory */
 1027         ISP_MEMZERO(&vp, sizeof(vp));
 1028         vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
 1029         vp.vp_mod_hdr.rqs_entry_count = 1;
 1030         vp.vp_mod_cnt = 1;
 1031         vp.vp_mod_idx0 = chan;
 1032         vp.vp_mod_cmd = VP_MODIFY_ENA;
 1033         vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
 1034             ICB2400_VPOPT_ENA_SNSLOGIN;
 1035         if (fcp->role & ISP_ROLE_INITIATOR)
 1036                 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
 1037         if ((fcp->role & ISP_ROLE_TARGET) == 0)
 1038                 vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
 1039         if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
 1040                 vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
 1041                 if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
 1042                         vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
 1043         }
 1044         MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
 1045         MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
 1046 
 1047         retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
 1048         if (retval != 0) {
 1049                 isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of chan %d error %d",
 1050                     __func__, chan, retval);
 1051                 return (retval);
 1052         }
 1053 
 1054         if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
 1055                 isp_prt(isp, ISP_LOGERR,
 1056                     "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
 1057                     __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
 1058                 return (EIO);
 1059         }
 1060         return (0);
 1061 }
 1062 
 1063 static int
 1064 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
 1065 {
 1066         vp_ctrl_info_t vp;
 1067         int retval;
 1068 
 1069         /* Build a VP CTRL command in memory */
 1070         ISP_MEMZERO(&vp, sizeof(vp));
 1071         vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
 1072         vp.vp_ctrl_hdr.rqs_entry_count = 1;
 1073         if (ISP_CAP_VP0(isp)) {
 1074                 vp.vp_ctrl_status = 1;
 1075         } else {
 1076                 vp.vp_ctrl_status = 0;
 1077                 chan--; /* VP0 can not be controlled in this case. */
 1078         }
 1079         vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
 1080         vp.vp_ctrl_vp_count = 1;
 1081         vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
 1082 
 1083         retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
 1084         if (retval != 0) {
 1085                 isp_prt(isp, ISP_LOGERR, "%s: VP_CTRL of chan %d error %d",
 1086                     __func__, chan, retval);
 1087                 return (retval);
 1088         }
 1089 
 1090         if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
 1091                 isp_prt(isp, ISP_LOGERR,
 1092                     "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
 1093                     __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
 1094                     vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
 1095                 return (EIO);
 1096         }
 1097         return (0);
 1098 }
 1099 
 1100 static int
 1101 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
 1102 {
 1103         fcparam *fcp = FCPARAM(isp, chan);
 1104         int i, was, res = 0;
 1105 
 1106         if (chan >= isp->isp_nchan) {
 1107                 isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
 1108                 return (ENXIO);
 1109         }
 1110         if (fcp->role == new_role)
 1111                 return (0);
 1112         for (was = 0, i = 0; i < isp->isp_nchan; i++) {
 1113                 if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
 1114                         was++;
 1115         }
 1116         if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
 1117                 fcp->role = new_role;
 1118                 return (isp_reinit(isp, 0));
 1119         }
 1120         if (fcp->role != ISP_ROLE_NONE) {
 1121                 res = isp_fc_disable_vp(isp, chan);
 1122                 isp_clear_portdb(isp, chan);
 1123         }
 1124         fcp->role = new_role;
 1125         if (fcp->role != ISP_ROLE_NONE)
 1126                 res = isp_fc_enable_vp(isp, chan);
 1127         return (res);
 1128 }
 1129 
 1130 static void
 1131 isp_clear_portdb(ispsoftc_t *isp, int chan)
 1132 {
 1133         fcparam *fcp = FCPARAM(isp, chan);
 1134         fcportdb_t *lp;
 1135         int i;
 1136 
 1137         for (i = 0; i < MAX_FC_TARG; i++) {
 1138                 lp = &fcp->portdb[i];
 1139                 switch (lp->state) {
 1140                 case FC_PORTDB_STATE_DEAD:
 1141                 case FC_PORTDB_STATE_CHANGED:
 1142                 case FC_PORTDB_STATE_VALID:
 1143                         lp->state = FC_PORTDB_STATE_NIL;
 1144                         isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
 1145                         break;
 1146                 case FC_PORTDB_STATE_NIL:
 1147                 case FC_PORTDB_STATE_NEW:
 1148                         lp->state = FC_PORTDB_STATE_NIL;
 1149                         break;
 1150                 case FC_PORTDB_STATE_ZOMBIE:
 1151                         break;
 1152                 default:
 1153                         panic("Don't know how to clear state %d\n", lp->state);
 1154                 }
 1155         }
 1156 }
 1157 
 1158 static void
 1159 isp_mark_portdb(ispsoftc_t *isp, int chan)
 1160 {
 1161         fcparam *fcp = FCPARAM(isp, chan);
 1162         fcportdb_t *lp;
 1163         int i;
 1164 
 1165         for (i = 0; i < MAX_FC_TARG; i++) {
 1166                 lp = &fcp->portdb[i];
 1167                 if (lp->state == FC_PORTDB_STATE_NIL)
 1168                         continue;
 1169                 if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
 1170                     lp->portid <= DOMAIN_CONTROLLER_END)
 1171                         continue;
 1172                 fcp->portdb[i].probational = 1;
 1173         }
 1174 }
 1175 
 1176 /*
 1177  * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
 1178  * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
 1179  */
 1180 static int
 1181 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
 1182 {
 1183         isp_plogx_t pl;
 1184         uint32_t sst, parm1;
 1185         int retval, lev;
 1186         const char *msg;
 1187         char buf[64];
 1188 
 1189         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
 1190             chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
 1191             "Login":"Logout", portid, handle);
 1192 
 1193         ISP_MEMZERO(&pl, sizeof(pl));
 1194         pl.plogx_header.rqs_entry_count = 1;
 1195         pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
 1196         pl.plogx_nphdl = handle;
 1197         pl.plogx_vphdl = chan;
 1198         pl.plogx_portlo = portid;
 1199         pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
 1200         pl.plogx_flags = flags;
 1201 
 1202         retval = isp_exec_entry_queue(isp, &pl, &pl, 3 * ICB_LOGIN_TOV);
 1203         if (retval != 0) {
 1204                 isp_prt(isp, ISP_LOGERR, "%s: PLOGX of chan %d error %d",
 1205                     __func__, chan, retval);
 1206                 return (retval);
 1207         }
 1208 
 1209         if (pl.plogx_status == PLOGX_STATUS_OK) {
 1210                 return (0);
 1211         } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
 1212                 isp_prt(isp, ISP_LOGWARN,
 1213                     "status 0x%x on port login IOCB channel %d",
 1214                     pl.plogx_status, chan);
 1215                 return (-1);
 1216         }
 1217 
 1218         sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
 1219         parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
 1220 
 1221         retval = -1;
 1222         lev = ISP_LOGERR;
 1223         msg = NULL;
 1224 
 1225         switch (sst) {
 1226         case PLOGX_IOCBERR_NOLINK:
 1227                 msg = "no link";
 1228                 break;
 1229         case PLOGX_IOCBERR_NOIOCB:
 1230                 msg = "no IOCB buffer";
 1231                 break;
 1232         case PLOGX_IOCBERR_NOXGHG:
 1233                 msg = "no Exchange Control Block";
 1234                 break;
 1235         case PLOGX_IOCBERR_FAILED:
 1236                 ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
 1237                 msg = buf;
 1238                 break;
 1239         case PLOGX_IOCBERR_NOFABRIC:
 1240                 msg = "no fabric";
 1241                 break;
 1242         case PLOGX_IOCBERR_NOTREADY:
 1243                 msg = "firmware not ready";
 1244                 break;
 1245         case PLOGX_IOCBERR_NOLOGIN:
 1246                 ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
 1247                 msg = buf;
 1248                 retval = MBOX_NOT_LOGGED_IN;
 1249                 break;
 1250         case PLOGX_IOCBERR_REJECT:
 1251                 ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
 1252                 msg = buf;
 1253                 break;
 1254         case PLOGX_IOCBERR_NOPCB:
 1255                 msg = "no PCB allocated";
 1256                 break;
 1257         case PLOGX_IOCBERR_EINVAL:
 1258                 ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
 1259                 msg = buf;
 1260                 break;
 1261         case PLOGX_IOCBERR_PORTUSED:
 1262                 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
 1263                 ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
 1264                 msg = buf;
 1265                 retval = MBOX_PORT_ID_USED | (parm1 << 16);
 1266                 break;
 1267         case PLOGX_IOCBERR_HNDLUSED:
 1268                 lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
 1269                 ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
 1270                 msg = buf;
 1271                 retval = MBOX_LOOP_ID_USED;
 1272                 break;
 1273         case PLOGX_IOCBERR_NOHANDLE:
 1274                 msg = "no handle allocated";
 1275                 break;
 1276         case PLOGX_IOCBERR_NOFLOGI:
 1277                 msg = "no FLOGI_ACC";
 1278                 break;
 1279         default:
 1280                 ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
 1281                 msg = buf;
 1282                 break;
 1283         }
 1284         if (msg) {
 1285                 isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
 1286                     chan, portid, handle, msg);
 1287         }
 1288         return (retval);
 1289 }
 1290 
 1291 static int
 1292 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
 1293 {
 1294         mbreg_t mbs;
 1295         union {
 1296                 isp_pdb_24xx_t bill;
 1297         } un;
 1298 
 1299         MBSINIT(&mbs, MBOX_GET_PORT_DB,
 1300             MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
 1301         mbs.ibits = (1 << 9)|(1 << 10);
 1302         mbs.param[1] = id;
 1303         mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
 1304         mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
 1305         mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
 1306         mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
 1307         mbs.param[9] = chan;
 1308         MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan);
 1309 
 1310         isp_mboxcmd(isp, &mbs);
 1311         if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
 1312                 return (mbs.param[0] | (mbs.param[1] << 16));
 1313 
 1314         MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan);
 1315         isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill);
 1316         pdb->handle = un.bill.pdb_handle;
 1317         pdb->prli_word0 = un.bill.pdb_prli_svc0;
 1318         pdb->prli_word3 = un.bill.pdb_prli_svc3;
 1319         pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
 1320         ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
 1321         ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
 1322         isp_prt(isp, ISP_LOGDEBUG0,
 1323             "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x",
 1324             chan, id, pdb->portid, un.bill.pdb_flags,
 1325             un.bill.pdb_curstate, un.bill.pdb_laststate);
 1326 
 1327         if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
 1328                 mbs.param[0] = MBOX_NOT_LOGGED_IN;
 1329                 return (mbs.param[0]);
 1330         }
 1331         return (0);
 1332 }
 1333 
 1334 static int
 1335 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
 1336 {
 1337         fcparam *fcp = FCPARAM(isp, chan);
 1338         mbreg_t mbs;
 1339         isp_pnhle_24xx_t el4, *elp4;
 1340         int i, j;
 1341         uint32_t p;
 1342 
 1343         MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000);
 1344         mbs.param[2] = DMA_WD1(fcp->isp_scdma);
 1345         mbs.param[3] = DMA_WD0(fcp->isp_scdma);
 1346         mbs.param[6] = DMA_WD3(fcp->isp_scdma);
 1347         mbs.param[7] = DMA_WD2(fcp->isp_scdma);
 1348         mbs.param[8] = ISP_FC_SCRLEN;
 1349         mbs.param[9] = chan;
 1350         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 1351                 isp_prt(isp, ISP_LOGERR, sacq);
 1352                 return (-1);
 1353         }
 1354         MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
 1355         isp_mboxcmd(isp, &mbs);
 1356         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 1357                 FC_SCRATCH_RELEASE(isp, chan);
 1358                 return (mbs.param[0] | (mbs.param[1] << 16));
 1359         }
 1360         MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
 1361         elp4 = fcp->isp_scratch;
 1362         for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
 1363                 isp_get_pnhle_24xx(isp, &elp4[i], &el4);
 1364                 p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16);
 1365                 if (loop && (p >> 8) != (fcp->isp_portid >> 8))
 1366                         continue;
 1367                 handles[j++] = el4.pnhle_handle;
 1368         }
 1369         *num = j;
 1370         FC_SCRATCH_RELEASE(isp, chan);
 1371         return (0);
 1372 }
 1373 
 1374 static void
 1375 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
 1376 {
 1377         isp_pdb_t pdb;
 1378         uint16_t nphdl;
 1379 
 1380         isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
 1381         for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) {
 1382                 if (isp_getpdb(isp, chan, nphdl, &pdb)) {
 1383                         continue;
 1384                 }
 1385                 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
 1386                     "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
 1387                     chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
 1388                     pdb.portname[2], pdb.portname[3], pdb.portname[4],
 1389                     pdb.portname[5], pdb.portname[6], pdb.portname[7]);
 1390         }
 1391 }
 1392 
 1393 static uint64_t
 1394 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
 1395 {
 1396         uint64_t wwn = INI_NONE;
 1397         mbreg_t mbs;
 1398 
 1399         MBSINIT(&mbs, MBOX_GET_PORT_NAME,
 1400             MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
 1401         mbs.param[1] = nphdl;
 1402         if (nodename)
 1403                 mbs.param[10] = 1;
 1404         mbs.param[9] = chan;
 1405         isp_mboxcmd(isp, &mbs);
 1406         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 1407                 return (wwn);
 1408         }
 1409         wwn = (((uint64_t)(mbs.param[2] >> 8))  << 56) |
 1410               (((uint64_t)(mbs.param[2] & 0xff))<< 48) |
 1411               (((uint64_t)(mbs.param[3] >> 8))  << 40) |
 1412               (((uint64_t)(mbs.param[3] & 0xff))<< 32) |
 1413               (((uint64_t)(mbs.param[6] >> 8))  << 24) |
 1414               (((uint64_t)(mbs.param[6] & 0xff))<< 16) |
 1415               (((uint64_t)(mbs.param[7] >> 8))  <<  8) |
 1416               (((uint64_t)(mbs.param[7] & 0xff)));
 1417         return (wwn);
 1418 }
 1419 
 1420 /*
 1421  * Make sure we have good FC link.
 1422  */
 1423 
 1424 static int
 1425 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
 1426 {
 1427         mbreg_t mbs;
 1428         int i, r, topo;
 1429         fcparam *fcp;
 1430         isp_pdb_t pdb;
 1431         NANOTIME_T hra, hrb;
 1432 
 1433         fcp = FCPARAM(isp, chan);
 1434 
 1435         if (fcp->isp_loopstate < LOOP_HAVE_LINK)
 1436                 return (-1);
 1437         if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
 1438                 return (0);
 1439 
 1440         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
 1441 
 1442         /*
 1443          * Wait up to N microseconds for F/W to go to a ready state.
 1444          */
 1445         GET_NANOTIME(&hra);
 1446         while (1) {
 1447                 isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
 1448                 if (fcp->isp_fwstate == FW_READY) {
 1449                         break;
 1450                 }
 1451                 if (fcp->isp_loopstate < LOOP_HAVE_LINK)
 1452                         goto abort;
 1453                 GET_NANOTIME(&hrb);
 1454                 if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
 1455                         break;
 1456                 ISP_SLEEP(isp, 1000);
 1457         }
 1458         if (fcp->isp_fwstate != FW_READY) {
 1459                 isp_prt(isp, ISP_LOG_SANCFG,
 1460                     "Chan %d Firmware is not ready (%s)",
 1461                     chan, isp_fc_fw_statename(fcp->isp_fwstate));
 1462                 return (-1);
 1463         }
 1464 
 1465         /*
 1466          * Get our Loop ID and Port ID.
 1467          */
 1468         MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
 1469         mbs.param[9] = chan;
 1470         isp_mboxcmd(isp, &mbs);
 1471         if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 1472                 return (-1);
 1473         }
 1474 
 1475         topo = (int) mbs.param[6];
 1476         if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
 1477                 topo = TOPO_PTP_STUB;
 1478         fcp->isp_topo = topo;
 1479         fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
 1480 
 1481         if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
 1482                 fcp->isp_loopid = mbs.param[1] & 0xff;
 1483         } else if (fcp->isp_topo != TOPO_F_PORT) {
 1484                 uint8_t alpa = fcp->isp_portid;
 1485 
 1486                 for (i = 0; alpa_map[i]; i++) {
 1487                         if (alpa_map[i] == alpa)
 1488                                 break;
 1489                 }
 1490                 if (alpa_map[i])
 1491                         fcp->isp_loopid = i;
 1492         }
 1493 
 1494 #if 0
 1495         fcp->isp_loopstate = LOOP_HAVE_ADDR;
 1496 #endif
 1497         fcp->isp_loopstate = LOOP_TESTING_LINK;
 1498 
 1499         if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
 1500                 r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
 1501                 if (r != 0 || pdb.portid == 0) {
 1502                         isp_prt(isp, ISP_LOGWARN,
 1503                             "fabric topology, but cannot get info about fabric controller (0x%x)", r);
 1504                         fcp->isp_topo = TOPO_PTP_STUB;
 1505                         goto not_on_fabric;
 1506                 }
 1507 
 1508                 fcp->isp_fabric_params = mbs.param[7];
 1509                 fcp->isp_sns_hdl = NPH_SNS_ID;
 1510                 r = isp_register_fc4_type(isp, chan);
 1511                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
 1512                         goto abort;
 1513                 if (r != 0)
 1514                         goto not_on_fabric;
 1515                 r = isp_register_fc4_features_24xx(isp, chan);
 1516                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
 1517                         goto abort;
 1518                 if (r != 0)
 1519                         goto not_on_fabric;
 1520                 r = isp_register_port_name_24xx(isp, chan);
 1521                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
 1522                         goto abort;
 1523                 if (r != 0)
 1524                         goto not_on_fabric;
 1525                 isp_register_node_name_24xx(isp, chan);
 1526                 if (fcp->isp_loopstate < LOOP_TESTING_LINK)
 1527                         goto abort;
 1528         }
 1529 
 1530 not_on_fabric:
 1531         /* Get link speed. */
 1532         fcp->isp_gbspeed = 1;
 1533         MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
 1534         mbs.param[1] = MBGSD_GET_RATE;
 1535         /* mbs.param[2] undefined if we're just getting rate */
 1536         isp_mboxcmd(isp, &mbs);
 1537         if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 1538                 if (mbs.param[1] == MBGSD_10GB)
 1539                         fcp->isp_gbspeed = 10;
 1540                 else if (mbs.param[1] == MBGSD_32GB)
 1541                         fcp->isp_gbspeed = 32;
 1542                 else if (mbs.param[1] == MBGSD_16GB)
 1543                         fcp->isp_gbspeed = 16;
 1544                 else if (mbs.param[1] == MBGSD_8GB)
 1545                         fcp->isp_gbspeed = 8;
 1546                 else if (mbs.param[1] == MBGSD_4GB)
 1547                         fcp->isp_gbspeed = 4;
 1548                 else if (mbs.param[1] == MBGSD_2GB)
 1549                         fcp->isp_gbspeed = 2;
 1550                 else if (mbs.param[1] == MBGSD_1GB)
 1551                         fcp->isp_gbspeed = 1;
 1552         }
 1553 
 1554         if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
 1555 abort:
 1556                 isp_prt(isp, ISP_LOG_SANCFG,
 1557                     "Chan %d FC link test aborted", chan);
 1558                 return (1);
 1559         }
 1560         fcp->isp_loopstate = LOOP_LTEST_DONE;
 1561         isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
 1562             "Chan %d WWPN %016jx WWNN %016jx",
 1563             chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
 1564         isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
 1565             "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
 1566             chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
 1567             fcp->isp_loopid);
 1568         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
 1569         return (0);
 1570 }
 1571 
 1572 /*
 1573  * Complete the synchronization of our Port Database.
 1574  *
 1575  * At this point, we've scanned the local loop (if any) and the fabric
 1576  * and performed fabric logins on all new devices.
 1577  *
 1578  * Our task here is to go through our port database removing any entities
 1579  * that are still marked probational (issuing PLOGO for ones which we had
 1580  * PLOGI'd into) or are dead, and notifying upper layers about new/changed
 1581  * devices.
 1582  */
 1583 static int
 1584 isp_pdb_sync(ispsoftc_t *isp, int chan)
 1585 {
 1586         fcparam *fcp = FCPARAM(isp, chan);
 1587         fcportdb_t *lp;
 1588         uint16_t dbidx;
 1589 
 1590         if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
 1591                 return (-1);
 1592         if (fcp->isp_loopstate >= LOOP_READY)
 1593                 return (0);
 1594 
 1595         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
 1596 
 1597         fcp->isp_loopstate = LOOP_SYNCING_PDB;
 1598 
 1599         for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
 1600                 lp = &fcp->portdb[dbidx];
 1601 
 1602                 if (lp->state == FC_PORTDB_STATE_NIL)
 1603                         continue;
 1604                 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
 1605                         lp->state = FC_PORTDB_STATE_DEAD;
 1606                 switch (lp->state) {
 1607                 case FC_PORTDB_STATE_DEAD:
 1608                         lp->state = FC_PORTDB_STATE_NIL;
 1609                         isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
 1610                         if ((lp->portid & 0xffff00) != 0) {
 1611                                 (void) isp_plogx(isp, chan, lp->handle,
 1612                                     lp->portid,
 1613                                     PLOGX_FLG_CMD_LOGO |
 1614                                     PLOGX_FLG_IMPLICIT |
 1615                                     PLOGX_FLG_FREE_NPHDL);
 1616                         }
 1617                         /*
 1618                          * Note that we might come out of this with our state
 1619                          * set to FC_PORTDB_STATE_ZOMBIE.
 1620                          */
 1621                         break;
 1622                 case FC_PORTDB_STATE_NEW:
 1623                         lp->state = FC_PORTDB_STATE_VALID;
 1624                         isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
 1625                         break;
 1626                 case FC_PORTDB_STATE_CHANGED:
 1627                         lp->state = FC_PORTDB_STATE_VALID;
 1628                         isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
 1629                         lp->portid = lp->new_portid;
 1630                         lp->prli_word0 = lp->new_prli_word0;
 1631                         lp->prli_word3 = lp->new_prli_word3;
 1632                         break;
 1633                 case FC_PORTDB_STATE_VALID:
 1634                         isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
 1635                         break;
 1636                 case FC_PORTDB_STATE_ZOMBIE:
 1637                         break;
 1638                 default:
 1639                         isp_prt(isp, ISP_LOGWARN,
 1640                             "isp_pdb_sync: state %d for idx %d",
 1641                             lp->state, dbidx);
 1642                         isp_dump_portdb(isp, chan);
 1643                 }
 1644         }
 1645 
 1646         if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
 1647                 isp_prt(isp, ISP_LOG_SANCFG,
 1648                     "Chan %d FC PDB sync aborted", chan);
 1649                 return (1);
 1650         }
 1651 
 1652         fcp->isp_loopstate = LOOP_READY;
 1653         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
 1654         return (0);
 1655 }
 1656 
 1657 static void
 1658 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
 1659 {
 1660         fcportdb_t *lp;
 1661         uint64_t wwnn, wwpn;
 1662 
 1663         MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
 1664         MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
 1665 
 1666         /* Search port database for the same WWPN. */
 1667         if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
 1668                 if (!lp->probational) {
 1669                         isp_prt(isp, ISP_LOGERR,
 1670                             "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
 1671                             chan, lp->portid, lp->handle,
 1672                             FC_PORTDB_TGT(isp, chan, lp), lp->state);
 1673                         isp_dump_portdb(isp, chan);
 1674                         return;
 1675                 }
 1676                 lp->probational = 0;
 1677                 lp->node_wwn = wwnn;
 1678 
 1679                 /* Old device, nothing new. */
 1680                 if (lp->portid == pdb->portid &&
 1681                     lp->handle == pdb->handle &&
 1682                     lp->prli_word3 == pdb->prli_word3 &&
 1683                     ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) ==
 1684                      (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) {
 1685                         if (lp->state != FC_PORTDB_STATE_NEW)
 1686                                 lp->state = FC_PORTDB_STATE_VALID;
 1687                         isp_prt(isp, ISP_LOG_SANCFG,
 1688                             "Chan %d Port 0x%06x@0x%04x is valid",
 1689                             chan, pdb->portid, pdb->handle);
 1690                         return;
 1691                 }
 1692 
 1693                 /* Something has changed. */
 1694                 lp->state = FC_PORTDB_STATE_CHANGED;
 1695                 lp->handle = pdb->handle;
 1696                 lp->new_portid = pdb->portid;
 1697                 lp->new_prli_word0 = pdb->prli_word0;
 1698                 lp->new_prli_word3 = pdb->prli_word3;
 1699                 isp_prt(isp, ISP_LOG_SANCFG,
 1700                     "Chan %d Port 0x%06x@0x%04x is changed",
 1701                     chan, pdb->portid, pdb->handle);
 1702                 return;
 1703         }
 1704 
 1705         /* It seems like a new port. Find an empty slot for it. */
 1706         if (!isp_find_pdb_empty(isp, chan, &lp)) {
 1707                 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
 1708                 return;
 1709         }
 1710 
 1711         ISP_MEMZERO(lp, sizeof (fcportdb_t));
 1712         lp->probational = 0;
 1713         lp->state = FC_PORTDB_STATE_NEW;
 1714         lp->portid = lp->new_portid = pdb->portid;
 1715         lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0;
 1716         lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
 1717         lp->handle = pdb->handle;
 1718         lp->port_wwn = wwpn;
 1719         lp->node_wwn = wwnn;
 1720         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
 1721             chan, pdb->portid, pdb->handle);
 1722 }
 1723 
 1724 /*
 1725  * Scan local loop for devices.
 1726  */
 1727 static int
 1728 isp_scan_loop(ispsoftc_t *isp, int chan)
 1729 {
 1730         fcparam *fcp = FCPARAM(isp, chan);
 1731         int idx, lim, r;
 1732         isp_pdb_t pdb;
 1733         uint16_t *handles;
 1734         uint16_t handle;
 1735 
 1736         if (fcp->isp_loopstate < LOOP_LTEST_DONE)
 1737                 return (-1);
 1738         if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
 1739                 return (0);
 1740 
 1741         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
 1742         fcp->isp_loopstate = LOOP_SCANNING_LOOP;
 1743         if (TOPO_IS_FABRIC(fcp->isp_topo)) {
 1744                 isp_prt(isp, ISP_LOG_SANCFG,
 1745                     "Chan %d FC loop scan done (no loop)", chan);
 1746                 fcp->isp_loopstate = LOOP_LSCAN_DONE;
 1747                 return (0);
 1748         }
 1749 
 1750         handles = (uint16_t *)fcp->isp_scanscratch;
 1751         lim = ISP_FC_SCRLEN / 2;
 1752         r = isp_gethandles(isp, chan, handles, &lim, 1);
 1753         if (r != 0) {
 1754                 isp_prt(isp, ISP_LOG_SANCFG,
 1755                     "Chan %d Getting list of handles failed with %x", chan, r);
 1756                 isp_prt(isp, ISP_LOG_SANCFG,
 1757                     "Chan %d FC loop scan done (bad)", chan);
 1758                 return (-1);
 1759         }
 1760 
 1761         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
 1762             chan, lim);
 1763 
 1764         /*
 1765          * Run through the list and get the port database info for each one.
 1766          */
 1767         isp_mark_portdb(isp, chan);
 1768         for (idx = 0; idx < lim; idx++) {
 1769                 handle = handles[idx];
 1770 
 1771                 /*
 1772                  * Don't scan "special" ids.
 1773                  */
 1774                 if (handle >= NPH_RESERVED)
 1775                         continue;
 1776 
 1777                 /*
 1778                  * Get the port database entity for this index.
 1779                  */
 1780                 r = isp_getpdb(isp, chan, handle, &pdb);
 1781                 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
 1782 abort:
 1783                         isp_prt(isp, ISP_LOG_SANCFG,
 1784                             "Chan %d FC loop scan aborted", chan);
 1785                         return (1);
 1786                 }
 1787                 if (r != 0) {
 1788                         isp_prt(isp, ISP_LOGDEBUG1,
 1789                             "Chan %d FC Scan Loop handle %d returned %x",
 1790                             chan, handle, r);
 1791                         continue;
 1792                 }
 1793 
 1794                 isp_pdb_add_update(isp, chan, &pdb);
 1795         }
 1796         if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
 1797                 goto abort;
 1798         fcp->isp_loopstate = LOOP_LSCAN_DONE;
 1799         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
 1800         return (0);
 1801 }
 1802 
 1803 static int
 1804 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
 1805 {
 1806         fcparam *fcp = FCPARAM(isp, chan);
 1807         isp_ct_pt_t pt;
 1808         int retval;
 1809 
 1810         if (isp->isp_dblev & ISP_LOGDEBUG1)
 1811                 isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
 1812 
 1813         /*
 1814          * Build a Passthrough IOCB in memory.
 1815          */
 1816         ISP_MEMZERO(&pt, sizeof(pt));
 1817         pt.ctp_header.rqs_entry_count = 1;
 1818         pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
 1819         pt.ctp_nphdl = fcp->isp_sns_hdl;
 1820         pt.ctp_cmd_cnt = 1;
 1821         pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
 1822         pt.ctp_time = 10;
 1823         pt.ctp_rsp_cnt = 1;
 1824         pt.ctp_rsp_bcnt = rsp_bcnt;
 1825         pt.ctp_cmd_bcnt = cmd_bcnt;
 1826         pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma);
 1827         pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma);
 1828         pt.ctp_dataseg[0].ds_count = cmd_bcnt;
 1829         pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
 1830         pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
 1831         pt.ctp_dataseg[1].ds_count = rsp_bcnt;
 1832 
 1833         retval = isp_exec_entry_queue(isp, &pt, &pt, 2 * pt.ctp_time);
 1834         if (retval != 0) {
 1835                 isp_prt(isp, ISP_LOGERR, "%s: CTP of chan %d error %d",
 1836                     __func__, chan, retval);
 1837                 return (retval);
 1838         }
 1839 
 1840         if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
 1841                 isp_prt(isp, ISP_LOGWARN,
 1842                     "Chan %d CT pass-through returned 0x%x",
 1843                     chan, pt.ctp_status);
 1844                 return (-1);
 1845         }
 1846 
 1847         if (isp->isp_dblev & ISP_LOGDEBUG1)
 1848                 isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
 1849 
 1850         return (0);
 1851 }
 1852 
 1853 /*
 1854  * Scan the fabric for devices and add them to our port database.
 1855  *
 1856  * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
 1857  * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
 1858  *
 1859  * We use CT Pass-through IOCB.
 1860  */
 1861 #define GIDLEN  ISP_FC_SCRLEN
 1862 #define NGENT   ((GIDLEN - 16) >> 2)
 1863 
 1864 static int
 1865 isp_gid_pt(ispsoftc_t *isp, int chan)
 1866 {
 1867         fcparam *fcp = FCPARAM(isp, chan);
 1868         ct_hdr_t ct;
 1869         uint8_t *scp = fcp->isp_scratch;
 1870 
 1871         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
 1872         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 1873                 isp_prt(isp, ISP_LOGERR, sacq);
 1874                 return (-1);
 1875         }
 1876 
 1877         /* Build the CT command and execute via pass-through. */
 1878         ISP_MEMZERO(&ct, sizeof (ct));
 1879         ct.ct_revision = CT_REVISION;
 1880         ct.ct_fcs_type = CT_FC_TYPE_FC;
 1881         ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 1882         ct.ct_cmd_resp = SNS_GID_PT;
 1883         ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
 1884         isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
 1885         scp[sizeof(ct)] = 0x7f;         /* Port Type = Nx_Port */
 1886         scp[sizeof(ct)+1] = 0;          /* Domain_ID = any */
 1887         scp[sizeof(ct)+2] = 0;          /* Area_ID = any */
 1888         scp[sizeof(ct)+3] = 0;          /* Flags = no Area_ID */
 1889 
 1890         if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
 1891                 FC_SCRATCH_RELEASE(isp, chan);
 1892                 return (-1);
 1893         }
 1894 
 1895         isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
 1896             (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
 1897         FC_SCRATCH_RELEASE(isp, chan);
 1898         return (0);
 1899 }
 1900 
 1901 static int
 1902 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
 1903 {
 1904         fcparam *fcp = FCPARAM(isp, chan);
 1905         ct_hdr_t ct;
 1906         uint32_t *rp;
 1907         uint8_t *scp = fcp->isp_scratch;
 1908         sns_gff_id_rsp_t rsp;
 1909         int i, res = -1;
 1910 
 1911         if (!fcp->isp_use_gff_id)       /* User may block GFF_ID use. */
 1912                 return (res);
 1913 
 1914         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
 1915         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 1916                 isp_prt(isp, ISP_LOGERR, sacq);
 1917                 return (res);
 1918         }
 1919 
 1920         /* Build the CT command and execute via pass-through. */
 1921         ISP_MEMZERO(&ct, sizeof (ct));
 1922         ct.ct_revision = CT_REVISION;
 1923         ct.ct_fcs_type = CT_FC_TYPE_FC;
 1924         ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 1925         ct.ct_cmd_resp = SNS_GFF_ID;
 1926         ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
 1927         isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
 1928         rp = (uint32_t *) &scp[sizeof(ct)];
 1929         ISP_IOZPUT_32(isp, portid, rp);
 1930 
 1931         if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
 1932             SNS_GFF_ID_RESP_SIZE)) {
 1933                 FC_SCRATCH_RELEASE(isp, chan);
 1934                 return (res);
 1935         }
 1936 
 1937         isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
 1938         if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
 1939                 for (i = 0; i < 32; i++) {
 1940                         if (rsp.snscb_fc4_features[i] != 0) {
 1941                                 res = 0;
 1942                                 break;
 1943                         }
 1944                 }
 1945                 if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
 1946                     ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
 1947                         res = 1;
 1948                 /* Workaround for broken Brocade firmware. */
 1949                 if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
 1950                     ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
 1951                         res = 1;
 1952         }
 1953         FC_SCRATCH_RELEASE(isp, chan);
 1954         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
 1955         return (res);
 1956 }
 1957 
 1958 static int
 1959 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
 1960 {
 1961         fcparam *fcp = FCPARAM(isp, chan);
 1962         ct_hdr_t ct;
 1963         uint32_t *rp;
 1964         uint8_t *scp = fcp->isp_scratch;
 1965         sns_gft_id_rsp_t rsp;
 1966         int i, res = -1;
 1967 
 1968         if (!fcp->isp_use_gft_id)       /* User may block GFT_ID use. */
 1969                 return (res);
 1970 
 1971         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
 1972         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 1973                 isp_prt(isp, ISP_LOGERR, sacq);
 1974                 return (res);
 1975         }
 1976 
 1977         /* Build the CT command and execute via pass-through. */
 1978         ISP_MEMZERO(&ct, sizeof (ct));
 1979         ct.ct_revision = CT_REVISION;
 1980         ct.ct_fcs_type = CT_FC_TYPE_FC;
 1981         ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 1982         ct.ct_cmd_resp = SNS_GFT_ID;
 1983         ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
 1984         isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
 1985         rp = (uint32_t *) &scp[sizeof(ct)];
 1986         ISP_IOZPUT_32(isp, portid, rp);
 1987 
 1988         if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
 1989             SNS_GFT_ID_RESP_SIZE)) {
 1990                 FC_SCRATCH_RELEASE(isp, chan);
 1991                 return (res);
 1992         }
 1993 
 1994         isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
 1995         if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
 1996                 for (i = 0; i < 8; i++) {
 1997                         if (rsp.snscb_fc4_types[i] != 0) {
 1998                                 res = 0;
 1999                                 break;
 2000                         }
 2001                 }
 2002                 if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
 2003                     (FC4_SCSI % 32)) & 0x01) != 0)
 2004                         res = 1;
 2005         }
 2006         FC_SCRATCH_RELEASE(isp, chan);
 2007         isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
 2008         return (res);
 2009 }
 2010 
 2011 static int
 2012 isp_scan_fabric(ispsoftc_t *isp, int chan)
 2013 {
 2014         fcparam *fcp = FCPARAM(isp, chan);
 2015         fcportdb_t *lp;
 2016         uint32_t portid;
 2017         isp_pdb_t pdb;
 2018         int portidx, portlim, r;
 2019         sns_gid_xx_rsp_t *rs;
 2020 
 2021         if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
 2022                 return (-1);
 2023         if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
 2024                 return (0);
 2025 
 2026         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
 2027         fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
 2028         if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
 2029                 fcp->isp_loopstate = LOOP_FSCAN_DONE;
 2030                 isp_prt(isp, ISP_LOG_SANCFG,
 2031                     "Chan %d FC fabric scan done (no fabric)", chan);
 2032                 return (0);
 2033         }
 2034 
 2035         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
 2036 abort:
 2037                 FC_SCRATCH_RELEASE(isp, chan);
 2038                 isp_prt(isp, ISP_LOG_SANCFG,
 2039                     "Chan %d FC fabric scan aborted", chan);
 2040                 return (1);
 2041         }
 2042 
 2043         /*
 2044          * Make sure we still are logged into the fabric controller.
 2045          */
 2046         r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
 2047         if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
 2048                 isp_dump_chip_portdb(isp, chan);
 2049         }
 2050         if (r) {
 2051                 fcp->isp_loopstate = LOOP_LTEST_DONE;
 2052 fail:
 2053                 isp_prt(isp, ISP_LOG_SANCFG,
 2054                     "Chan %d FC fabric scan done (bad)", chan);
 2055                 return (-1);
 2056         }
 2057 
 2058         /* Get list of port IDs from SNS. */
 2059         r = isp_gid_pt(isp, chan);
 2060         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
 2061                 goto abort;
 2062         if (r > 0) {
 2063                 fcp->isp_loopstate = LOOP_FSCAN_DONE;
 2064                 return (-1);
 2065         } else if (r < 0) {
 2066                 fcp->isp_loopstate = LOOP_LTEST_DONE;   /* try again */
 2067                 return (-1);
 2068         }
 2069 
 2070         rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
 2071         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
 2072                 goto abort;
 2073         if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
 2074                 int level;
 2075                 /* FC-4 Type and Port Type not registered are not errors. */
 2076                 if (rs->snscb_cthdr.ct_reason == 9 &&
 2077                     (rs->snscb_cthdr.ct_explanation == 0x07 ||
 2078                      rs->snscb_cthdr.ct_explanation == 0x0a)) {
 2079                         level = ISP_LOG_SANCFG;
 2080                 } else {
 2081                         level = ISP_LOGWARN;
 2082                 }
 2083                 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
 2084                     " (Reason=0x%x Expl=0x%x)", chan,
 2085                     rs->snscb_cthdr.ct_reason,
 2086                     rs->snscb_cthdr.ct_explanation);
 2087                 fcp->isp_loopstate = LOOP_FSCAN_DONE;
 2088                 return (-1);
 2089         }
 2090 
 2091         /* Check our buffer was big enough to get the full list. */
 2092         for (portidx = 0; portidx < NGENT-1; portidx++) {
 2093                 if (rs->snscb_ports[portidx].control & 0x80)
 2094                         break;
 2095         }
 2096         if ((rs->snscb_ports[portidx].control & 0x80) == 0) {
 2097                 isp_prt(isp, ISP_LOGWARN,
 2098                     "fabric too big for scratch area: increase ISP_FC_SCRLEN");
 2099         }
 2100         portlim = portidx + 1;
 2101         isp_prt(isp, ISP_LOG_SANCFG,
 2102             "Chan %d Got %d ports back from name server", chan, portlim);
 2103 
 2104         /* Go through the list and remove duplicate port ids. */
 2105         for (portidx = 0; portidx < portlim; portidx++) {
 2106                 int npidx;
 2107 
 2108                 portid =
 2109                     ((rs->snscb_ports[portidx].portid[0]) << 16) |
 2110                     ((rs->snscb_ports[portidx].portid[1]) << 8) |
 2111                     ((rs->snscb_ports[portidx].portid[2]));
 2112 
 2113                 for (npidx = portidx + 1; npidx < portlim; npidx++) {
 2114                         uint32_t new_portid =
 2115                             ((rs->snscb_ports[npidx].portid[0]) << 16) |
 2116                             ((rs->snscb_ports[npidx].portid[1]) << 8) |
 2117                             ((rs->snscb_ports[npidx].portid[2]));
 2118                         if (new_portid == portid) {
 2119                                 break;
 2120                         }
 2121                 }
 2122 
 2123                 if (npidx < portlim) {
 2124                         rs->snscb_ports[npidx].portid[0] = 0;
 2125                         rs->snscb_ports[npidx].portid[1] = 0;
 2126                         rs->snscb_ports[npidx].portid[2] = 0;
 2127                         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid);
 2128                 }
 2129         }
 2130 
 2131         /*
 2132          * We now have a list of Port IDs for all FC4 SCSI devices
 2133          * that the Fabric Name server knows about.
 2134          *
 2135          * For each entry on this list go through our port database looking
 2136          * for probational entries- if we find one, then an old entry is
 2137          * maybe still this one. We get some information to find out.
 2138          *
 2139          * Otherwise, it's a new fabric device, and we log into it
 2140          * (unconditionally). After searching the entire database
 2141          * again to make sure that we never ever ever ever have more
 2142          * than one entry that has the same PortID or the same
 2143          * WWNN/WWPN duple, we enter the device into our database.
 2144          */
 2145         isp_mark_portdb(isp, chan);
 2146         for (portidx = 0; portidx < portlim; portidx++) {
 2147                 portid = ((rs->snscb_ports[portidx].portid[0]) << 16) |
 2148                          ((rs->snscb_ports[portidx].portid[1]) << 8) |
 2149                          ((rs->snscb_ports[portidx].portid[2]));
 2150                 isp_prt(isp, ISP_LOG_SANCFG,
 2151                     "Chan %d Checking fabric port 0x%06x", chan, portid);
 2152                 if (portid == 0) {
 2153                         isp_prt(isp, ISP_LOG_SANCFG,
 2154                             "Chan %d Port at idx %d is zero",
 2155                             chan, portidx);
 2156                         continue;
 2157                 }
 2158                 if (portid == fcp->isp_portid) {
 2159                         isp_prt(isp, ISP_LOG_SANCFG,
 2160                             "Chan %d Port 0x%06x is our", chan, portid);
 2161                         continue;
 2162                 }
 2163 
 2164                 /* Now search the entire port database for the same portid. */
 2165                 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
 2166                         if (!lp->probational) {
 2167                                 isp_prt(isp, ISP_LOGERR,
 2168                                     "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
 2169                                     chan, lp->portid, lp->handle,
 2170                                     FC_PORTDB_TGT(isp, chan, lp), lp->state);
 2171                                 isp_dump_portdb(isp, chan);
 2172                                 goto fail;
 2173                         }
 2174 
 2175                         if (lp->state == FC_PORTDB_STATE_ZOMBIE)
 2176                                 goto relogin;
 2177 
 2178                         /*
 2179                          * See if we're still logged into it.
 2180                          *
 2181                          * If we aren't, mark it as a dead device and
 2182                          * leave the new portid in the database entry
 2183                          * for somebody further along to decide what to
 2184                          * do (policy choice).
 2185                          *
 2186                          * If we are, check to see if it's the same
 2187                          * device still (it should be). If for some
 2188                          * reason it isn't, mark it as a changed device
 2189                          * and leave the new portid and role in the
 2190                          * database entry for somebody further along to
 2191                          * decide what to do (policy choice).
 2192                          */
 2193                         r = isp_getpdb(isp, chan, lp->handle, &pdb);
 2194                         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
 2195                                 goto abort;
 2196                         if (r != 0) {
 2197                                 lp->state = FC_PORTDB_STATE_DEAD;
 2198                                 isp_prt(isp, ISP_LOG_SANCFG,
 2199                                     "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
 2200                                     chan, portid, lp->handle, r);
 2201                                 goto relogin;
 2202                         }
 2203 
 2204                         isp_pdb_add_update(isp, chan, &pdb);
 2205                         continue;
 2206                 }
 2207 
 2208 relogin:
 2209                 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
 2210                         isp_prt(isp, ISP_LOG_SANCFG,
 2211                             "Chan %d Port 0x%06x is not logged in", chan, portid);
 2212                         continue;
 2213                 }
 2214 
 2215                 r = isp_gff_id(isp, chan, portid);
 2216                 if (r == 0) {
 2217                         isp_prt(isp, ISP_LOG_SANCFG,
 2218                             "Chan %d Port 0x%06x is not an FCP target", chan, portid);
 2219                         continue;
 2220                 }
 2221                 if (r < 0)
 2222                         r = isp_gft_id(isp, chan, portid);
 2223                 if (r == 0) {
 2224                         isp_prt(isp, ISP_LOG_SANCFG,
 2225                             "Chan %d Port 0x%06x is not FCP", chan, portid);
 2226                         continue;
 2227                 }
 2228 
 2229                 if (isp_login_device(isp, chan, portid, &pdb,
 2230                     &FCPARAM(isp, 0)->isp_lasthdl)) {
 2231                         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
 2232                                 goto abort;
 2233                         continue;
 2234                 }
 2235 
 2236                 isp_pdb_add_update(isp, chan, &pdb);
 2237         }
 2238 
 2239         if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
 2240                 goto abort;
 2241         fcp->isp_loopstate = LOOP_FSCAN_DONE;
 2242         isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
 2243         return (0);
 2244 }
 2245 
 2246 /*
 2247  * Find an unused handle and try and use to login to a port.
 2248  */
 2249 static int
 2250 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
 2251 {
 2252         int i, r;
 2253         uint16_t handle;
 2254 
 2255         handle = isp_next_handle(isp, ohp);
 2256         for (i = 0; i < NPH_MAX_2K; i++) {
 2257                 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
 2258                         return (-1);
 2259 
 2260                 /* Check if this handle is free. */
 2261                 r = isp_getpdb(isp, chan, handle, p);
 2262                 if (r == 0) {
 2263                         if (p->portid != portid) {
 2264                                 /* This handle is busy, try next one. */
 2265                                 handle = isp_next_handle(isp, ohp);
 2266                                 continue;
 2267                         }
 2268                         break;
 2269                 }
 2270                 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
 2271                         return (-1);
 2272 
 2273                 /*
 2274                  * Now try and log into the device
 2275                  */
 2276                 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
 2277                 if (r == 0) {
 2278                         break;
 2279                 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
 2280                         /*
 2281                          * If we get here, then the firmwware still thinks we're logged into this device, but with a different
 2282                          * handle. We need to break that association. We used to try and just substitute the handle, but then
 2283                          * failed to get any data via isp_getpdb (below).
 2284                          */
 2285                         if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
 2286                                 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
 2287                         }
 2288                         if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
 2289                                 return (-1);
 2290                         r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
 2291                         if (r != 0)
 2292                                 i = NPH_MAX_2K;
 2293                         break;
 2294                 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
 2295                         /* Try the next handle. */
 2296                         handle = isp_next_handle(isp, ohp);
 2297                 } else {
 2298                         /* Give up. */
 2299                         i = NPH_MAX_2K;
 2300                         break;
 2301                 }
 2302         }
 2303 
 2304         if (i == NPH_MAX_2K) {
 2305                 isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
 2306                 return (-1);
 2307         }
 2308 
 2309         /*
 2310          * If we successfully logged into it, get the PDB for it
 2311          * so we can crosscheck that it is still what we think it
 2312          * is and that we also have the role it plays
 2313          */
 2314         r = isp_getpdb(isp, chan, handle, p);
 2315         if (r != 0) {
 2316                 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
 2317                 return (-1);
 2318         }
 2319 
 2320         if (p->handle != handle || p->portid != portid) {
 2321                 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
 2322                     chan, portid, handle, p->portid, p->handle);
 2323                 return (-1);
 2324         }
 2325         return (0);
 2326 }
 2327 
 2328 static int
 2329 isp_register_fc4_type(ispsoftc_t *isp, int chan)
 2330 {
 2331         fcparam *fcp = FCPARAM(isp, chan);
 2332         rft_id_t rp;
 2333         ct_hdr_t *ct = &rp.rftid_hdr;
 2334         uint8_t *scp = fcp->isp_scratch;
 2335 
 2336         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 2337                 isp_prt(isp, ISP_LOGERR, sacq);
 2338                 return (-1);
 2339         }
 2340 
 2341         /* Build the CT command and execute via pass-through. */
 2342         ISP_MEMZERO(&rp, sizeof(rp));
 2343         ct->ct_revision = CT_REVISION;
 2344         ct->ct_fcs_type = CT_FC_TYPE_FC;
 2345         ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 2346         ct->ct_cmd_resp = SNS_RFT_ID;
 2347         ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
 2348         rp.rftid_portid[0] = fcp->isp_portid >> 16;
 2349         rp.rftid_portid[1] = fcp->isp_portid >> 8;
 2350         rp.rftid_portid[2] = fcp->isp_portid;
 2351         rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
 2352         isp_put_rft_id(isp, &rp, (rft_id_t *)scp);
 2353 
 2354         if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
 2355                 FC_SCRATCH_RELEASE(isp, chan);
 2356                 return (-1);
 2357         }
 2358 
 2359         isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
 2360         FC_SCRATCH_RELEASE(isp, chan);
 2361         if (ct->ct_cmd_resp == LS_RJT) {
 2362                 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan);
 2363                 return (-1);
 2364         } else if (ct->ct_cmd_resp == LS_ACC) {
 2365                 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
 2366         } else {
 2367                 isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
 2368                 return (-1);
 2369         }
 2370         return (0);
 2371 }
 2372 
 2373 static int
 2374 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
 2375 {
 2376         fcparam *fcp = FCPARAM(isp, chan);
 2377         ct_hdr_t *ct;
 2378         rff_id_t rp;
 2379         uint8_t *scp = fcp->isp_scratch;
 2380 
 2381         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 2382                 isp_prt(isp, ISP_LOGERR, sacq);
 2383                 return (-1);
 2384         }
 2385 
 2386         /*
 2387          * Build the CT header and command in memory.
 2388          */
 2389         ISP_MEMZERO(&rp, sizeof(rp));
 2390         ct = &rp.rffid_hdr;
 2391         ct->ct_revision = CT_REVISION;
 2392         ct->ct_fcs_type = CT_FC_TYPE_FC;
 2393         ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 2394         ct->ct_cmd_resp = SNS_RFF_ID;
 2395         ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
 2396         rp.rffid_portid[0] = fcp->isp_portid >> 16;
 2397         rp.rffid_portid[1] = fcp->isp_portid >> 8;
 2398         rp.rffid_portid[2] = fcp->isp_portid;
 2399         rp.rffid_fc4features = 0;
 2400         if (fcp->role & ISP_ROLE_TARGET)
 2401                 rp.rffid_fc4features |= 1;
 2402         if (fcp->role & ISP_ROLE_INITIATOR)
 2403                 rp.rffid_fc4features |= 2;
 2404         rp.rffid_fc4type = FC4_SCSI;
 2405         isp_put_rff_id(isp, &rp, (rff_id_t *)scp);
 2406         if (isp->isp_dblev & ISP_LOGDEBUG1)
 2407                 isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp);
 2408 
 2409         if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
 2410                 FC_SCRATCH_RELEASE(isp, chan);
 2411                 return (-1);
 2412         }
 2413 
 2414         isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
 2415         FC_SCRATCH_RELEASE(isp, chan);
 2416         if (ct->ct_cmd_resp == LS_RJT) {
 2417                 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
 2418                     "Chan %d Register FC4 Features rejected", chan);
 2419                 return (-1);
 2420         } else if (ct->ct_cmd_resp == LS_ACC) {
 2421                 isp_prt(isp, ISP_LOG_SANCFG,
 2422                     "Chan %d Register FC4 Features accepted", chan);
 2423         } else {
 2424                 isp_prt(isp, ISP_LOGWARN,
 2425                     "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
 2426                 return (-1);
 2427         }
 2428         return (0);
 2429 }
 2430 
 2431 static int
 2432 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
 2433 {
 2434         fcparam *fcp = FCPARAM(isp, chan);
 2435         ct_hdr_t *ct;
 2436         rspn_id_t rp;
 2437         uint8_t *scp = fcp->isp_scratch;
 2438         int len;
 2439 
 2440         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 2441                 isp_prt(isp, ISP_LOGERR, sacq);
 2442                 return (-1);
 2443         }
 2444 
 2445         /*
 2446          * Build the CT header and command in memory.
 2447          */
 2448         ISP_MEMZERO(&rp, sizeof(rp));
 2449         ct = &rp.rspnid_hdr;
 2450         ct->ct_revision = CT_REVISION;
 2451         ct->ct_fcs_type = CT_FC_TYPE_FC;
 2452         ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 2453         ct->ct_cmd_resp = SNS_RSPN_ID;
 2454         rp.rspnid_portid[0] = fcp->isp_portid >> 16;
 2455         rp.rspnid_portid[1] = fcp->isp_portid >> 8;
 2456         rp.rspnid_portid[2] = fcp->isp_portid;
 2457         rp.rspnid_length = 0;
 2458         len = offsetof(rspn_id_t, rspnid_name);
 2459         mtx_lock(&prison0.pr_mtx);
 2460         rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
 2461             "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
 2462         mtx_unlock(&prison0.pr_mtx);
 2463         rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
 2464             ":%s", device_get_nameunit(isp->isp_dev));
 2465         if (chan != 0) {
 2466                 rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
 2467                     "/%d", chan);
 2468         }
 2469         len += rp.rspnid_length;
 2470         ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
 2471         isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp);
 2472 
 2473         if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
 2474                 FC_SCRATCH_RELEASE(isp, chan);
 2475                 return (-1);
 2476         }
 2477 
 2478         isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
 2479         FC_SCRATCH_RELEASE(isp, chan);
 2480         if (ct->ct_cmd_resp == LS_RJT) {
 2481                 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
 2482                     "Chan %d Register Symbolic Port Name rejected", chan);
 2483                 return (-1);
 2484         } else if (ct->ct_cmd_resp == LS_ACC) {
 2485                 isp_prt(isp, ISP_LOG_SANCFG,
 2486                     "Chan %d Register Symbolic Port Name accepted", chan);
 2487         } else {
 2488                 isp_prt(isp, ISP_LOGWARN,
 2489                     "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
 2490                 return (-1);
 2491         }
 2492         return (0);
 2493 }
 2494 
 2495 static int
 2496 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
 2497 {
 2498         fcparam *fcp = FCPARAM(isp, chan);
 2499         ct_hdr_t *ct;
 2500         rsnn_nn_t rp;
 2501         uint8_t *scp = fcp->isp_scratch;
 2502         int len;
 2503 
 2504         if (FC_SCRATCH_ACQUIRE(isp, chan)) {
 2505                 isp_prt(isp, ISP_LOGERR, sacq);
 2506                 return (-1);
 2507         }
 2508 
 2509         /*
 2510          * Build the CT header and command in memory.
 2511          */
 2512         ISP_MEMZERO(&rp, sizeof(rp));
 2513         ct = &rp.rsnnnn_hdr;
 2514         ct->ct_revision = CT_REVISION;
 2515         ct->ct_fcs_type = CT_FC_TYPE_FC;
 2516         ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
 2517         ct->ct_cmd_resp = SNS_RSNN_NN;
 2518         MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn);
 2519         rp.rsnnnn_length = 0;
 2520         len = offsetof(rsnn_nn_t, rsnnnn_name);
 2521         mtx_lock(&prison0.pr_mtx);
 2522         rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length],
 2523             "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
 2524         mtx_unlock(&prison0.pr_mtx);
 2525         len += rp.rsnnnn_length;
 2526         ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
 2527         isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp);
 2528 
 2529         if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
 2530                 FC_SCRATCH_RELEASE(isp, chan);
 2531                 return (-1);
 2532         }
 2533 
 2534         isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
 2535         FC_SCRATCH_RELEASE(isp, chan);
 2536         if (ct->ct_cmd_resp == LS_RJT) {
 2537                 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
 2538                     "Chan %d Register Symbolic Node Name rejected", chan);
 2539                 return (-1);
 2540         } else if (ct->ct_cmd_resp == LS_ACC) {
 2541                 isp_prt(isp, ISP_LOG_SANCFG,
 2542                     "Chan %d Register Symbolic Node Name accepted", chan);
 2543         } else {
 2544                 isp_prt(isp, ISP_LOGWARN,
 2545                     "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
 2546                 return (-1);
 2547         }
 2548         return (0);
 2549 }
 2550 
 2551 static uint16_t
 2552 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
 2553 {
 2554         fcparam *fcp;
 2555         int i, chan, wrap;
 2556         uint16_t handle;
 2557 
 2558         handle = *ohp;
 2559         wrap = 0;
 2560 
 2561 next:
 2562         if (handle == NIL_HANDLE) {
 2563                 handle = 0;
 2564         } else {
 2565                 handle++;
 2566                 if (handle > NPH_RESERVED - 1) {
 2567                         if (++wrap >= 2) {
 2568                                 isp_prt(isp, ISP_LOGERR, "Out of port handles!");
 2569                                 return (NIL_HANDLE);
 2570                         }
 2571                         handle = 0;
 2572                 }
 2573         }
 2574         for (chan = 0; chan < isp->isp_nchan; chan++) {
 2575                 fcp = FCPARAM(isp, chan);
 2576                 if (fcp->role == ISP_ROLE_NONE)
 2577                         continue;
 2578                 for (i = 0; i < MAX_FC_TARG; i++) {
 2579                         if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL &&
 2580                             fcp->portdb[i].handle == handle)
 2581                                 goto next;
 2582                 }
 2583         }
 2584         *ohp = handle;
 2585         return (handle);
 2586 }
 2587 
 2588 /*
 2589  * Start a command. Locking is assumed done in the caller.
 2590  */
 2591 
 2592 int
 2593 isp_start(XS_T *xs)
 2594 {
 2595         ispsoftc_t *isp;
 2596         fcparam *fcp;
 2597         uint32_t cdblen;
 2598         ispreqt7_t local, *reqp = &local;
 2599         void *qep;
 2600         fcportdb_t *lp;
 2601         int target, dmaresult;
 2602 
 2603         XS_INITERR(xs);
 2604         isp = XS_ISP(xs);
 2605 
 2606         /*
 2607          * Check command CDB length, etc.. We really are limited to 16 bytes
 2608          * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
 2609          * but probably only if we're running fairly new firmware (we'll
 2610          * let the old f/w choke on an extended command queue entry).
 2611          */
 2612 
 2613         if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) {
 2614                 isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
 2615                 XS_SETERR(xs, HBA_REQINVAL);
 2616                 return (CMD_COMPLETE);
 2617         }
 2618 
 2619         /*
 2620          * Translate the target to device handle as appropriate, checking
 2621          * for correct device state as well.
 2622          */
 2623         target = XS_TGT(xs);
 2624         fcp = FCPARAM(isp, XS_CHANNEL(xs));
 2625 
 2626         if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
 2627                 isp_prt(isp, ISP_LOG_WARN1,
 2628                     "%d.%d.%jx I am not an initiator",
 2629                     XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
 2630                 XS_SETERR(xs, HBA_SELTIMEOUT);
 2631                 return (CMD_COMPLETE);
 2632         }
 2633 
 2634         if (isp->isp_state != ISP_RUNSTATE) {
 2635                 isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
 2636                 XS_SETERR(xs, HBA_BOTCH);
 2637                 return (CMD_COMPLETE);
 2638         }
 2639 
 2640         isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target);
 2641         lp = &fcp->portdb[target];
 2642         if (target < 0 || target >= MAX_FC_TARG ||
 2643             lp->is_target == 0) {
 2644                 XS_SETERR(xs, HBA_SELTIMEOUT);
 2645                 return (CMD_COMPLETE);
 2646         }
 2647         if (fcp->isp_loopstate != LOOP_READY) {
 2648                 isp_prt(isp, ISP_LOGDEBUG1,
 2649                     "%d.%d.%jx loop is not ready",
 2650                     XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
 2651                 return (CMD_RQLATER);
 2652         }
 2653         if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
 2654                 isp_prt(isp, ISP_LOGDEBUG1,
 2655                     "%d.%d.%jx target zombie",
 2656                     XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
 2657                 return (CMD_RQLATER);
 2658         }
 2659         if (lp->state != FC_PORTDB_STATE_VALID) {
 2660                 isp_prt(isp, ISP_LOGDEBUG1,
 2661                     "%d.%d.%jx bad db port state 0x%x",
 2662                     XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state);
 2663                 XS_SETERR(xs, HBA_SELTIMEOUT);
 2664                 return (CMD_COMPLETE);
 2665         }
 2666 
 2667  start_again:
 2668 
 2669         qep = isp_getrqentry(isp);
 2670         if (qep == NULL) {
 2671                 isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
 2672                 XS_SETERR(xs, HBA_BOTCH);
 2673                 return (CMD_EAGAIN);
 2674         }
 2675         XS_SETERR(xs, HBA_NOERROR);
 2676 
 2677         /*
 2678          * Now see if we need to synchronize the ISP with respect to anything.
 2679          * We do dual duty here (cough) for synchronizing for buses other
 2680          * than which we got here to send a command to.
 2681          */
 2682         ISP_MEMZERO(reqp, QENTRY_LEN);
 2683         if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
 2684                 isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
 2685                 m->mrk_header.rqs_entry_count = 1;
 2686                 m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
 2687                 m->mrk_modifier = SYNC_ALL;
 2688                 m->mrk_vphdl = XS_CHANNEL(xs);
 2689                 isp_put_marker_24xx(isp, m, qep);
 2690                 ISP_SYNC_REQUEST(isp);
 2691                 ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
 2692                 goto start_again;
 2693         }
 2694 
 2695         /*
 2696          * NB: we do not support long CDBs (yet)
 2697          */
 2698         cdblen = XS_CDBLEN(xs);
 2699         if (cdblen > sizeof (reqp->req_cdb)) {
 2700                 isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen);
 2701                 XS_SETERR(xs, HBA_REQINVAL);
 2702                 return (CMD_COMPLETE);
 2703         }
 2704 
 2705         reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
 2706         reqp->req_header.rqs_entry_count = 1;
 2707         reqp->req_nphdl = lp->handle;
 2708         reqp->req_time = XS_TIME(xs);
 2709         be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs)));
 2710         if (XS_XFRIN(xs))
 2711                 reqp->req_alen_datadir = FCP_CMND_DATA_READ;
 2712         else if (XS_XFROUT(xs))
 2713                 reqp->req_alen_datadir = FCP_CMND_DATA_WRITE;
 2714         if (XS_TAG_P(xs))
 2715                 reqp->req_task_attribute = XS_TAG_TYPE(xs);
 2716         else
 2717                 reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
 2718         reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
 2719              FCP_CMND_PRIO_MASK;
 2720         if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) {
 2721                 if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) {
 2722                         isp_prt(isp, ISP_LOG_WARN1,
 2723                             "%d.%d.%jx cannot generate next CRN",
 2724                             XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
 2725                         XS_SETERR(xs, HBA_BOTCH);
 2726                         return (CMD_EAGAIN);
 2727                 }
 2728         }
 2729         ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen);
 2730         reqp->req_dl = XS_XFRLEN(xs);
 2731         reqp->req_tidlo = lp->portid;
 2732         reqp->req_tidhi = lp->portid >> 16;
 2733         reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
 2734 
 2735         /* Whew. Thankfully the same for type 7 requests */
 2736         reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
 2737         if (reqp->req_handle == 0) {
 2738                 isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers");
 2739                 XS_SETERR(xs, HBA_BOTCH);
 2740                 return (CMD_EAGAIN);
 2741         }
 2742 
 2743         /*
 2744          * Set up DMA and/or do any platform dependent swizzling of the request entry
 2745          * so that the Qlogic F/W understands what is being asked of it.
 2746          *
 2747          * The callee is responsible for adding all requests at this point.
 2748          */
 2749         dmaresult = ISP_DMASETUP(isp, xs, reqp);
 2750         if (dmaresult != 0) {
 2751                 isp_destroy_handle(isp, reqp->req_handle);
 2752                 /*
 2753                  * dmasetup sets actual error in packet, and
 2754                  * return what we were given to return.
 2755                  */
 2756                 return (dmaresult);
 2757         }
 2758         isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
 2759         return (0);
 2760 }
 2761 
 2762 /*
 2763  * isp control
 2764  * Locks (ints blocked) assumed held.
 2765  */
 2766 
 2767 int
 2768 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
 2769 {
 2770         fcparam *fcp;
 2771         fcportdb_t *lp;
 2772         XS_T *xs;
 2773         mbreg_t *mbr;
 2774         int chan, tgt;
 2775         uint32_t handle;
 2776         va_list ap;
 2777         uint8_t local[QENTRY_LEN];
 2778 
 2779         switch (ctl) {
 2780         case ISPCTL_RESET_BUS:
 2781                 /*
 2782                  * Issue a bus reset.
 2783                  */
 2784                 isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
 2785                 break;
 2786 
 2787         case ISPCTL_RESET_DEV:
 2788         {
 2789                 isp24xx_tmf_t *tmf;
 2790                 isp24xx_statusreq_t *sp;
 2791 
 2792                 va_start(ap, ctl);
 2793                 chan = va_arg(ap, int);
 2794                 tgt = va_arg(ap, int);
 2795                 va_end(ap);
 2796                 fcp = FCPARAM(isp, chan);
 2797 
 2798                 if (tgt < 0 || tgt >= MAX_FC_TARG) {
 2799                         isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
 2800                         break;
 2801                 }
 2802                 lp = &fcp->portdb[tgt];
 2803                 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
 2804                         isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
 2805                         break;
 2806                 }
 2807 
 2808                 tmf = (isp24xx_tmf_t *) local;
 2809                 ISP_MEMZERO(tmf, QENTRY_LEN);
 2810                 tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
 2811                 tmf->tmf_header.rqs_entry_count = 1;
 2812                 tmf->tmf_nphdl = lp->handle;
 2813                 tmf->tmf_delay = 2;
 2814                 tmf->tmf_timeout = 4;
 2815                 tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
 2816                 tmf->tmf_tidlo = lp->portid;
 2817                 tmf->tmf_tidhi = lp->portid >> 16;
 2818                 tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
 2819                 fcp->sendmarker = 1;
 2820                 isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
 2821 
 2822                 sp = (isp24xx_statusreq_t *) local;
 2823                 if (isp_exec_entry_mbox(isp, tmf, sp, 2 * tmf->tmf_timeout))
 2824                         break;
 2825 
 2826                 if (sp->req_completion_status == 0)
 2827                         return (0);
 2828                 isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
 2829                 break;
 2830         }
 2831         case ISPCTL_ABORT_CMD:
 2832         {
 2833                 isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
 2834 
 2835                 va_start(ap, ctl);
 2836                 xs = va_arg(ap, XS_T *);
 2837                 va_end(ap);
 2838 
 2839                 tgt = XS_TGT(xs);
 2840                 chan = XS_CHANNEL(xs);
 2841 
 2842                 handle = isp_find_handle(isp, xs);
 2843                 if (handle == 0) {
 2844                         isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
 2845                         break;
 2846                 }
 2847 
 2848                 fcp = FCPARAM(isp, chan);
 2849                 if (tgt < 0 || tgt >= MAX_FC_TARG) {
 2850                         isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt);
 2851                         break;
 2852                 }
 2853                 lp = &fcp->portdb[tgt];
 2854                 if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
 2855                         isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
 2856                         break;
 2857                 }
 2858                 isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
 2859                 ISP_MEMZERO(ab, QENTRY_LEN);
 2860                 ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
 2861                 ab->abrt_header.rqs_entry_count = 1;
 2862                 ab->abrt_handle = lp->handle;
 2863                 ab->abrt_cmd_handle = handle;
 2864                 ab->abrt_tidlo = lp->portid;
 2865                 ab->abrt_tidhi = lp->portid >> 16;
 2866                 ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
 2867 
 2868                 if (isp_exec_entry_mbox(isp, ab, ab, 5))
 2869                         break;
 2870 
 2871                 if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY)
 2872                         return (0);
 2873                 isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
 2874         }
 2875         case ISPCTL_FCLINK_TEST:
 2876         {
 2877                 int usdelay;
 2878 
 2879                 va_start(ap, ctl);
 2880                 chan = va_arg(ap, int);
 2881                 usdelay = va_arg(ap, int);
 2882                 va_end(ap);
 2883                 if (usdelay == 0)
 2884                         usdelay = 250000;
 2885                 return (isp_fclink_test(isp, chan, usdelay));
 2886         }
 2887         case ISPCTL_SCAN_FABRIC:
 2888 
 2889                 va_start(ap, ctl);
 2890                 chan = va_arg(ap, int);
 2891                 va_end(ap);
 2892                 return (isp_scan_fabric(isp, chan));
 2893 
 2894         case ISPCTL_SCAN_LOOP:
 2895 
 2896                 va_start(ap, ctl);
 2897                 chan = va_arg(ap, int);
 2898                 va_end(ap);
 2899                 return (isp_scan_loop(isp, chan));
 2900 
 2901         case ISPCTL_PDB_SYNC:
 2902 
 2903                 va_start(ap, ctl);
 2904                 chan = va_arg(ap, int);
 2905                 va_end(ap);
 2906                 return (isp_pdb_sync(isp, chan));
 2907 
 2908         case ISPCTL_SEND_LIP:
 2909                 break;
 2910 
 2911         case ISPCTL_GET_PDB:
 2912         {
 2913                 isp_pdb_t *pdb;
 2914                 va_start(ap, ctl);
 2915                 chan = va_arg(ap, int);
 2916                 tgt = va_arg(ap, int);
 2917                 pdb = va_arg(ap, isp_pdb_t *);
 2918                 va_end(ap);
 2919                 return (isp_getpdb(isp, chan, tgt, pdb));
 2920         }
 2921         case ISPCTL_GET_NAMES:
 2922         {
 2923                 uint64_t *wwnn, *wwnp;
 2924                 va_start(ap, ctl);
 2925                 chan = va_arg(ap, int);
 2926                 tgt = va_arg(ap, int);
 2927                 wwnn = va_arg(ap, uint64_t *);
 2928                 wwnp = va_arg(ap, uint64_t *);
 2929                 va_end(ap);
 2930                 if (wwnn == NULL && wwnp == NULL) {
 2931                         break;
 2932                 }
 2933                 if (wwnn) {
 2934                         *wwnn = isp_get_wwn(isp, chan, tgt, 1);
 2935                         if (*wwnn == INI_NONE) {
 2936                                 break;
 2937                         }
 2938                 }
 2939                 if (wwnp) {
 2940                         *wwnp = isp_get_wwn(isp, chan, tgt, 0);
 2941                         if (*wwnp == INI_NONE) {
 2942                                 break;
 2943                         }
 2944                 }
 2945                 return (0);
 2946         }
 2947         case ISPCTL_RUN_MBOXCMD:
 2948         {
 2949                 va_start(ap, ctl);
 2950                 mbr = va_arg(ap, mbreg_t *);
 2951                 va_end(ap);
 2952                 isp_mboxcmd(isp, mbr);
 2953                 return (0);
 2954         }
 2955         case ISPCTL_PLOGX:
 2956         {
 2957                 isp_plcmd_t *p;
 2958                 int r;
 2959 
 2960                 va_start(ap, ctl);
 2961                 p = va_arg(ap, isp_plcmd_t *);
 2962                 va_end(ap);
 2963 
 2964                 if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
 2965                         return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
 2966                 }
 2967                 do {
 2968                         isp_next_handle(isp, &p->handle);
 2969                         r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
 2970                         if ((r & 0xffff) == MBOX_PORT_ID_USED) {
 2971                                 p->handle = r >> 16;
 2972                                 r = 0;
 2973                                 break;
 2974                         }
 2975                 } while ((r & 0xffff) == MBOX_LOOP_ID_USED);
 2976                 return (r);
 2977         }
 2978         case ISPCTL_CHANGE_ROLE:
 2979         {
 2980                 int role;
 2981 
 2982                 va_start(ap, ctl);
 2983                 chan = va_arg(ap, int);
 2984                 role = va_arg(ap, int);
 2985                 va_end(ap);
 2986                 return (isp_fc_change_role(isp, chan, role));
 2987         }
 2988         default:
 2989                 isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
 2990                 break;
 2991 
 2992         }
 2993         return (-1);
 2994 }
 2995 
 2996 /*
 2997  * Interrupt Service Routine(s).
 2998  *
 2999  * External (OS) framework has done the appropriate locking,
 3000  * and the locking will be held throughout this function.
 3001  */
 3002 
 3003 #ifdef  ISP_TARGET_MODE
 3004 void
 3005 isp_intr_atioq(ispsoftc_t *isp)
 3006 {
 3007         void *addr;
 3008         uint32_t iptr, optr, oop;
 3009 
 3010         iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
 3011         optr = isp->isp_atioodx;
 3012         while (optr != iptr) {
 3013                 oop = optr;
 3014                 MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1);
 3015                 addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
 3016                 switch (((isphdr_t *)addr)->rqs_entry_type) {
 3017                 case RQSTYPE_NOTIFY:
 3018                 case RQSTYPE_ATIO:
 3019                 case RQSTYPE_NOTIFY_ACK:        /* Can be set to ATIO queue.*/
 3020                 case RQSTYPE_ABTS_RCVD:         /* Can be set to ATIO queue.*/
 3021                         (void) isp_target_notify(isp, addr, &oop,
 3022                             ATIO_QUEUE_LEN(isp));
 3023                         break;
 3024                 case RQSTYPE_RPT_ID_ACQ:        /* Can be set to ATIO queue.*/
 3025                 default:
 3026                         isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
 3027                         break;
 3028                 }
 3029                 optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp));
 3030         }
 3031         if (isp->isp_atioodx != optr) {
 3032                 ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
 3033                 isp->isp_atioodx = optr;
 3034         }
 3035 }
 3036 #endif
 3037 
 3038 void
 3039 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
 3040 {
 3041         int i, obits;
 3042 
 3043         if (!isp->isp_mboxbsy) {
 3044                 isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
 3045                 return;
 3046         }
 3047         obits = isp->isp_obits;
 3048         isp->isp_mboxtmp[0] = mbox0;
 3049         for (i = 1; i < ISP_NMBOX(isp); i++) {
 3050                 if ((obits & (1 << i)) == 0)
 3051                         continue;
 3052                 isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
 3053         }
 3054         isp->isp_mboxbsy = 0;
 3055 }
 3056 
 3057 void
 3058 isp_intr_respq(ispsoftc_t *isp)
 3059 {
 3060         XS_T *xs, *cont_xs;
 3061         uint8_t qe[QENTRY_LEN];
 3062         isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
 3063         ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
 3064         isphdr_t *hp;
 3065         uint8_t *resp, *snsp, etype;
 3066         uint16_t scsi_status;
 3067         uint32_t iptr, cont = 0, cptr, optr, rlen, slen, totslen;
 3068 #ifdef  ISP_TARGET_MODE
 3069         uint32_t sptr;
 3070 #endif
 3071 
 3072         /*
 3073          * We can't be getting this now.
 3074          */
 3075         if (isp->isp_state != ISP_RUNSTATE) {
 3076                 isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
 3077                 return;
 3078         }
 3079 
 3080         iptr = ISP_READ(isp, BIU2400_RSPINP);
 3081         optr = isp->isp_resodx;
 3082         while (optr != iptr) {
 3083                 cptr = optr;
 3084 #ifdef  ISP_TARGET_MODE
 3085                 sptr = optr;
 3086 #endif
 3087                 hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
 3088                 optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
 3089 
 3090                 /*
 3091                  * Synchronize our view of this response queue entry.
 3092                  */
 3093                 MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
 3094                 if (isp->isp_dblev & ISP_LOGDEBUG1)
 3095                         isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
 3096                 isp_get_hdr(isp, hp, &sp->req_header);
 3097 
 3098                 /*
 3099                  * Log IOCBs rejected by the firmware.  We can't really do
 3100                  * much more about them, since it just should not happen.
 3101                  */
 3102                 if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
 3103                         isp_print_qentry(isp, "invalid entry type", cptr, hp);
 3104                         continue;
 3105                 }
 3106                 if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
 3107                         isp_print_qentry(isp, "invalid entry parameter", cptr, hp);
 3108                         continue;
 3109                 }
 3110                 if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
 3111                         isp_print_qentry(isp, "invalid entry count", cptr, hp);
 3112                         continue;
 3113                 }
 3114                 if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
 3115                         isp_print_qentry(isp, "invalid entry order", cptr, hp);
 3116                         continue;
 3117                 }
 3118 
 3119                 etype = sp->req_header.rqs_entry_type;
 3120 
 3121                 /* We expected Status Continuation, but got different IOCB. */
 3122                 if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
 3123                         cont = 0;
 3124                         isp_done(cont_xs);
 3125                 }
 3126 
 3127                 if (isp_handle_control(isp, hp)) {
 3128                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3129                         continue;
 3130                 }
 3131 
 3132                 switch (etype) {
 3133                 case RQSTYPE_RESPONSE:
 3134                         isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
 3135                         break;
 3136                 case RQSTYPE_MARKER:
 3137                         isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
 3138                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3139                         continue;
 3140                 case RQSTYPE_STATUS_CONT:
 3141                         isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
 3142                         if (cont > 0) {
 3143                                 slen = min(cont, sizeof(scp->req_sense_data));
 3144                                 XS_SENSE_APPEND(cont_xs, scp->req_sense_data, slen);
 3145                                 cont -= slen;
 3146                                 if (cont == 0) {
 3147                                         isp_done(cont_xs);
 3148                                 } else {
 3149                                         isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
 3150                                             "Expecting Status Continuations for %u bytes",
 3151                                             cont);
 3152                                 }
 3153                         } else {
 3154                                 isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
 3155                         }
 3156                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3157                         continue;
 3158 #ifdef  ISP_TARGET_MODE
 3159                 case RQSTYPE_NOTIFY_ACK:        /* Can be set to ATIO queue. */
 3160                 case RQSTYPE_CTIO7:
 3161                 case RQSTYPE_ABTS_RCVD:         /* Can be set to ATIO queue. */
 3162                 case RQSTYPE_ABTS_RSP:
 3163                         isp_target_notify(isp, hp, &cptr, RESULT_QUEUE_LEN(isp));
 3164                         /* More then one IOCB could be consumed. */
 3165                         while (sptr != cptr) {
 3166                                 ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3167                                 sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
 3168                                 hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
 3169                         }
 3170                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3171                         optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
 3172                         continue;
 3173 #endif
 3174                 case RQSTYPE_RPT_ID_ACQ:        /* Can be set to ATIO queue.*/
 3175                         isp_handle_rpt_id_acq(isp, hp);
 3176                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3177                         continue;
 3178                 default:
 3179                         /* We don't know what was this -- log and skip. */
 3180                         isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
 3181                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3182                         continue;
 3183                 }
 3184 
 3185                 xs = isp_find_xs(isp, sp->req_handle);
 3186                 if (xs == NULL) {
 3187                         /*
 3188                          * Only whine if this isn't the expected fallout of
 3189                          * aborting the command or resetting the target.
 3190                          */
 3191                         if (sp->req_completion_status != RQCS_ABORTED &&
 3192                             sp->req_completion_status != RQCS_RESET_OCCURRED)
 3193                                 isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)",
 3194                                     sp->req_handle, sp->req_completion_status);
 3195                         ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3196                         continue;
 3197                 }
 3198 
 3199                 resp = snsp = sp->req_rsp_sense;
 3200                 rlen = slen = totslen = 0;
 3201                 scsi_status = sp->req_scsi_status;
 3202                 if (scsi_status & RQCS_RV) {
 3203                         rlen = sp->req_response_len;
 3204                         snsp += rlen;
 3205                 }
 3206                 if (scsi_status & RQCS_SV) {
 3207                         totslen = sp->req_sense_len;
 3208                         slen = MIN(totslen, sizeof(sp->req_rsp_sense) - rlen);
 3209                 }
 3210                 *XS_STSP(xs) = scsi_status & 0xff;
 3211                 if (scsi_status & RQCS_RESID)
 3212                         XS_SET_RESID(xs, sp->req_fcp_residual);
 3213                 else
 3214                         XS_SET_RESID(xs, 0);
 3215 
 3216                 if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
 3217                         const char *ptr;
 3218                         char lb[64];
 3219                         const char *rnames[10] = {
 3220                             "Task Management function complete",
 3221                             "FCP_DATA length different than FCP_BURST_LEN",
 3222                             "FCP_CMND fields invalid",
 3223                             "FCP_DATA parameter mismatch with FCP_DATA_RO",
 3224                             "Task Management function rejected",
 3225                             "Task Management function failed",
 3226                             NULL,
 3227                             NULL,
 3228                             "Task Management function succeeded",
 3229                             "Task Management function incorrect logical unit number",
 3230                         };
 3231                         uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
 3232                         if (code >= nitems(rnames) || rnames[code] == NULL) {
 3233                                 ISP_SNPRINTF(lb, sizeof(lb),
 3234                                     "Unknown FCP Response Code 0x%x", code);
 3235                                 ptr = lb;
 3236                         } else {
 3237                                 ptr = rnames[code];
 3238                         }
 3239                         isp_xs_prt(isp, xs, ISP_LOGWARN,
 3240                             "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
 3241                             rlen, ptr, XS_CDBP(xs)[0] & 0xff);
 3242                         if (code != FCP_RSPNS_TMF_DONE &&
 3243                             code != FCP_RSPNS_TMF_SUCCEEDED)
 3244                                 XS_SETERR(xs, HBA_BOTCH);
 3245                 }
 3246                 isp_parse_status_24xx(isp, sp, xs);
 3247                 if (slen > 0) {
 3248                         XS_SAVE_SENSE(xs, snsp, slen);
 3249                         if (totslen > slen) {
 3250                                 cont = totslen - slen;
 3251                                 cont_xs = xs;
 3252                                 isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
 3253                                     "Expecting Status Continuations for %u bytes",
 3254                                     cont);
 3255                         }
 3256                 }
 3257 
 3258                 ISP_DMAFREE(isp, xs);
 3259                 isp_destroy_handle(isp, sp->req_handle);
 3260                 ISP_MEMZERO(hp, QENTRY_LEN);    /* PERF */
 3261 
 3262                 /* Complete command if we expect no Status Continuations. */
 3263                 if (cont == 0)
 3264                         isp_done(xs);
 3265         }
 3266 
 3267         /* We haven't received all Status Continuations, but that is it. */
 3268         if (cont > 0)
 3269                 isp_done(cont_xs);
 3270 
 3271         /* If we processed any IOCBs, let ISP know about it. */
 3272         if (optr != isp->isp_resodx) {
 3273                 ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
 3274                 isp->isp_resodx = optr;
 3275         }
 3276 }
 3277 
 3278 
 3279 void
 3280 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
 3281 {
 3282         fcparam *fcp;
 3283         uint16_t chan;
 3284 
 3285         isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
 3286 
 3287         switch (mbox) {
 3288         case ASYNC_SYSTEM_ERROR:
 3289                 isp->isp_state = ISP_CRASHED;
 3290                 for (chan = 0; chan < isp->isp_nchan; chan++) {
 3291                         FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
 3292                         isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
 3293                 }
 3294                 /*
 3295                  * Were we waiting for a mailbox command to complete?
 3296                  * If so, it's dead, so wake up the waiter.
 3297                  */
 3298                 if (isp->isp_mboxbsy) {
 3299                         isp->isp_obits = 1;
 3300                         isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
 3301                         isp->isp_mboxbsy = 0;
 3302                 }
 3303                 /*
 3304                  * It's up to the handler for isp_async to reinit stuff and
 3305                  * restart the firmware
 3306                  */
 3307                 isp_async(isp, ISPASYNC_FW_CRASH);
 3308                 break;
 3309 
 3310         case ASYNC_RQS_XFER_ERR:
 3311                 isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
 3312                 break;
 3313 
 3314         case ASYNC_RSP_XFER_ERR:
 3315                 isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
 3316                 break;
 3317 
 3318         case ASYNC_ATIO_XFER_ERR:
 3319                 isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
 3320                 break;
 3321 
 3322         case ASYNC_LIP_OCCURRED:
 3323         case ASYNC_LIP_NOS_OLS_RECV:
 3324         case ASYNC_LIP_ERROR:
 3325         case ASYNC_PTPMODE:
 3326                 /*
 3327                  * These are broadcast events that have to be sent across
 3328                  * all active channels.
 3329                  */
 3330                 for (chan = 0; chan < isp->isp_nchan; chan++) {
 3331                         fcp = FCPARAM(isp, chan);
 3332                         int topo = fcp->isp_topo;
 3333 
 3334                         if (fcp->role == ISP_ROLE_NONE)
 3335                                 continue;
 3336                         if (fcp->isp_loopstate > LOOP_HAVE_LINK)
 3337                                 fcp->isp_loopstate = LOOP_HAVE_LINK;
 3338                         ISP_SET_SENDMARKER(isp, chan, 1);
 3339                         isp_async(isp, ISPASYNC_LIP, chan);
 3340 #ifdef  ISP_TARGET_MODE
 3341                         isp_target_async(isp, chan, mbox);
 3342 #endif
 3343                         /*
 3344                          * We've had problems with data corruption occurring on
 3345                          * commands that complete (with no apparent error) after
 3346                          * we receive a LIP. This has been observed mostly on
 3347                          * Local Loop topologies. To be safe, let's just mark
 3348                          * all active initiator commands as dead.
 3349                          */
 3350                         if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
 3351                                 int i, j;
 3352                                 for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
 3353                                         XS_T *xs;
 3354                                         isp_hdl_t *hdp;
 3355 
 3356                                         hdp = &isp->isp_xflist[i];
 3357                                         if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
 3358                                                 continue;
 3359                                         }
 3360                                         xs = hdp->cmd;
 3361                                         if (XS_CHANNEL(xs) != chan) {
 3362                                                 continue;
 3363                                         }
 3364                                         j++;
 3365                                         isp_prt(isp, ISP_LOG_WARN1,
 3366                                             "%d.%d.%jx bus reset set at %s:%u",
 3367                                             XS_CHANNEL(xs), XS_TGT(xs),
 3368                                             (uintmax_t)XS_LUN(xs),
 3369                                             __func__, __LINE__);
 3370                                         XS_SETERR(xs, HBA_BUSRESET);
 3371                                 }
 3372                                 if (j) {
 3373                                         isp_prt(isp, ISP_LOGERR, lipd, chan, j);
 3374                                 }
 3375                         }
 3376                 }
 3377                 break;
 3378 
 3379         case ASYNC_LOOP_UP:
 3380                 /*
 3381                  * This is a broadcast event that has to be sent across
 3382                  * all active channels.
 3383                  */
 3384                 for (chan = 0; chan < isp->isp_nchan; chan++) {
 3385                         fcp = FCPARAM(isp, chan);
 3386                         if (fcp->role == ISP_ROLE_NONE)
 3387                                 continue;
 3388                         fcp->isp_linkstate = 1;
 3389                         if (fcp->isp_loopstate < LOOP_HAVE_LINK)
 3390                                 fcp->isp_loopstate = LOOP_HAVE_LINK;
 3391                         ISP_SET_SENDMARKER(isp, chan, 1);
 3392                         isp_async(isp, ISPASYNC_LOOP_UP, chan);
 3393 #ifdef  ISP_TARGET_MODE
 3394                         isp_target_async(isp, chan, mbox);
 3395 #endif
 3396                 }
 3397                 break;
 3398 
 3399         case ASYNC_LOOP_DOWN:
 3400                 /*
 3401                  * This is a broadcast event that has to be sent across
 3402                  * all active channels.
 3403                  */
 3404                 for (chan = 0; chan < isp->isp_nchan; chan++) {
 3405                         fcp = FCPARAM(isp, chan);
 3406                         if (fcp->role == ISP_ROLE_NONE)
 3407                                 continue;
 3408                         ISP_SET_SENDMARKER(isp, chan, 1);
 3409                         fcp->isp_linkstate = 0;
 3410                         fcp->isp_loopstate = LOOP_NIL;
 3411                         isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
 3412 #ifdef  ISP_TARGET_MODE
 3413                         isp_target_async(isp, chan, mbox);
 3414 #endif
 3415                 }
 3416                 break;
 3417 
 3418         case ASYNC_LOOP_RESET:
 3419                 /*
 3420                  * This is a broadcast event that has to be sent across
 3421                  * all active channels.
 3422                  */
 3423                 for (chan = 0; chan < isp->isp_nchan; chan++) {
 3424                         fcp = FCPARAM(isp, chan);
 3425                         if (fcp->role == ISP_ROLE_NONE)
 3426                                 continue;
 3427                         ISP_SET_SENDMARKER(isp, chan, 1);
 3428                         if (fcp->isp_loopstate > LOOP_HAVE_LINK)
 3429                                 fcp->isp_loopstate = LOOP_HAVE_LINK;
 3430                         isp_async(isp, ISPASYNC_LOOP_RESET, chan);
 3431 #ifdef  ISP_TARGET_MODE
 3432                         isp_target_async(isp, chan, mbox);
 3433 #endif
 3434                 }
 3435                 break;
 3436 
 3437         case ASYNC_PDB_CHANGED:
 3438         {
 3439                 int echan, nphdl, nlstate, reason;
 3440 
 3441                 nphdl = ISP_READ(isp, OUTMAILBOX1);
 3442                 nlstate = ISP_READ(isp, OUTMAILBOX2);
 3443                 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
 3444                 if (ISP_CAP_MULTI_ID(isp)) {
 3445                         chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
 3446                         if (chan == 0xff || nphdl == NIL_HANDLE) {
 3447                                 chan = 0;
 3448                                 echan = isp->isp_nchan - 1;
 3449                         } else if (chan >= isp->isp_nchan) {
 3450                                 break;
 3451                         } else {
 3452                                 echan = chan;
 3453                         }
 3454                 } else {
 3455                         chan = echan = 0;
 3456                 }
 3457                 for (; chan <= echan; chan++) {
 3458                         fcp = FCPARAM(isp, chan);
 3459                         if (fcp->role == ISP_ROLE_NONE)
 3460                                 continue;
 3461                         if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
 3462                                 if (nphdl != NIL_HANDLE &&
 3463                                     nphdl == fcp->isp_login_hdl &&
 3464                                     reason == PDB24XX_AE_OPN_2)
 3465                                         continue;
 3466                                 fcp->isp_loopstate = LOOP_LTEST_DONE;
 3467                         } else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
 3468                                 fcp->isp_loopstate = LOOP_HAVE_LINK;
 3469                         isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
 3470                             ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
 3471                 }
 3472                 break;
 3473         }
 3474         case ASYNC_CHANGE_NOTIFY:
 3475         {
 3476                 int portid;
 3477 
 3478                 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
 3479                     ISP_READ(isp, OUTMAILBOX2);
 3480                 if (ISP_CAP_MULTI_ID(isp)) {
 3481                         chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
 3482                         if (chan >= isp->isp_nchan)
 3483                                 break;
 3484                 } else {
 3485                         chan = 0;
 3486                 }
 3487                 fcp = FCPARAM(isp, chan);
 3488                 if (fcp->role == ISP_ROLE_NONE)
 3489                         break;
 3490                 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
 3491                         fcp->isp_loopstate = LOOP_LTEST_DONE;
 3492                 else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
 3493                         fcp->isp_loopstate = LOOP_HAVE_LINK;
 3494                 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
 3495                     ISPASYNC_CHANGE_SNS, portid);
 3496                 break;
 3497         }
 3498         case ASYNC_ERR_LOGGING_DISABLED:
 3499                 isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
 3500                     ISP_READ(isp, OUTMAILBOX1));
 3501                 break;
 3502         case ASYNC_P2P_INIT_ERR:
 3503                 isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
 3504                     ISP_READ(isp, OUTMAILBOX1));
 3505                 break;
 3506         case ASYNC_RCV_ERR:
 3507                 isp_prt(isp, ISP_LOGWARN, "Receive Error");
 3508                 break;
 3509         case ASYNC_RJT_SENT:    /* same as ASYNC_QFULL_SENT */
 3510                 isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
 3511                 break;
 3512         case ASYNC_FW_RESTART_COMPLETE:
 3513                 isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
 3514                 break;
 3515         case ASYNC_TEMPERATURE_ALERT:
 3516                 isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
 3517                     ISP_READ(isp, OUTMAILBOX1));
 3518                 break;
 3519         case ASYNC_INTER_DRIVER_COMP:
 3520                 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
 3521                 break;
 3522         case ASYNC_INTER_DRIVER_NOTIFY:
 3523                 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
 3524                 break;
 3525         case ASYNC_INTER_DRIVER_TIME_EXT:
 3526                 isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
 3527                 break;
 3528         case ASYNC_TRANSCEIVER_INSERTION:
 3529                 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
 3530                     ISP_READ(isp, OUTMAILBOX1));
 3531                 break;
 3532         case ASYNC_TRANSCEIVER_REMOVAL:
 3533                 isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
 3534                 break;
 3535         case ASYNC_NIC_FW_STATE_CHANGE:
 3536                 isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
 3537                 break;
 3538         case ASYNC_AUTOLOAD_FW_COMPLETE:
 3539                 isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
 3540                 break;
 3541         case ASYNC_AUTOLOAD_FW_FAILURE:
 3542                 isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
 3543                 break;
 3544         default:
 3545                 isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
 3546                 break;
 3547         }
 3548 }
 3549 
 3550 /*
 3551  * Handle completions with control handles by waking up waiting threads.
 3552  */
 3553 static int
 3554 isp_handle_control(ispsoftc_t *isp, isphdr_t *hp)
 3555 {
 3556         uint32_t hdl;
 3557         void *ptr;
 3558 
 3559         switch (hp->rqs_entry_type) {
 3560         case RQSTYPE_RESPONSE:
 3561         case RQSTYPE_MARKER:
 3562         case RQSTYPE_NOTIFY_ACK:
 3563         case RQSTYPE_CTIO7:
 3564         case RQSTYPE_TSK_MGMT:
 3565         case RQSTYPE_CT_PASSTHRU:
 3566         case RQSTYPE_VP_MODIFY:
 3567         case RQSTYPE_VP_CTRL:
 3568         case RQSTYPE_ABORT_IO:
 3569         case RQSTYPE_MBOX:
 3570         case RQSTYPE_LOGIN:
 3571         case RQSTYPE_ELS_PASSTHRU:
 3572                 ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
 3573                 if (ISP_H2HT(hdl) != ISP_HANDLE_CTRL)
 3574                         break;
 3575                 ptr = isp_find_xs(isp, hdl);
 3576                 if (ptr != NULL) {
 3577                         isp_destroy_handle(isp, hdl);
 3578                         memcpy(ptr, hp, QENTRY_LEN);
 3579                         wakeup(ptr);
 3580                 }
 3581                 return (1);
 3582         }
 3583         return (0);
 3584 }
 3585 
 3586 static void
 3587 isp_handle_rpt_id_acq(ispsoftc_t *isp, isphdr_t *hp)
 3588 {
 3589         fcparam *fcp;
 3590         isp_ridacq_t rid;
 3591         int chan, c;
 3592         uint32_t portid;
 3593 
 3594         isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
 3595         portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
 3596             rid.ridacq_vp_port_lo;
 3597         if (rid.ridacq_format == 0) {
 3598                 for (chan = 0; chan < isp->isp_nchan; chan++) {
 3599                         fcp = FCPARAM(isp, chan);
 3600                         if (fcp->role == ISP_ROLE_NONE)
 3601                                 continue;
 3602                         c = (chan == 0) ? 127 : (chan - 1);
 3603                         if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
 3604                             chan == 0) {
 3605                                 fcp->isp_loopstate = LOOP_HAVE_LINK;
 3606                                 isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
 3607                                     chan, ISPASYNC_CHANGE_OTHER);
 3608                         } else {
 3609                                 fcp->isp_loopstate = LOOP_NIL;
 3610                                 isp_async(isp, ISPASYNC_LOOP_DOWN,
 3611                                     chan);
 3612                         }
 3613                 }
 3614         } else {
 3615                 fcp = FCPARAM(isp, rid.ridacq_vp_index);
 3616                 if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
 3617                     rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
 3618                         fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
 3619                         fcp->isp_portid = portid;
 3620                         fcp->isp_loopstate = LOOP_HAVE_ADDR;
 3621                         isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
 3622                             rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
 3623                 } else {
 3624                         fcp->isp_loopstate = LOOP_NIL;
 3625                         isp_async(isp, ISPASYNC_LOOP_DOWN,
 3626                             rid.ridacq_vp_index);
 3627                 }
 3628         }
 3629 }
 3630 
 3631 static void
 3632 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs)
 3633 {
 3634         int ru_marked, sv_marked;
 3635         int chan = XS_CHANNEL(xs);
 3636 
 3637         switch (sp->req_completion_status) {
 3638         case RQCS_COMPLETE:
 3639                 return;
 3640 
 3641         case RQCS_DMA_ERROR:
 3642                 isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
 3643                 if (XS_NOERR(xs))
 3644                         XS_SETERR(xs, HBA_BOTCH);
 3645                 break;
 3646 
 3647         case RQCS_TRANSPORT_ERROR:
 3648                 isp_xs_prt(isp, xs,  ISP_LOGERR, "Transport Error");
 3649                 if (XS_NOERR(xs))
 3650                         XS_SETERR(xs, HBA_BOTCH);
 3651                 break;
 3652 
 3653         case RQCS_RESET_OCCURRED:
 3654                 isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
 3655                 FCPARAM(isp, chan)->sendmarker = 1;
 3656                 if (XS_NOERR(xs))
 3657                         XS_SETERR(xs, HBA_BUSRESET);
 3658                 return;
 3659 
 3660         case RQCS_ABORTED:
 3661                 isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
 3662                 FCPARAM(isp, chan)->sendmarker = 1;
 3663                 if (XS_NOERR(xs))
 3664                         XS_SETERR(xs, HBA_ABORTED);
 3665                 return;
 3666 
 3667         case RQCS_TIMEOUT:
 3668                 isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
 3669                 if (XS_NOERR(xs))
 3670                         XS_SETERR(xs, HBA_CMDTIMEOUT);
 3671                 return;
 3672 
 3673         case RQCS_DATA_OVERRUN:
 3674                 XS_SET_RESID(xs, sp->req_resid);
 3675                 isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
 3676                 if (XS_NOERR(xs))
 3677                         XS_SETERR(xs, HBA_DATAOVR);
 3678                 return;
 3679 
 3680         case RQCS_DRE:          /* data reassembly error */
 3681                 isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
 3682                 if (XS_NOERR(xs))
 3683                         XS_SETERR(xs, HBA_BOTCH);
 3684                 return;
 3685 
 3686         case RQCS_TABORT:       /* aborted by target */
 3687                 isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
 3688                 if (XS_NOERR(xs))
 3689                         XS_SETERR(xs, HBA_ABORTED);
 3690                 return;
 3691 
 3692         case RQCS_DATA_UNDERRUN:
 3693                 ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
 3694                 /*
 3695                  * We can get an underrun w/o things being marked
 3696                  * if we got a non-zero status.
 3697                  */
 3698                 sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
 3699                 if ((ru_marked == 0 && sv_marked == 0) ||
 3700                     (sp->req_resid > XS_XFRLEN(xs))) {
 3701                         isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
 3702                         if (XS_NOERR(xs))
 3703                                 XS_SETERR(xs, HBA_BOTCH);
 3704                         return;
 3705                 }
 3706                 XS_SET_RESID(xs, sp->req_resid);
 3707                 isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
 3708                 return;
 3709 
 3710         case RQCS_PORT_UNAVAILABLE:
 3711                 /*
 3712                  * No such port on the loop. Moral equivalent of SELTIMEO
 3713                  */
 3714         case RQCS_PORT_LOGGED_OUT:
 3715         {
 3716                 const char *reason;
 3717                 uint8_t sts = sp->req_completion_status & 0xff;
 3718                 fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
 3719                 fcportdb_t *lp;
 3720 
 3721                 /*
 3722                  * It was there (maybe)- treat as a selection timeout.
 3723                  */
 3724                 if (sts == RQCS_PORT_UNAVAILABLE) {
 3725                         reason = "unavailable";
 3726                 } else {
 3727                         reason = "logout";
 3728                 }
 3729 
 3730                 isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
 3731                     chan, reason, XS_TGT(xs));
 3732 
 3733                 /* XXX: Should we trigger rescan or FW announce change? */
 3734 
 3735                 if (XS_NOERR(xs)) {
 3736                         lp = &fcp->portdb[XS_TGT(xs)];
 3737                         if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
 3738                                 *XS_STSP(xs) = SCSI_BUSY;
 3739                                 XS_SETERR(xs, HBA_TGTBSY);
 3740                         } else
 3741                                 XS_SETERR(xs, HBA_SELTIMEOUT);
 3742                 }
 3743                 return;
 3744         }
 3745         case RQCS_PORT_CHANGED:
 3746                 isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
 3747                 if (XS_NOERR(xs)) {
 3748                         *XS_STSP(xs) = SCSI_BUSY;
 3749                         XS_SETERR(xs, HBA_TGTBSY);
 3750                 }
 3751                 return;
 3752 
 3753         case RQCS_ENOMEM:       /* f/w resource unavailable */
 3754                 isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
 3755                 if (XS_NOERR(xs)) {
 3756                         *XS_STSP(xs) = SCSI_BUSY;
 3757                         XS_SETERR(xs, HBA_TGTBSY);
 3758                 }
 3759                 return;
 3760 
 3761         case RQCS_TMO:          /* task management overrun */
 3762                 isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
 3763                 if (XS_NOERR(xs)) {
 3764                         *XS_STSP(xs) = SCSI_BUSY;
 3765                         XS_SETERR(xs, HBA_TGTBSY);
 3766                 }
 3767                 return;
 3768 
 3769         default:
 3770                 isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
 3771                 break;
 3772         }
 3773         if (XS_NOERR(xs))
 3774                 XS_SETERR(xs, HBA_BOTCH);
 3775 }
 3776 
 3777 #define ISP_FC_IBITS(op)        ((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
 3778 #define ISP_FC_OBITS(op)        ((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
 3779 
 3780 #define ISP_FC_OPMAP(in0, out0)                                                   0,   0,   0, in0,    0,    0,    0, out0
 3781 #define ISP_FC_OPMAP_HALF(in1, in0, out1, out0)                                   0,   0, in1, in0,    0,    0, out1, out0
 3782 #define ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0)           in3, in2, in1, in0, out3, out2, out1, out0
 3783 static const uint32_t mbpfc[] = {
 3784         ISP_FC_OPMAP(0x01, 0x01),       /* 0x00: MBOX_NO_OP */
 3785         ISP_FC_OPMAP(0x1f, 0x01),       /* 0x01: MBOX_LOAD_RAM */
 3786         ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f),      /* 0x02: MBOX_EXEC_FIRMWARE */
 3787         ISP_FC_OPMAP(0xdf, 0x01),       /* 0x03: MBOX_DUMP_RAM */
 3788         ISP_FC_OPMAP(0x07, 0x07),       /* 0x04: MBOX_WRITE_RAM_WORD */
 3789         ISP_FC_OPMAP(0x03, 0x07),       /* 0x05: MBOX_READ_RAM_WORD */
 3790         ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),      /* 0x06: MBOX_MAILBOX_REG_TEST */
 3791         ISP_FC_OPMAP(0x07, 0x07),       /* 0x07: MBOX_VERIFY_CHECKSUM   */
 3792         ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f),   /* 0x08: MBOX_ABOUT_FIRMWARE */
 3793         ISP_FC_OPMAP(0xdf, 0x01),       /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
 3794         ISP_FC_OPMAP(0xdf, 0x01),       /* 0x0a: DUMP RAM */
 3795         ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01),        /* 0x0b: MBOX_LOAD_RISC_RAM */
 3796         ISP_FC_OPMAP(0x00, 0x00),       /* 0x0c: */
 3797         ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01),        /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
 3798         ISP_FC_OPMAP(0x01, 0x05),       /* 0x0e: MBOX_CHECK_FIRMWARE */
 3799         ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d),        /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
 3800         ISP_FC_OPMAP(0x1f, 0x11),       /* 0x10: MBOX_INIT_REQ_QUEUE */
 3801         ISP_FC_OPMAP(0x2f, 0x21),       /* 0x11: MBOX_INIT_RES_QUEUE */
 3802         ISP_FC_OPMAP(0x0f, 0x01),       /* 0x12: MBOX_EXECUTE_IOCB */
 3803         ISP_FC_OPMAP(0x03, 0x03),       /* 0x13: MBOX_WAKE_UP   */
 3804         ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03),        /* 0x14: MBOX_STOP_FIRMWARE */
 3805         ISP_FC_OPMAP(0x4f, 0x01),       /* 0x15: MBOX_ABORT */
 3806         ISP_FC_OPMAP(0x07, 0x01),       /* 0x16: MBOX_ABORT_DEVICE */
 3807         ISP_FC_OPMAP(0x07, 0x01),       /* 0x17: MBOX_ABORT_TARGET */
 3808         ISP_FC_OPMAP(0x03, 0x03),       /* 0x18: MBOX_BUS_RESET */
 3809         ISP_FC_OPMAP(0x07, 0x05),       /* 0x19: MBOX_STOP_QUEUE */
 3810         ISP_FC_OPMAP(0x07, 0x05),       /* 0x1a: MBOX_START_QUEUE */
 3811         ISP_FC_OPMAP(0x07, 0x05),       /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
 3812         ISP_FC_OPMAP(0x07, 0x05),       /* 0x1c: MBOX_ABORT_QUEUE */
 3813         ISP_FC_OPMAP(0x07, 0x03),       /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
 3814         ISP_FC_OPMAP(0x00, 0x00),       /* 0x1e: */
 3815         ISP_FC_OPMAP(0x01, 0x07),       /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
 3816         ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf),       /* 0x20: MBOX_GET_LOOP_ID */
 3817         ISP_FC_OPMAP(0x00, 0x00),       /* 0x21: */
 3818         ISP_FC_OPMAP(0x03, 0x4b),       /* 0x22: MBOX_GET_TIMEOUT_PARAMS */
 3819         ISP_FC_OPMAP(0x00, 0x00),       /* 0x23: */
 3820         ISP_FC_OPMAP(0x00, 0x00),       /* 0x24: */
 3821         ISP_FC_OPMAP(0x00, 0x00),       /* 0x25: */
 3822         ISP_FC_OPMAP(0x00, 0x00),       /* 0x26: */
 3823         ISP_FC_OPMAP(0x00, 0x00),       /* 0x27: */
 3824         ISP_FC_OPMAP(0x01, 0x03),       /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
 3825         ISP_FC_OPMAP(0x03, 0x07),       /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
 3826         ISP_FC_OPMAP(0x00, 0x00),       /* 0x2a: */
 3827         ISP_FC_OPMAP(0x00, 0x00),       /* 0x2b: */
 3828         ISP_FC_OPMAP(0x00, 0x00),       /* 0x2c: */
 3829         ISP_FC_OPMAP(0x00, 0x00),       /* 0x2d: */
 3830         ISP_FC_OPMAP(0x00, 0x00),       /* 0x2e: */
 3831         ISP_FC_OPMAP(0x00, 0x00),       /* 0x2f: */
 3832         ISP_FC_OPMAP(0x00, 0x00),       /* 0x30: */
 3833         ISP_FC_OPMAP(0x00, 0x00),       /* 0x31: */
 3834         ISP_FC_OPMAP(0x4b, 0x4b),       /* 0x32: MBOX_SET_TIMEOUT_PARAMS */
 3835         ISP_FC_OPMAP(0x00, 0x00),       /* 0x33: */
 3836         ISP_FC_OPMAP(0x00, 0x00),       /* 0x34: */
 3837         ISP_FC_OPMAP(0x00, 0x00),       /* 0x35: */
 3838         ISP_FC_OPMAP(0x00, 0x00),       /* 0x36: */
 3839         ISP_FC_OPMAP(0x00, 0x00),       /* 0x37: */
 3840         ISP_FC_OPMAP(0x0f, 0x01),       /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
 3841         ISP_FC_OPMAP(0x0f, 0x07),       /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
 3842         ISP_FC_OPMAP(0x00, 0x00),       /* 0x3a: */
 3843         ISP_FC_OPMAP(0x00, 0x00),       /* 0x3b: */
 3844         ISP_FC_OPMAP(0x00, 0x00),       /* 0x3c: */
 3845         ISP_FC_OPMAP(0x00, 0x00),       /* 0x3d: */
 3846         ISP_FC_OPMAP(0x00, 0x00),       /* 0x3e: */
 3847         ISP_FC_OPMAP(0x00, 0x00),       /* 0x3f: */
 3848         ISP_FC_OPMAP(0x03, 0x01),       /* 0x40: MBOX_LOOP_PORT_BYPASS */
 3849         ISP_FC_OPMAP(0x03, 0x01),       /* 0x41: MBOX_LOOP_PORT_ENABLE */
 3850         ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf),       /* 0x42: MBOX_GET_RESOURCE_COUNT */
 3851         ISP_FC_OPMAP(0x01, 0x01),       /* 0x43: MBOX_REQUEST_OFFLINE_MODE */
 3852         ISP_FC_OPMAP(0x00, 0x00),       /* 0x44: */
 3853         ISP_FC_OPMAP(0x00, 0x00),       /* 0x45: */
 3854         ISP_FC_OPMAP(0x00, 0x00),       /* 0x46: */
 3855         ISP_FC_OPMAP(0xcf, 0x03),       /* 0x47: GET PORT_DATABASE ENHANCED */
 3856         ISP_FC_OPMAP(0xcf, 0x0f),       /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
 3857         ISP_FC_OPMAP(0xcd, 0x01),       /* 0x49: MBOX_GET_VP_DATABASE */
 3858         ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01),        /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
 3859         ISP_FC_OPMAP(0x00, 0x00),       /* 0x4b: */
 3860         ISP_FC_OPMAP(0x00, 0x00),       /* 0x4c: */
 3861         ISP_FC_OPMAP(0x00, 0x00),       /* 0x4d: */
 3862         ISP_FC_OPMAP(0x00, 0x00),       /* 0x4e: */
 3863         ISP_FC_OPMAP(0x00, 0x00),       /* 0x4f: */
 3864         ISP_FC_OPMAP(0x00, 0x00),       /* 0x50: */
 3865         ISP_FC_OPMAP(0x00, 0x00),       /* 0x51: */
 3866         ISP_FC_OPMAP(0x00, 0x00),       /* 0x52: */
 3867         ISP_FC_OPMAP(0x00, 0x00),       /* 0x53: */
 3868         ISP_FC_OPMAP(0xcf, 0x01),       /* 0x54: EXECUTE IOCB A64 */
 3869         ISP_FC_OPMAP(0x00, 0x00),       /* 0x55: */
 3870         ISP_FC_OPMAP(0x00, 0x00),       /* 0x56: */
 3871         ISP_FC_OPMAP(0x00, 0x00),       /* 0x57: */
 3872         ISP_FC_OPMAP(0x00, 0x00),       /* 0x58: */
 3873         ISP_FC_OPMAP(0x00, 0x00),       /* 0x59: */
 3874         ISP_FC_OPMAP(0x00, 0x00),       /* 0x5a: */
 3875         ISP_FC_OPMAP(0x03, 0x01),       /* 0x5b: MBOX_DRIVER_HEARTBEAT */
 3876         ISP_FC_OPMAP(0xcf, 0x01),       /* 0x5c: MBOX_FW_HEARTBEAT */
 3877         ISP_FC_OPMAP(0x07, 0x1f),       /* 0x5d: MBOX_GET_SET_DATA_RATE */
 3878         ISP_FC_OPMAP(0x00, 0x00),       /* 0x5e: */
 3879         ISP_FC_OPMAP(0x00, 0x00),       /* 0x5f: */
 3880         ISP_FC_OPMAP(0xcf, 0x0f),       /* 0x60: MBOX_INIT_FIRMWARE */
 3881         ISP_FC_OPMAP(0x00, 0x00),       /* 0x61: */
 3882         ISP_FC_OPMAP(0x01, 0x01),       /* 0x62: MBOX_INIT_LIP */
 3883         ISP_FC_OPMAP(0xcd, 0x03),       /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
 3884         ISP_FC_OPMAP(0xcf, 0x01),       /* 0x64: MBOX_GET_PORT_DB */
 3885         ISP_FC_OPMAP(0x07, 0x01),       /* 0x65: MBOX_CLEAR_ACA */
 3886         ISP_FC_OPMAP(0x07, 0x01),       /* 0x66: MBOX_TARGET_RESET */
 3887         ISP_FC_OPMAP(0x07, 0x01),       /* 0x67: MBOX_CLEAR_TASK_SET */
 3888         ISP_FC_OPMAP(0x07, 0x01),       /* 0x68: MBOX_ABORT_TASK_SET */
 3889         ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f),      /* 0x69: MBOX_GET_FW_STATE */
 3890         ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf),        /* 0x6a: MBOX_GET_PORT_NAME */
 3891         ISP_FC_OPMAP(0xcf, 0x01),       /* 0x6b: MBOX_GET_LINK_STATUS */
 3892         ISP_FC_OPMAP(0x0f, 0x01),       /* 0x6c: MBOX_INIT_LIP_RESET */
 3893         ISP_FC_OPMAP(0x00, 0x00),       /* 0x6d: */
 3894         ISP_FC_OPMAP(0xcf, 0x03),       /* 0x6e: MBOX_SEND_SNS */
 3895         ISP_FC_OPMAP(0x0f, 0x07),       /* 0x6f: MBOX_FABRIC_LOGIN */
 3896         ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03),      /* 0x70: MBOX_SEND_CHANGE_REQUEST */
 3897         ISP_FC_OPMAP(0x03, 0x03),       /* 0x71: MBOX_FABRIC_LOGOUT */
 3898         ISP_FC_OPMAP(0x0f, 0x0f),       /* 0x72: MBOX_INIT_LIP_LOGIN */
 3899         ISP_FC_OPMAP(0x00, 0x00),       /* 0x73: */
 3900         ISP_FC_OPMAP(0x07, 0x01),       /* 0x74: LOGIN LOOP PORT */
 3901         ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07),      /* 0x75: GET PORT/NODE NAME LIST */
 3902         ISP_FC_OPMAP(0x4f, 0x01),       /* 0x76: SET VENDOR ID */
 3903         ISP_FC_OPMAP(0xcd, 0x01),       /* 0x77: INITIALIZE IP MAILBOX */
 3904         ISP_FC_OPMAP(0x00, 0x00),       /* 0x78: */
 3905         ISP_FC_OPMAP(0x00, 0x00),       /* 0x79: */
 3906         ISP_FC_OPMAP(0x00, 0x00),       /* 0x7a: */
 3907         ISP_FC_OPMAP(0x00, 0x00),       /* 0x7b: */
 3908         ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07),      /* 0x7c: Get ID List */
 3909         ISP_FC_OPMAP(0xcf, 0x01),       /* 0x7d: SEND LFA */
 3910         ISP_FC_OPMAP(0x0f, 0x01)        /* 0x7e: LUN RESET */
 3911 };
 3912 #define MAX_FC_OPCODE   0x7e
 3913 /*
 3914  * Footnotes
 3915  *
 3916  * (1): this sets bits 21..16 in mailbox register #8, which we nominally
 3917  *      do not access at this time in the core driver. The caller is
 3918  *      responsible for setting this register first (Gross!). The assumption
 3919  *      is that we won't overflow.
 3920  */
 3921 
 3922 static const char *fc_mbcmd_names[] = {
 3923         "NO-OP",                        /* 00h */
 3924         "LOAD RAM",
 3925         "EXEC FIRMWARE",
 3926         "DUMP RAM",
 3927         "WRITE RAM WORD",
 3928         "READ RAM WORD",
 3929         "MAILBOX REG TEST",
 3930         "VERIFY CHECKSUM",
 3931         "ABOUT FIRMWARE",
 3932         "LOAD RAM (2100)",
 3933         "DUMP RAM",
 3934         "LOAD RISC RAM",
 3935         "DUMP RISC RAM",
 3936         "WRITE RAM WORD EXTENDED",
 3937         "CHECK FIRMWARE",
 3938         "READ RAM WORD EXTENDED",
 3939         "INIT REQUEST QUEUE",           /* 10h */
 3940         "INIT RESULT QUEUE",
 3941         "EXECUTE IOCB",
 3942         "WAKE UP",
 3943         "STOP FIRMWARE",
 3944         "ABORT",
 3945         "ABORT DEVICE",
 3946         "ABORT TARGET",
 3947         "BUS RESET",
 3948         "STOP QUEUE",
 3949         "START QUEUE",
 3950         "SINGLE STEP QUEUE",
 3951         "ABORT QUEUE",
 3952         "GET DEV QUEUE STATUS",
 3953         NULL,
 3954         "GET FIRMWARE STATUS",
 3955         "GET LOOP ID",                  /* 20h */
 3956         NULL,
 3957         "GET TIMEOUT PARAMS",
 3958         NULL,
 3959         NULL,
 3960         NULL,
 3961         NULL,
 3962         NULL,
 3963         "GET FIRMWARE OPTIONS",
 3964         "GET PORT QUEUE PARAMS",
 3965         "GENERATE SYSTEM ERROR",
 3966         NULL,
 3967         NULL,
 3968         NULL,
 3969         NULL,
 3970         NULL,
 3971         "WRITE SFP",                    /* 30h */
 3972         "READ SFP",
 3973         "SET TIMEOUT PARAMS",
 3974         NULL,
 3975         NULL,
 3976         NULL,
 3977         NULL,
 3978         NULL,
 3979         "SET FIRMWARE OPTIONS",
 3980         "SET PORT QUEUE PARAMS",
 3981         NULL,
 3982         "SET FC LED CONF",
 3983         NULL,
 3984         "RESTART NIC FIRMWARE",
 3985         "ACCESS CONTROL",
 3986         NULL,
 3987         "LOOP PORT BYPASS",             /* 40h */
 3988         "LOOP PORT ENABLE",
 3989         "GET RESOURCE COUNT",
 3990         "REQUEST NON PARTICIPATING MODE",
 3991         "DIAGNOSTIC ECHO TEST",
 3992         "DIAGNOSTIC LOOPBACK",
 3993         NULL,
 3994         "GET PORT DATABASE ENHANCED",
 3995         "INIT FIRMWARE MULTI ID",
 3996         "GET VP DATABASE",
 3997         "GET VP DATABASE ENTRY",
 3998         NULL,
 3999         NULL,
 4000         NULL,
 4001         NULL,
 4002         NULL,
 4003         "GET FCF LIST",                 /* 50h */
 4004         "GET DCBX PARAMETERS",
 4005         NULL,
 4006         "HOST MEMORY COPY",
 4007         "EXECUTE IOCB A64",
 4008         NULL,
 4009         NULL,
 4010         "SEND RNID",
 4011         NULL,
 4012         "SET PARAMETERS",
 4013         "GET PARAMETERS",
 4014         "DRIVER HEARTBEAT",
 4015         "FIRMWARE HEARTBEAT",
 4016         "GET/SET DATA RATE",
 4017         "SEND RNFT",
 4018         NULL,
 4019         "INIT FIRMWARE",                /* 60h */
 4020         "GET INIT CONTROL BLOCK",
 4021         "INIT LIP",
 4022         "GET FC-AL POSITION MAP",
 4023         "GET PORT DATABASE",
 4024         "CLEAR ACA",
 4025         "TARGET RESET",
 4026         "CLEAR TASK SET",
 4027         "ABORT TASK SET",
 4028         "GET FW STATE",
 4029         "GET PORT NAME",
 4030         "GET LINK STATUS",
 4031         "INIT LIP RESET",
 4032         "GET LINK STATS & PRIVATE DATA CNTS",
 4033         "SEND SNS",
 4034         "FABRIC LOGIN",
 4035         "SEND CHANGE REQUEST",          /* 70h */
 4036         "FABRIC LOGOUT",
 4037         "INIT LIP LOGIN",
 4038         NULL,
 4039         "LOGIN LOOP PORT",
 4040         "GET PORT/NODE NAME LIST",
 4041         "SET VENDOR ID",
 4042         "INITIALIZE IP MAILBOX",
 4043         NULL,
 4044         NULL,
 4045         "GET XGMAC STATS",
 4046         NULL,
 4047         "GET ID LIST",
 4048         "SEND LFA",
 4049         "LUN RESET"
 4050 };
 4051 
 4052 static void
 4053 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
 4054 {
 4055         const char *cname, *xname, *sname;
 4056         char tname[16], mname[16];
 4057         unsigned int ibits, obits, box, opcode, t, to;
 4058 
 4059         opcode = mbp->param[0];
 4060         if (opcode > MAX_FC_OPCODE) {
 4061                 mbp->param[0] = MBOX_INVALID_COMMAND;
 4062                 isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
 4063                 return;
 4064         }
 4065         cname = fc_mbcmd_names[opcode];
 4066         ibits = ISP_FC_IBITS(opcode);
 4067         obits = ISP_FC_OBITS(opcode);
 4068         if (cname == NULL) {
 4069                 cname = tname;
 4070                 ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
 4071         }
 4072         isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
 4073 
 4074         /*
 4075          * Pick up any additional bits that the caller might have set.
 4076          */
 4077         ibits |= mbp->ibits;
 4078         obits |= mbp->obits;
 4079 
 4080         /*
 4081          * Mask any bits that the caller wants us to mask
 4082          */
 4083         ibits &= mbp->ibitm;
 4084         obits &= mbp->obitm;
 4085 
 4086 
 4087         if (ibits == 0 && obits == 0) {
 4088                 mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
 4089                 isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
 4090                 return;
 4091         }
 4092 
 4093         for (box = 0; box < ISP_NMBOX(isp); box++) {
 4094                 if (ibits & (1 << box)) {
 4095                         isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
 4096                             mbp->param[box]);
 4097                         ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
 4098                 }
 4099                 isp->isp_mboxtmp[box] = mbp->param[box] = 0;
 4100         }
 4101 
 4102         isp->isp_obits = obits;
 4103         isp->isp_mboxbsy = 1;
 4104 
 4105         /*
 4106          * Set Host Interrupt condition so that RISC will pick up mailbox regs.
 4107          */
 4108         ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
 4109 
 4110         /*
 4111          * While we haven't finished the command, spin our wheels here.
 4112          */
 4113         to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
 4114         for (t = 0; t < to; t += 100) {
 4115                 if (!isp->isp_mboxbsy)
 4116                         break;
 4117                 ISP_RUN_ISR(isp);
 4118                 if (!isp->isp_mboxbsy)
 4119                         break;
 4120                 ISP_DELAY(100);
 4121         }
 4122 
 4123         /*
 4124          * Did the command time out?
 4125          */
 4126         if (isp->isp_mboxbsy) {
 4127                 isp->isp_mboxbsy = 0;
 4128                 isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)",
 4129                     opcode, to, mbp->func, mbp->lineno);
 4130                 mbp->param[0] = MBOX_TIMEOUT;
 4131                 goto out;
 4132         }
 4133 
 4134         /*
 4135          * Copy back output registers.
 4136          */
 4137         for (box = 0; box < ISP_NMBOX(isp); box++) {
 4138                 if (obits & (1 << box)) {
 4139                         mbp->param[box] = isp->isp_mboxtmp[box];
 4140                         isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
 4141                             mbp->param[box]);
 4142                 }
 4143         }
 4144 
 4145 out:
 4146         if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
 4147                 return;
 4148 
 4149         if ((mbp->param[0] & 0xbfe0) == 0 &&
 4150             (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
 4151                 return;
 4152 
 4153         xname = NULL;
 4154         sname = "";
 4155         switch (mbp->param[0]) {
 4156         case MBOX_INVALID_COMMAND:
 4157                 xname = "INVALID COMMAND";
 4158                 break;
 4159         case MBOX_HOST_INTERFACE_ERROR:
 4160                 xname = "HOST INTERFACE ERROR";
 4161                 break;
 4162         case MBOX_TEST_FAILED:
 4163                 xname = "TEST FAILED";
 4164                 break;
 4165         case MBOX_COMMAND_ERROR:
 4166                 xname = "COMMAND ERROR";
 4167                 ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
 4168                     mbp->param[1]);
 4169                 sname = mname;
 4170                 break;
 4171         case MBOX_COMMAND_PARAM_ERROR:
 4172                 xname = "COMMAND PARAMETER ERROR";
 4173                 break;
 4174         case MBOX_PORT_ID_USED:
 4175                 xname = "PORT ID ALREADY IN USE";
 4176                 break;
 4177         case MBOX_LOOP_ID_USED:
 4178                 xname = "LOOP ID ALREADY IN USE";
 4179                 break;
 4180         case MBOX_ALL_IDS_USED:
 4181                 xname = "ALL LOOP IDS IN USE";
 4182                 break;
 4183         case MBOX_NOT_LOGGED_IN:
 4184                 xname = "NOT LOGGED IN";
 4185                 break;
 4186         case MBOX_LINK_DOWN_ERROR:
 4187                 xname = "LINK DOWN ERROR";
 4188                 break;
 4189         case MBOX_LOOPBACK_ERROR:
 4190                 xname = "LOOPBACK ERROR";
 4191                 break;
 4192         case MBOX_CHECKSUM_ERROR:
 4193                 xname = "CHECKSUM ERROR";
 4194                 break;
 4195         case MBOX_INVALID_PRODUCT_KEY:
 4196                 xname = "INVALID PRODUCT KEY";
 4197                 break;
 4198         case MBOX_REGS_BUSY:
 4199                 xname = "REGISTERS BUSY";
 4200                 break;
 4201         case MBOX_TIMEOUT:
 4202                 xname = "TIMEOUT";
 4203                 break;
 4204         default:
 4205                 ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
 4206                 xname = mname;
 4207                 break;
 4208         }
 4209         if (xname) {
 4210                 isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
 4211                     cname, xname, sname);
 4212         }
 4213 }
 4214 
 4215 static int
 4216 isp_fw_state(ispsoftc_t *isp, int chan)
 4217 {
 4218         mbreg_t mbs;
 4219 
 4220         MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
 4221         isp_mboxcmd(isp, &mbs);
 4222         if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
 4223                 return (mbs.param[1]);
 4224         return (FW_ERROR);
 4225 }
 4226 
 4227 static void
 4228 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
 4229 {
 4230         fcparam *fcp = FCPARAM(isp, chan);
 4231 
 4232         /*
 4233          * Establish some default parameters.
 4234          */
 4235         fcp->role = DEFAULT_ROLE(isp, chan);
 4236         fcp->isp_retry_delay = ICB_DFLT_RDELAY;
 4237         fcp->isp_retry_count = ICB_DFLT_RCOUNT;
 4238         fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
 4239         fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
 4240         fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
 4241         fcp->isp_fwoptions = 0;
 4242         fcp->isp_xfwoptions = 0;
 4243         fcp->isp_zfwoptions = 0;
 4244         fcp->isp_lasthdl = NIL_HANDLE;
 4245         fcp->isp_login_hdl = NIL_HANDLE;
 4246 
 4247         fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
 4248         fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
 4249         if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
 4250                 fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
 4251         fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
 4252         fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
 4253         fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
 4254 
 4255         /*
 4256          * Now try and read NVRAM unless told to not do so.
 4257          * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
 4258          */
 4259         if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
 4260                 int i, j = 0;
 4261                 /*
 4262                  * Give a couple of tries at reading NVRAM.
 4263                  */
 4264                 for (i = 0; i < 2; i++) {
 4265                         j = isp_read_nvram(isp, chan);
 4266                         if (j == 0) {
 4267                                 break;
 4268                         }
 4269                 }
 4270                 if (j) {
 4271                         isp->isp_confopts |= ISP_CFG_NONVRAM;
 4272                 }
 4273         }
 4274 
 4275         fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
 4276         fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
 4277         isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
 4278             chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
 4279             (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
 4280             isp_class3_roles[fcp->role]);
 4281 }
 4282 
 4283 /*
 4284  * Re-initialize the ISP and complete all orphaned commands
 4285  * with a 'botched' notice. The reset/init routines should
 4286  * not disturb an already active list of commands.
 4287  */
 4288 
 4289 int
 4290 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
 4291 {
 4292         int i, res = 0;
 4293 
 4294         if (isp->isp_state > ISP_RESETSTATE)
 4295                 isp_stop(isp);
 4296         if (isp->isp_state != ISP_RESETSTATE)
 4297                 isp_reset(isp, do_load_defaults);
 4298         if (isp->isp_state != ISP_RESETSTATE) {
 4299                 res = EIO;
 4300                 isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
 4301                 goto cleanup;
 4302         }
 4303 
 4304         isp_init(isp);
 4305         if (isp->isp_state > ISP_RESETSTATE &&
 4306             isp->isp_state != ISP_RUNSTATE) {
 4307                 res = EIO;
 4308                 isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
 4309                 ISP_DISABLE_INTS(isp);
 4310         }
 4311 
 4312 cleanup:
 4313         isp_clear_commands(isp);
 4314         for (i = 0; i < isp->isp_nchan; i++)
 4315                 isp_clear_portdb(isp, i);
 4316         return (res);
 4317 }
 4318 
 4319 /*
 4320  * NVRAM Routines
 4321  */
 4322 static int
 4323 isp_read_nvram(ispsoftc_t *isp, int bus)
 4324 {
 4325 
 4326         return (isp_read_nvram_2400(isp));
 4327 }
 4328 
 4329 static int
 4330 isp_read_nvram_2400(ispsoftc_t *isp)
 4331 {
 4332         int retval = 0;
 4333         uint32_t addr, csum, lwrds, *dptr;
 4334         uint8_t nvram_data[ISP2400_NVRAM_SIZE];
 4335 
 4336         addr = ISP2400_NVRAM_PORT_ADDR(isp->isp_port);
 4337         dptr = (uint32_t *) nvram_data;
 4338         for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
 4339                 isp_rd_2400_nvram(isp, addr++, dptr++);
 4340         }
 4341         if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
 4342             nvram_data[2] != 'P') {
 4343                 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
 4344                     nvram_data[0], nvram_data[1], nvram_data[2]);
 4345                 retval = -1;
 4346                 goto out;
 4347         }
 4348         dptr = (uint32_t *) nvram_data;
 4349         for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
 4350                 uint32_t tmp;
 4351                 ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
 4352                 csum += tmp;
 4353         }
 4354         if (csum != 0) {
 4355                 isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
 4356                 retval = -1;
 4357                 goto out;
 4358         }
 4359         isp_parse_nvram_2400(isp, nvram_data);
 4360 out:
 4361         return (retval);
 4362 }
 4363 
 4364 static void
 4365 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
 4366 {
 4367         int loops = 0;
 4368         uint32_t base = 0x7ffe0000;
 4369         uint32_t tmp = 0;
 4370 
 4371         if (IS_26XX(isp)) {
 4372                 base = 0x7fe7c000;      /* XXX: Observation, may be wrong. */
 4373         } else if (IS_25XX(isp)) {
 4374                 base = 0x7ff00000 | 0x48000;
 4375         }
 4376         ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
 4377         for (loops = 0; loops < 5000; loops++) {
 4378                 ISP_DELAY(10);
 4379                 tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
 4380                 if ((tmp & (1U << 31)) != 0) {
 4381                         break;
 4382                 }
 4383         }
 4384         if (tmp & (1U << 31)) {
 4385                 *rp = ISP_READ(isp, BIU2400_FLASH_DATA);
 4386                 ISP_SWIZZLE_NVRAM_LONG(isp, rp);
 4387         } else {
 4388                 *rp = 0xffffffff;
 4389         }
 4390 }
 4391 
 4392 static void
 4393 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
 4394 {
 4395         fcparam *fcp = FCPARAM(isp, 0);
 4396         uint64_t wwn;
 4397 
 4398         isp_prt(isp, ISP_LOGDEBUG0,
 4399             "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d",
 4400             (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
 4401             (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
 4402             (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
 4403             (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
 4404             ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
 4405         isp_prt(isp, ISP_LOGDEBUG0,
 4406             "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
 4407             ISP2400_NVRAM_HARDLOOPID(nvram_data),
 4408             ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
 4409             ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
 4410             ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
 4411 
 4412         wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
 4413         fcp->isp_wwpn_nvram = wwn;
 4414 
 4415         wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
 4416         if (wwn) {
 4417                 if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
 4418                         wwn = 0;
 4419                 }
 4420         }
 4421         if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
 4422                 wwn = fcp->isp_wwpn_nvram;
 4423                 wwn &= ~((uint64_t) 0xfff << 48);
 4424         }
 4425         fcp->isp_wwnn_nvram = wwn;
 4426 
 4427         if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
 4428                 DEFAULT_FRAMESIZE(isp) =
 4429                     ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
 4430         }
 4431         if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
 4432                 fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
 4433         }
 4434         fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
 4435         fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
 4436         fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);
 4437 }

Cache object: 267e0748e45f2174afa7124f8ee7d0c4


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