[BACK]Return to isp.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/isp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: isp.c,v 1.39 2007/05/23 01:32:25 ray Exp $ */
        !             2: /*
        !             3:  * Machine and OS Independent (well, as best as possible)
        !             4:  * code for the Qlogic ISP SCSI adapters.
        !             5:  *
        !             6:  * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob
        !             7:  * Feral Software
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice immediately at the beginning of the file, without modification,
        !            15:  *    this list of conditions, and the following disclaimer.
        !            16:  * 2. The name of the author may not be used to endorse or promote products
        !            17:  *    derived from this software without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            23:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  */
        !            31:
        !            32: /*
        !            33:  * Inspiration and ideas about this driver are from Erik Moe's Linux driver
        !            34:  * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
        !            35:  * ideas dredged from the Solaris driver.
        !            36:  */
        !            37:
        !            38: /*
        !            39:  * Include header file appropriate for platform we're building on.
        !            40:  */
        !            41:
        !            42: #ifdef __NetBSD__
        !            43: #include <dev/ic/isp_netbsd.h>
        !            44: #endif
        !            45: #ifdef __FreeBSD__
        !            46: #include <dev/isp/isp_freebsd.h>
        !            47: #endif
        !            48: #ifdef __OpenBSD__
        !            49: #include <dev/ic/isp_openbsd.h>
        !            50: #endif
        !            51: #ifdef __linux__
        !            52: #include "isp_linux.h"
        !            53: #endif
        !            54: #ifdef __svr4__
        !            55: #include "isp_solaris.h"
        !            56: #endif
        !            57:
        !            58: /*
        !            59:  * General defines
        !            60:  */
        !            61:
        !            62: #define        MBOX_DELAY_COUNT        1000000 / 100
        !            63:
        !            64: /*
        !            65:  * Local static data
        !            66:  */
        !            67: static const char portshift[] =
        !            68:     "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)";
        !            69: static const char portdup[] =
        !            70:     "Target %d duplicates Target %d- killing off both";
        !            71: static const char retained[] =
        !            72:     "Retaining Loop ID 0x%x for Target %d (Port 0x%x)";
        !            73: static const char lretained[] =
        !            74:     "Retained login of Target %d (Loop ID 0x%x) Port 0x%x";
        !            75: static const char plogout[] =
        !            76:     "Logging out Target %d at Loop ID 0x%x (Port 0x%x)";
        !            77: static const char plogierr[] =
        !            78:     "Command Error in PLOGI for Port 0x%x (0x%x)";
        !            79: static const char nopdb[] =
        !            80:     "Could not get PDB for Device @ Port 0x%x";
        !            81: static const char pdbmfail1[] =
        !            82:     "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)";
        !            83: static const char pdbmfail2[] =
        !            84:     "PDB Port info for Device @ Port 0x%x does not match up (0x%x)";
        !            85: static const char ldumped[] =
        !            86:     "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch";
        !            87: static const char notresp[] =
        !            88:   "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
        !            89: static const char xact1[] =
        !            90:     "HBA attempted queued transaction with disconnect not set for %d.%d.%d";
        !            91: static const char xact2[] =
        !            92:     "HBA attempted queued transaction to target routine %d on target %d bus %d";
        !            93: static const char xact3[] =
        !            94:     "HBA attempted queued cmd for %d.%d.%d when queueing disabled";
        !            95: static const char pskip[] =
        !            96:     "SCSI phase skipped for target %d.%d.%d";
        !            97: static const char topology[] =
        !            98:     "Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'";
        !            99: static const char swrej[] =
        !           100:     "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";
        !           101: static const char finmsg[] =
        !           102:     "(%d.%d.%d): FIN dl%d resid %lu STS 0x%x SKEY %c XS_ERR=0x%x";
        !           103: static const char sc0[] =
        !           104:     "%s CHAN %d FTHRSH %d IID %d RESETD %d RETRYC %d RETRYD %d ASD 0x%x";
        !           105: static const char sc1[] =
        !           106:     "%s RAAN 0x%x DLAN 0x%x DDMAB 0x%x CDMAB 0x%x SELTIME %d MQD %d";
        !           107: static const char sc2[] = "%s CHAN %d TGT %d FLAGS 0x%x 0x%x/0x%x";
        !           108: static const char sc3[] = "Generated";
        !           109: static const char sc4[] = "NVRAM";
        !           110: static const char bun[] =
        !           111:     "bad underrun for %d.%d (count %d, resid %d, status %s)";
        !           112:
        !           113: /*
        !           114:  * Local function prototypes.
        !           115:  */
        !           116: static int isp_parse_async(struct ispsoftc *, u_int16_t);
        !           117: static int isp_handle_other_response(struct ispsoftc *, int, isphdr_t *,
        !           118:     u_int16_t *);
        !           119: static void
        !           120: isp_parse_status(struct ispsoftc *, ispstatusreq_t *, XS_T *);
        !           121: static void isp_fastpost_complete(struct ispsoftc *, u_int16_t);
        !           122: static int isp_mbox_continue(struct ispsoftc *);
        !           123: static void isp_scsi_init(struct ispsoftc *);
        !           124: static void isp_scsi_channel_init(struct ispsoftc *, int);
        !           125: static void isp_fibre_init(struct ispsoftc *);
        !           126: static void isp_mark_getpdb_all(struct ispsoftc *);
        !           127: static int isp_getmap(struct ispsoftc *, fcpos_map_t *);
        !           128: static int isp_getpdb(struct ispsoftc *, int, isp_pdb_t *);
        !           129: static u_int64_t isp_get_portname(struct ispsoftc *, int, int);
        !           130: static int isp_fclink_test(struct ispsoftc *, int);
        !           131: static char *isp2100_fw_statename(int);
        !           132: static int isp_pdb_sync(struct ispsoftc *);
        !           133: static int isp_scan_loop(struct ispsoftc *);
        !           134: static int isp_fabric_mbox_cmd(struct ispsoftc *, mbreg_t *);
        !           135: static int isp_scan_fabric(struct ispsoftc *, int);
        !           136: static void isp_register_fc4_type(struct ispsoftc *);
        !           137: static void isp_fw_state(struct ispsoftc *);
        !           138: static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int);
        !           139: static void isp_mboxcmd(struct ispsoftc *, mbreg_t *, int);
        !           140:
        !           141: static void isp_update(struct ispsoftc *);
        !           142: static void isp_update_bus(struct ispsoftc *, int);
        !           143: static void isp_setdfltparm(struct ispsoftc *, int);
        !           144: static int isp_read_nvram(struct ispsoftc *);
        !           145: static void isp_rdnvram_word(struct ispsoftc *, int, u_int16_t *);
        !           146: static void isp_parse_nvram_1020(struct ispsoftc *, u_int8_t *);
        !           147: static void isp_parse_nvram_1080(struct ispsoftc *, int, u_int8_t *);
        !           148: static void isp_parse_nvram_12160(struct ispsoftc *, int, u_int8_t *);
        !           149: static void isp_parse_nvram_2100(struct ispsoftc *, u_int8_t *);
        !           150:
        !           151: /*
        !           152:  * Reset Hardware.
        !           153:  *
        !           154:  * Hit the chip over the head, download new f/w if available and set it running.
        !           155:  *
        !           156:  * Locking done elsewhere.
        !           157:  */
        !           158:
        !           159: void
        !           160: isp_reset(struct ispsoftc *isp)
        !           161: {
        !           162:        mbreg_t mbs;
        !           163:        u_int16_t code_org;
        !           164:        int loops, i, dodnld = 1;
        !           165:        char *btype = "????";
        !           166:
        !           167:        isp->isp_state = ISP_NILSTATE;
        !           168:
        !           169:        /*
        !           170:         * Basic types (SCSI, FibreChannel and PCI or SBus)
        !           171:         * have been set in the MD code. We figure out more
        !           172:         * here. Possibly more refined types based upon PCI
        !           173:         * identification. Chip revision has been gathered.
        !           174:         *
        !           175:         * After we've fired this chip up, zero out the conf1 register
        !           176:         * for SCSI adapters and do other settings for the 2100.
        !           177:         */
        !           178:
        !           179:        /*
        !           180:         * Get the current running firmware revision out of the
        !           181:         * chip before we hit it over the head (if this is our
        !           182:         * first time through). Note that we store this as the
        !           183:         * 'ROM' firmware revision- which it may not be. In any
        !           184:         * case, we don't really use this yet, but we may in
        !           185:         * the future.
        !           186:         */
        !           187:        if (isp->isp_touched == 0) {
        !           188:                /*
        !           189:                 * First see whether or not we're sitting in the ISP PROM.
        !           190:                 * If we've just been reset, we'll have the string "ISP   "
        !           191:                 * spread through outgoing mailbox registers 1-3. We do
        !           192:                 * this for PCI cards because otherwise we really don't
        !           193:                 * know what state the card is in and we could hang if
        !           194:                 * we try this command otherwise.
        !           195:                 *
        !           196:                 * For SBus cards, we just do this because they almost
        !           197:                 * certainly will be running firmware by now.
        !           198:                 */
        !           199:                if (ISP_READ(isp, OUTMAILBOX1) != 0x4953 ||
        !           200:                    ISP_READ(isp, OUTMAILBOX2) != 0x5020 ||
        !           201:                    ISP_READ(isp, OUTMAILBOX3) != 0x2020) {
        !           202:                        /*
        !           203:                         * Just in case it was paused...
        !           204:                         */
        !           205:                        ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
        !           206:                        mbs.param[0] = MBOX_ABOUT_FIRMWARE;
        !           207:                        isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !           208:                        if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !           209:                                isp->isp_romfw_rev[0] = mbs.param[1];
        !           210:                                isp->isp_romfw_rev[1] = mbs.param[2];
        !           211:                                isp->isp_romfw_rev[2] = mbs.param[3];
        !           212:                        }
        !           213:                }
        !           214:                isp->isp_touched = 1;
        !           215:        }
        !           216:
        !           217:        DISABLE_INTS(isp);
        !           218:
        !           219:        /*
        !           220:         * Set up default request/response queue in-pointer/out-pointer
        !           221:         * register indices.
        !           222:         */
        !           223:        if (IS_23XX(isp)) {
        !           224:                isp->isp_rqstinrp = BIU_REQINP;
        !           225:                isp->isp_rqstoutrp = BIU_REQOUTP;
        !           226:                isp->isp_respinrp = BIU_RSPINP;
        !           227:                isp->isp_respoutrp = BIU_RSPOUTP;
        !           228:        } else {
        !           229:                isp->isp_rqstinrp = INMAILBOX4;
        !           230:                isp->isp_rqstoutrp = OUTMAILBOX4;
        !           231:                isp->isp_respinrp = OUTMAILBOX5;
        !           232:                isp->isp_respoutrp = INMAILBOX5;
        !           233:        }
        !           234:
        !           235:        /*
        !           236:         * Put the board into PAUSE mode (so we can read the SXP registers
        !           237:         * or write FPM/FBM registers).
        !           238:         */
        !           239:        ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
        !           240:
        !           241:        if (IS_FC(isp)) {
        !           242:                switch (isp->isp_type) {
        !           243:                case ISP_HA_FC_2100:
        !           244:                        btype = "2100";
        !           245:                        break;
        !           246:                case ISP_HA_FC_2200:
        !           247:                        btype = "2200";
        !           248:                        break;
        !           249:                case ISP_HA_FC_2300:
        !           250:                        btype = "2300";
        !           251:                        break;
        !           252:                case ISP_HA_FC_2312:
        !           253:                        btype = "2312";
        !           254:                        break;
        !           255:                default:
        !           256:                        break;
        !           257:                }
        !           258:                /*
        !           259:                 * While we're paused, reset the FPM module and FBM fifos.
        !           260:                 */
        !           261:                ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);
        !           262:                ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
        !           263:                ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
        !           264:                ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
        !           265:                ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
        !           266:        } else if (IS_1240(isp)) {
        !           267:                sdparam *sdp = isp->isp_param;
        !           268:                btype = "1240";
        !           269:                isp->isp_clock = 60;
        !           270:                sdp->isp_ultramode = 1;
        !           271:                sdp++;
        !           272:                sdp->isp_ultramode = 1;
        !           273:                /*
        !           274:                 * XXX: Should probably do some bus sensing.
        !           275:                 */
        !           276:        } else if (IS_ULTRA2(isp)) {
        !           277:                static const char m[] = "bus %d is in %s Mode";
        !           278:                u_int16_t l;
        !           279:                sdparam *sdp = isp->isp_param;
        !           280:
        !           281:                isp->isp_clock = 100;
        !           282:
        !           283:                if (IS_1280(isp))
        !           284:                        btype = "1280";
        !           285:                else if (IS_1080(isp))
        !           286:                        btype = "1080";
        !           287:                else if (IS_10160(isp))
        !           288:                        btype = "10160";
        !           289:                else if (IS_12160(isp))
        !           290:                        btype = "12160";
        !           291:                else
        !           292:                        btype = "<UNKLVD>";
        !           293:
        !           294:                l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK;
        !           295:                switch (l) {
        !           296:                case ISP1080_LVD_MODE:
        !           297:                        sdp->isp_lvdmode = 1;
        !           298:                        isp_prt(isp, ISP_LOGCONFIG, m, 0, "LVD");
        !           299:                        break;
        !           300:                case ISP1080_HVD_MODE:
        !           301:                        sdp->isp_diffmode = 1;
        !           302:                        isp_prt(isp, ISP_LOGCONFIG, m, 0, "Differential");
        !           303:                        break;
        !           304:                case ISP1080_SE_MODE:
        !           305:                        sdp->isp_ultramode = 1;
        !           306:                        isp_prt(isp, ISP_LOGCONFIG, m, 0, "Single-Ended");
        !           307:                        break;
        !           308:                default:
        !           309:                        isp_prt(isp, ISP_LOGERR,
        !           310:                            "unknown mode on bus %d (0x%x)", 0, l);
        !           311:                        break;
        !           312:                }
        !           313:
        !           314:                if (IS_DUALBUS(isp)) {
        !           315:                        sdp++;
        !           316:                        l = ISP_READ(isp, SXP_PINS_DIFF|SXP_BANK1_SELECT);
        !           317:                        l &= ISP1080_MODE_MASK;
        !           318:                        switch(l) {
        !           319:                        case ISP1080_LVD_MODE:
        !           320:                                sdp->isp_lvdmode = 1;
        !           321:                                isp_prt(isp, ISP_LOGCONFIG, m, 1, "LVD");
        !           322:                                break;
        !           323:                        case ISP1080_HVD_MODE:
        !           324:                                sdp->isp_diffmode = 1;
        !           325:                                isp_prt(isp, ISP_LOGCONFIG,
        !           326:                                    m, 1, "Differential");
        !           327:                                break;
        !           328:                        case ISP1080_SE_MODE:
        !           329:                                sdp->isp_ultramode = 1;
        !           330:                                isp_prt(isp, ISP_LOGCONFIG,
        !           331:                                    m, 1, "Single-Ended");
        !           332:                                break;
        !           333:                        default:
        !           334:                                isp_prt(isp, ISP_LOGERR,
        !           335:                                    "unknown mode on bus %d (0x%x)", 1, l);
        !           336:                                break;
        !           337:                        }
        !           338:                }
        !           339:        } else {
        !           340:                sdparam *sdp = isp->isp_param;
        !           341:                i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
        !           342:                switch (i) {
        !           343:                default:
        !           344:                        isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i);
        !           345:                        /* FALLTHROUGH */
        !           346:                case 1:
        !           347:                        btype = "1020";
        !           348:                        isp->isp_type = ISP_HA_SCSI_1020;
        !           349:                        isp->isp_clock = 40;
        !           350:                        break;
        !           351:                case 2:
        !           352:                        /*
        !           353:                         * Some 1020A chips are Ultra Capable, but don't
        !           354:                         * run the clock rate up for that unless told to
        !           355:                         * do so by the Ultra Capable bits being set.
        !           356:                         */
        !           357:                        btype = "1020A";
        !           358:                        isp->isp_type = ISP_HA_SCSI_1020A;
        !           359:                        isp->isp_clock = 40;
        !           360:                        break;
        !           361:                case 3:
        !           362:                        btype = "1040";
        !           363:                        isp->isp_type = ISP_HA_SCSI_1040;
        !           364:                        isp->isp_clock = 60;
        !           365:                        break;
        !           366:                case 4:
        !           367:                        btype = "1040A";
        !           368:                        isp->isp_type = ISP_HA_SCSI_1040A;
        !           369:                        isp->isp_clock = 60;
        !           370:                        break;
        !           371:                case 5:
        !           372:                        btype = "1040B";
        !           373:                        isp->isp_type = ISP_HA_SCSI_1040B;
        !           374:                        isp->isp_clock = 60;
        !           375:                        break;
        !           376:                case 6:
        !           377:                        btype = "1040C";
        !           378:                        isp->isp_type = ISP_HA_SCSI_1040C;
        !           379:                        isp->isp_clock = 60;
        !           380:                         break;
        !           381:                }
        !           382:                /*
        !           383:                 * Now, while we're at it, gather info about ultra
        !           384:                 * and/or differential mode.
        !           385:                 */
        !           386:                if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) {
        !           387:                        isp_prt(isp, ISP_LOGCONFIG, "Differential Mode");
        !           388:                        sdp->isp_diffmode = 1;
        !           389:                } else {
        !           390:                        sdp->isp_diffmode = 0;
        !           391:                }
        !           392:                i = ISP_READ(isp, RISC_PSR);
        !           393:                if (isp->isp_bustype == ISP_BT_SBUS) {
        !           394:                        i &= RISC_PSR_SBUS_ULTRA;
        !           395:                } else {
        !           396:                        i &= RISC_PSR_PCI_ULTRA;
        !           397:                }
        !           398:                if (i != 0) {
        !           399:                        isp_prt(isp, ISP_LOGCONFIG, "Ultra Mode Capable");
        !           400:                        sdp->isp_ultramode = 1;
        !           401:                        /*
        !           402:                         * If we're in Ultra Mode, we have to be 60MHz clock-
        !           403:                         * even for the SBus version.
        !           404:                         */
        !           405:                        isp->isp_clock = 60;
        !           406:                } else {
        !           407:                        sdp->isp_ultramode = 0;
        !           408:                        /*
        !           409:                         * Clock is known. Gronk.
        !           410:                         */
        !           411:                }
        !           412:
        !           413:                /*
        !           414:                 * Machine dependent clock (if set) overrides
        !           415:                 * our generic determinations.
        !           416:                 */
        !           417:                if (isp->isp_mdvec->dv_clock) {
        !           418:                        if (isp->isp_mdvec->dv_clock < isp->isp_clock) {
        !           419:                                isp->isp_clock = isp->isp_mdvec->dv_clock;
        !           420:                        }
        !           421:                }
        !           422:
        !           423:        }
        !           424:
        !           425:        /*
        !           426:         * Clear instrumentation
        !           427:         */
        !           428:        isp->isp_intcnt = isp->isp_intbogus = 0;
        !           429:
        !           430:        /*
        !           431:         * Do MD specific pre initialization
        !           432:         */
        !           433:        ISP_RESET0(isp);
        !           434:
        !           435: again:
        !           436:
        !           437:        /*
        !           438:         * Hit the chip over the head with hammer,
        !           439:         * and give the ISP a chance to recover.
        !           440:         */
        !           441:
        !           442:        if (IS_SCSI(isp)) {
        !           443:                ISP_WRITE(isp, BIU_ICR, BIU_ICR_SOFT_RESET);
        !           444:                /*
        !           445:                 * A slight delay...
        !           446:                 */
        !           447:                USEC_DELAY(100);
        !           448:
        !           449:                /*
        !           450:                 * Clear data && control DMA engines.
        !           451:                 */
        !           452:                ISP_WRITE(isp, CDMA_CONTROL,
        !           453:                    DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
        !           454:                ISP_WRITE(isp, DDMA_CONTROL,
        !           455:                    DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
        !           456:
        !           457:
        !           458:        } else {
        !           459:                ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
        !           460:                /*
        !           461:                 * A slight delay...
        !           462:                 */
        !           463:                USEC_DELAY(100);
        !           464:
        !           465:                /*
        !           466:                 * Clear data && control DMA engines.
        !           467:                 */
        !           468:                ISP_WRITE(isp, CDMA2100_CONTROL,
        !           469:                        DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
        !           470:                ISP_WRITE(isp, TDMA2100_CONTROL,
        !           471:                        DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
        !           472:                ISP_WRITE(isp, RDMA2100_CONTROL,
        !           473:                        DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
        !           474:        }
        !           475:
        !           476:        /*
        !           477:         * Wait for ISP to be ready to go...
        !           478:         */
        !           479:        loops = MBOX_DELAY_COUNT;
        !           480:        for (;;) {
        !           481:                if (IS_SCSI(isp)) {
        !           482:                        if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET))
        !           483:                                break;
        !           484:                } else {
        !           485:                        if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET))
        !           486:                                break;
        !           487:                }
        !           488:                USEC_DELAY(100);
        !           489:                if (--loops < 0) {
        !           490:                        ISP_DUMPREGS(isp, "chip reset timed out");
        !           491:                        return;
        !           492:                }
        !           493:        }
        !           494:
        !           495:        /*
        !           496:         * After we've fired this chip up, zero out the conf1 register
        !           497:         * for SCSI adapters and other settings for the 2100.
        !           498:         */
        !           499:
        !           500:        if (IS_SCSI(isp)) {
        !           501:                ISP_WRITE(isp, BIU_CONF1, 0);
        !           502:        } else {
        !           503:                ISP_WRITE(isp, BIU2100_CSR, 0);
        !           504:        }
        !           505:
        !           506:        /*
        !           507:         * Reset RISC Processor
        !           508:         */
        !           509:        ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
        !           510:        USEC_DELAY(100);
        !           511:        /* Clear semaphore register (just to be sure) */
        !           512:        ISP_WRITE(isp, BIU_SEMA, 0);
        !           513:
        !           514:        /*
        !           515:         * Establish some initial burst rate stuff.
        !           516:         * (only for the 1XX0 boards). This really should
        !           517:         * be done later after fetching from NVRAM.
        !           518:         */
        !           519:        if (IS_SCSI(isp)) {
        !           520:                u_int16_t tmp = isp->isp_mdvec->dv_conf1;
        !           521:                /*
        !           522:                 * Busted FIFO. Turn off all but burst enables.
        !           523:                 */
        !           524:                if (isp->isp_type == ISP_HA_SCSI_1040A) {
        !           525:                        tmp &= BIU_BURST_ENABLE;
        !           526:                }
        !           527:                ISP_SETBITS(isp, BIU_CONF1, tmp);
        !           528:                if (tmp & BIU_BURST_ENABLE) {
        !           529:                        ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
        !           530:                        ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
        !           531:                }
        !           532: #ifdef PTI_CARDS
        !           533:                if (((sdparam *) isp->isp_param)->isp_ultramode) {
        !           534:                        while (ISP_READ(isp, RISC_MTR) != 0x1313) {
        !           535:                                ISP_WRITE(isp, RISC_MTR, 0x1313);
        !           536:                                ISP_WRITE(isp, HCCR, HCCR_CMD_STEP);
        !           537:                        }
        !           538:                } else {
        !           539:                        ISP_WRITE(isp, RISC_MTR, 0x1212);
        !           540:                }
        !           541:                /*
        !           542:                 * PTI specific register
        !           543:                 */
        !           544:                ISP_WRITE(isp, RISC_EMB, DUAL_BANK)
        !           545: #else
        !           546:                ISP_WRITE(isp, RISC_MTR, 0x1212);
        !           547: #endif
        !           548:        } else {
        !           549:                ISP_WRITE(isp, RISC_MTR2100, 0x1212);
        !           550:                if (IS_2200(isp) || IS_23XX(isp)) {
        !           551:                        ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE);
        !           552:                }
        !           553:        }
        !           554:
        !           555:        ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */
        !           556:
        !           557:        /*
        !           558:         * Do MD specific post initialization
        !           559:         */
        !           560:        ISP_RESET1(isp);
        !           561:
        !           562:        /*
        !           563:         * Wait for everything to finish firing up.
        !           564:         *
        !           565:         * Avoid doing this on the 2312 because you can generate a PCI
        !           566:         * parity error (chip breakage).
        !           567:         */
        !           568:        if (IS_23XX(isp)) {
        !           569:                USEC_DELAY(5);
        !           570:        } else {
        !           571:                loops = MBOX_DELAY_COUNT;
        !           572:                while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
        !           573:                        USEC_DELAY(100);
        !           574:                        if (--loops < 0) {
        !           575:                                isp_prt(isp, ISP_LOGERR,
        !           576:                                    "MBOX_BUSY never cleared on reset");
        !           577:                                return;
        !           578:                        }
        !           579:                }
        !           580:        }
        !           581:
        !           582:        /*
        !           583:         * Up until this point we've done everything by just reading or
        !           584:         * setting registers. From this point on we rely on at least *some*
        !           585:         * kind of firmware running in the card.
        !           586:         */
        !           587:
        !           588:        /*
        !           589:         * Do some sanity checking.
        !           590:         */
        !           591:        mbs.param[0] = MBOX_NO_OP;
        !           592:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           593:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           594:                return;
        !           595:        }
        !           596:
        !           597:        if (IS_SCSI(isp)) {
        !           598:                mbs.param[0] = MBOX_MAILBOX_REG_TEST;
        !           599:                mbs.param[1] = 0xdead;
        !           600:                mbs.param[2] = 0xbeef;
        !           601:                mbs.param[3] = 0xffff;
        !           602:                mbs.param[4] = 0x1111;
        !           603:                mbs.param[5] = 0xa5a5;
        !           604:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           605:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           606:                        return;
        !           607:                }
        !           608:                if (mbs.param[1] != 0xdead || mbs.param[2] != 0xbeef ||
        !           609:                    mbs.param[3] != 0xffff || mbs.param[4] != 0x1111 ||
        !           610:                    mbs.param[5] != 0xa5a5) {
        !           611:                        isp_prt(isp, ISP_LOGERR,
        !           612:                            "Register Test Failed (0x%x 0x%x 0x%x 0x%x 0x%x)",
        !           613:                            mbs.param[1], mbs.param[2], mbs.param[3],
        !           614:                            mbs.param[4], mbs.param[5]);
        !           615:                        return;
        !           616:                }
        !           617:
        !           618:        }
        !           619:
        !           620:        /*
        !           621:         * Download new Firmware, unless requested not to do so.
        !           622:         * This is made slightly trickier in some cases where the
        !           623:         * firmware of the ROM revision is newer than the revision
        !           624:         * compiled into the driver. So, where we used to compare
        !           625:         * versions of our f/w and the ROM f/w, now we just see
        !           626:         * whether we have f/w at all and whether a config flag
        !           627:         * has disabled our download.
        !           628:         */
        !           629:        if ((isp->isp_mdvec->dv_ispfw == NULL) ||
        !           630:            (isp->isp_confopts & ISP_CFG_NORELOAD)) {
        !           631:                dodnld = 0;
        !           632:        }
        !           633:
        !           634:        if (IS_23XX(isp))
        !           635:                code_org = ISP_CODE_ORG_2300;
        !           636:        else
        !           637:                code_org = ISP_CODE_ORG;
        !           638:
        !           639:        if (dodnld) {
        !           640:                isp->isp_mbxworkp = (void *) &isp->isp_mdvec->dv_ispfw[1];
        !           641:                isp->isp_mbxwrk0 = isp->isp_mdvec->dv_ispfw[3] - 1;
        !           642:                isp->isp_mbxwrk1 = code_org + 1;
        !           643:                mbs.param[0] = MBOX_WRITE_RAM_WORD;
        !           644:                mbs.param[1] = code_org;
        !           645:                mbs.param[2] = isp->isp_mdvec->dv_ispfw[0];
        !           646:                isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !           647:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           648:                        isp_prt(isp, ISP_LOGERR,
        !           649:                            "F/W download failed at word %d",
        !           650:                            isp->isp_mbxwrk1 - code_org);
        !           651:                        dodnld = 0;
        !           652:                        goto again;
        !           653:                }
        !           654:                /*
        !           655:                 * Verify that it downloaded correctly.
        !           656:                 */
        !           657:                mbs.param[0] = MBOX_VERIFY_CHECKSUM;
        !           658:                mbs.param[1] = code_org;
        !           659:                isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !           660:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           661:                        isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure");
        !           662:                        return;
        !           663:                }
        !           664:                isp->isp_loaded_fw = 1;
        !           665:        } else {
        !           666:                isp->isp_loaded_fw = 0;
        !           667:                isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
        !           668:        }
        !           669:
        !           670:        /*
        !           671:         * Now start it rolling.
        !           672:         *
        !           673:         * If we didn't actually download f/w,
        !           674:         * we still need to (re)start it.
        !           675:         */
        !           676:
        !           677:
        !           678:        mbs.param[0] = MBOX_EXEC_FIRMWARE;
        !           679:        mbs.param[1] = code_org;
        !           680:        isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !           681:        /*
        !           682:         * Give it a chance to start.
        !           683:         */
        !           684:        USEC_DELAY(500);
        !           685:
        !           686:        if (IS_SCSI(isp)) {
        !           687:                /*
        !           688:                 * Set CLOCK RATE, but only if asked to.
        !           689:                 */
        !           690:                if (isp->isp_clock) {
        !           691:                        mbs.param[0] = MBOX_SET_CLOCK_RATE;
        !           692:                        mbs.param[1] = isp->isp_clock;
        !           693:                        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           694:                        /* we will try not to care if this fails */
        !           695:                }
        !           696:        }
        !           697:
        !           698:        mbs.param[0] = MBOX_ABOUT_FIRMWARE;
        !           699:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           700:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           701:                return;
        !           702:        }
        !           703:
        !           704:        /*
        !           705:         * The SBus firmware that we are using apparently does not return
        !           706:         * major, minor, micro revisions in the mailbox registers, which
        !           707:         * is really, really, annoying.
        !           708:         */
        !           709:        if (ISP_SBUS_SUPPORTED && isp->isp_bustype == ISP_BT_SBUS) {
        !           710:                if (dodnld) {
        !           711: #ifdef ISP_TARGET_MODE
        !           712:                        isp->isp_fwrev[0] = 7;
        !           713:                        isp->isp_fwrev[1] = 55;
        !           714: #else
        !           715:                        isp->isp_fwrev[0] = 1;
        !           716:                        isp->isp_fwrev[1] = 37;
        !           717: #endif
        !           718:                        isp->isp_fwrev[2] = 0;
        !           719:                }
        !           720:        } else {
        !           721:                isp->isp_fwrev[0] = mbs.param[1];
        !           722:                isp->isp_fwrev[1] = mbs.param[2];
        !           723:                isp->isp_fwrev[2] = mbs.param[3];
        !           724:        }
        !           725:        isp_prt(isp, ISP_LOGCONFIG,
        !           726:            "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
        !           727:            btype, isp->isp_revision, dodnld? "loaded" : "resident",
        !           728:            isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
        !           729:
        !           730:        if (IS_FC(isp)) {
        !           731:                /*
        !           732:                 * We do not believe firmware attributes for 2100 code less
        !           733:                 * than 1.17.0, unless it's the firmware we specifically
        !           734:                 * are loading.
        !           735:                 *
        !           736:                 * Note that all 22XX and 23XX f/w is greater than 1.X.0.
        !           737:                 */
        !           738:                if (!(ISP_FW_NEWER_THAN(isp, 1, 17, 0))) {
        !           739: #ifdef USE_SMALLER_2100_FIRMWARE
        !           740:                        FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN;
        !           741: #else
        !           742:                        FCPARAM(isp)->isp_fwattr = 0;
        !           743: #endif
        !           744:                } else {
        !           745:                        FCPARAM(isp)->isp_fwattr = mbs.param[6];
        !           746:                        isp_prt(isp, ISP_LOGDEBUG0,
        !           747:                            "Firmware Attributes = 0x%x", mbs.param[6]);
        !           748:                }
        !           749:                if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) {
        !           750:                        isp_prt(isp, ISP_LOGCONFIG,
        !           751:                            "Installed in 64-Bit PCI slot");
        !           752:                }
        !           753:        }
        !           754:
        !           755:        if (isp->isp_romfw_rev[0] || isp->isp_romfw_rev[1] ||
        !           756:            isp->isp_romfw_rev[2]) {
        !           757:                isp_prt(isp, ISP_LOGCONFIG, "Last F/W revision was %d.%d.%d",
        !           758:                    isp->isp_romfw_rev[0], isp->isp_romfw_rev[1],
        !           759:                    isp->isp_romfw_rev[2]);
        !           760:        }
        !           761:
        !           762:        mbs.param[0] = MBOX_GET_FIRMWARE_STATUS;
        !           763:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           764:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           765:                return;
        !           766:        }
        !           767:        isp->isp_maxcmds = mbs.param[2];
        !           768:        isp_prt(isp, ISP_LOGINFO,
        !           769:            "%d max I/O commands supported", mbs.param[2]);
        !           770:        isp_fw_state(isp);
        !           771:
        !           772:        /*
        !           773:         * Set up DMA for the request and result mailboxes.
        !           774:         */
        !           775:        if (ISP_MBOXDMASETUP(isp) != 0) {
        !           776:                isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
        !           777:                return;
        !           778:        }
        !           779:        isp->isp_state = ISP_RESETSTATE;
        !           780:
        !           781:        /*
        !           782:         * Okay- now that we have new firmware running, we now (re)set our
        !           783:         * notion of how many luns we support. This is somewhat tricky because
        !           784:         * if we haven't loaded firmware, we sometimes do not have an easy way
        !           785:         * of knowing how many luns we support.
        !           786:         *
        !           787:         * Expanded lun firmware gives you 32 luns for SCSI cards and
        !           788:         * 16384 luns for Fibre Channel cards.
        !           789:         *
        !           790:         * It turns out that even for QLogic 2100s with ROM 1.10 and above
        !           791:         * we do get a firmware attributes word returned in mailbox register 6.
        !           792:         *
        !           793:         * Because the lun is in a different position in the Request Queue
        !           794:         * Entry structure for Fibre Channel with expanded lun firmware, we
        !           795:         * can only support one lun (lun zero) when we don't know what kind
        !           796:         * of firmware we're running.
        !           797:         */
        !           798:        if (IS_SCSI(isp)) {
        !           799:                if (dodnld) {
        !           800:                        if (IS_ULTRA2(isp) || IS_ULTRA3(isp)) {
        !           801:                                isp->isp_maxluns = 32;
        !           802:                        } else {
        !           803:                                isp->isp_maxluns = 8;
        !           804:                        }
        !           805:                } else {
        !           806:                        isp->isp_maxluns = 8;
        !           807:                }
        !           808:        } else {
        !           809:                if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
        !           810:                        isp->isp_maxluns = 16384;
        !           811:                } else {
        !           812:                        isp->isp_maxluns = 16;
        !           813:                }
        !           814:        }
        !           815: }
        !           816:
        !           817: /*
        !           818:  * Initialize Parameters of Hardware to a known state.
        !           819:  *
        !           820:  * Locks are held before coming here.
        !           821:  */
        !           822:
        !           823: void
        !           824: isp_init(struct ispsoftc *isp)
        !           825: {
        !           826:        /*
        !           827:         * Must do this first to get defaults established.
        !           828:         */
        !           829:        isp_setdfltparm(isp, 0);
        !           830:        if (IS_DUALBUS(isp)) {
        !           831:                isp_setdfltparm(isp, 1);
        !           832:        }
        !           833:        if (IS_FC(isp)) {
        !           834:                isp_fibre_init(isp);
        !           835:        } else {
        !           836:                isp_scsi_init(isp);
        !           837:        }
        !           838: }
        !           839:
        !           840: static void
        !           841: isp_scsi_init(struct ispsoftc *isp)
        !           842: {
        !           843:        sdparam *sdp_chan0, *sdp_chan1;
        !           844:        mbreg_t mbs;
        !           845:
        !           846:        sdp_chan0 = isp->isp_param;
        !           847:        sdp_chan1 = sdp_chan0;
        !           848:        if (IS_DUALBUS(isp)) {
        !           849:                sdp_chan1++;
        !           850:        }
        !           851:
        !           852:        /*
        !           853:         * If we have no role (neither target nor initiator), return.
        !           854:         */
        !           855:        if (isp->isp_role == ISP_ROLE_NONE) {
        !           856:                return;
        !           857:        }
        !           858:
        !           859:        /* First do overall per-card settings. */
        !           860:
        !           861:        /*
        !           862:         * If we have fast memory timing enabled, turn it on.
        !           863:         */
        !           864:        if (sdp_chan0->isp_fast_mttr) {
        !           865:                ISP_WRITE(isp, RISC_MTR, 0x1313);
        !           866:        }
        !           867:
        !           868:        /*
        !           869:         * Set Retry Delay and Count.
        !           870:         * You set both channels at the same time.
        !           871:         */
        !           872:        mbs.param[0] = MBOX_SET_RETRY_COUNT;
        !           873:        mbs.param[1] = sdp_chan0->isp_retry_count;
        !           874:        mbs.param[2] = sdp_chan0->isp_retry_delay;
        !           875:        mbs.param[6] = sdp_chan1->isp_retry_count;
        !           876:        mbs.param[7] = sdp_chan1->isp_retry_delay;
        !           877:
        !           878:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           879:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           880:                return;
        !           881:        }
        !           882:
        !           883:        /*
        !           884:         * Set ASYNC DATA SETUP time. This is very important.
        !           885:         */
        !           886:        mbs.param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME;
        !           887:        mbs.param[1] = sdp_chan0->isp_async_data_setup;
        !           888:        mbs.param[2] = sdp_chan1->isp_async_data_setup;
        !           889:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           890:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           891:                return;
        !           892:        }
        !           893:
        !           894:        /*
        !           895:         * Set ACTIVE Negation State.
        !           896:         */
        !           897:        mbs.param[0] = MBOX_SET_ACT_NEG_STATE;
        !           898:        mbs.param[1] =
        !           899:            (sdp_chan0->isp_req_ack_active_neg << 4) |
        !           900:            (sdp_chan0->isp_data_line_active_neg << 5);
        !           901:        mbs.param[2] =
        !           902:            (sdp_chan1->isp_req_ack_active_neg << 4) |
        !           903:            (sdp_chan1->isp_data_line_active_neg << 5);
        !           904:
        !           905:        isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !           906:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           907:                isp_prt(isp, ISP_LOGERR,
        !           908:                    "failed to set active negation state (%d,%d), (%d,%d)",
        !           909:                    sdp_chan0->isp_req_ack_active_neg,
        !           910:                    sdp_chan0->isp_data_line_active_neg,
        !           911:                    sdp_chan1->isp_req_ack_active_neg,
        !           912:                    sdp_chan1->isp_data_line_active_neg);
        !           913:                /*
        !           914:                 * But don't return.
        !           915:                 */
        !           916:        }
        !           917:
        !           918:        /*
        !           919:         * Set the Tag Aging limit
        !           920:         */
        !           921:        mbs.param[0] = MBOX_SET_TAG_AGE_LIMIT;
        !           922:        mbs.param[1] = sdp_chan0->isp_tag_aging;
        !           923:        mbs.param[2] = sdp_chan1->isp_tag_aging;
        !           924:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           925:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           926:                isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)",
        !           927:                    sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging);
        !           928:                return;
        !           929:        }
        !           930:
        !           931:        /*
        !           932:         * Set selection timeout.
        !           933:         */
        !           934:        mbs.param[0] = MBOX_SET_SELECT_TIMEOUT;
        !           935:        mbs.param[1] = sdp_chan0->isp_selection_timeout;
        !           936:        mbs.param[2] = sdp_chan1->isp_selection_timeout;
        !           937:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           938:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           939:                return;
        !           940:        }
        !           941:
        !           942:        /* now do per-channel settings */
        !           943:        isp_scsi_channel_init(isp, 0);
        !           944:        if (IS_DUALBUS(isp))
        !           945:                isp_scsi_channel_init(isp, 1);
        !           946:
        !           947:        /*
        !           948:         * Now enable request/response queues
        !           949:         */
        !           950:
        !           951:        if (IS_ULTRA2(isp) || IS_1240(isp)) {
        !           952:                mbs.param[0] = MBOX_INIT_RES_QUEUE_A64;
        !           953:                mbs.param[1] = RESULT_QUEUE_LEN(isp);
        !           954:                mbs.param[2] = DMA_WD1(isp->isp_result_dma);
        !           955:                mbs.param[3] = DMA_WD0(isp->isp_result_dma);
        !           956:                mbs.param[4] = 0;
        !           957:                mbs.param[6] = DMA_WD3(isp->isp_result_dma);
        !           958:                mbs.param[7] = DMA_WD2(isp->isp_result_dma);
        !           959:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           960:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           961:                        return;
        !           962:                }
        !           963:                isp->isp_residx = mbs.param[5];
        !           964:
        !           965:                mbs.param[0] = MBOX_INIT_REQ_QUEUE_A64;
        !           966:                mbs.param[1] = RQUEST_QUEUE_LEN(isp);
        !           967:                mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
        !           968:                mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
        !           969:                mbs.param[5] = 0;
        !           970:                mbs.param[6] = DMA_WD3(isp->isp_result_dma);
        !           971:                mbs.param[7] = DMA_WD2(isp->isp_result_dma);
        !           972:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           973:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           974:                        return;
        !           975:                }
        !           976:                isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
        !           977:        } else {
        !           978:                mbs.param[0] = MBOX_INIT_RES_QUEUE;
        !           979:                mbs.param[1] = RESULT_QUEUE_LEN(isp);
        !           980:                mbs.param[2] = DMA_WD1(isp->isp_result_dma);
        !           981:                mbs.param[3] = DMA_WD0(isp->isp_result_dma);
        !           982:                mbs.param[4] = 0;
        !           983:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           984:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           985:                        return;
        !           986:                }
        !           987:                isp->isp_residx = mbs.param[5];
        !           988:
        !           989:                mbs.param[0] = MBOX_INIT_REQ_QUEUE;
        !           990:                mbs.param[1] = RQUEST_QUEUE_LEN(isp);
        !           991:                mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
        !           992:                mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
        !           993:                mbs.param[5] = 0;
        !           994:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !           995:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !           996:                        return;
        !           997:                }
        !           998:                isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
        !           999:        }
        !          1000:
        !          1001:        /*
        !          1002:         * Turn on Fast Posting, LVD transitions
        !          1003:         *
        !          1004:         * Ultra2 F/W always has had fast posting (and LVD transitions)
        !          1005:         *
        !          1006:         * Ultra and older (i.e., SBus) cards may not. It's just safer
        !          1007:         * to assume not for them.
        !          1008:         */
        !          1009:
        !          1010:        mbs.param[0] = MBOX_SET_FW_FEATURES;
        !          1011:        mbs.param[1] = 0;
        !          1012:        if (IS_ULTRA2(isp))
        !          1013:                mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;
        !          1014: #ifndef        ISP_NO_RIO
        !          1015:        if (IS_ULTRA2(isp) || IS_1240(isp))
        !          1016:                mbs.param[1] |= FW_FEATURE_RIO_16BIT;
        !          1017: #else
        !          1018: #ifndef        ISP_NO_FASTPOST
        !          1019:        if (IS_ULTRA2(isp) || IS_1240(isp))
        !          1020:                mbs.param[1] |= FW_FEATURE_FAST_POST;
        !          1021: #endif
        !          1022: #endif
        !          1023:        if (mbs.param[1] != 0) {
        !          1024:                u_int16_t sfeat = mbs.param[1];
        !          1025:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1026:                if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          1027:                        isp_prt(isp, ISP_LOGINFO,
        !          1028:                            "Enabled FW features (0x%x)", sfeat);
        !          1029:                }
        !          1030:        }
        !          1031:
        !          1032:        /*
        !          1033:         * Let the outer layers decide whether to issue a SCSI bus reset.
        !          1034:         */
        !          1035:        isp->isp_state = ISP_INITSTATE;
        !          1036: }
        !          1037:
        !          1038: static void
        !          1039: isp_scsi_channel_init(struct ispsoftc *isp, int channel)
        !          1040: {
        !          1041:        sdparam *sdp;
        !          1042:        mbreg_t mbs;
        !          1043:        int tgt;
        !          1044:
        !          1045:        sdp = isp->isp_param;
        !          1046:        sdp += channel;
        !          1047:
        !          1048:        /*
        !          1049:         * Set (possibly new) Initiator ID.
        !          1050:         */
        !          1051:        mbs.param[0] = MBOX_SET_INIT_SCSI_ID;
        !          1052:        mbs.param[1] = (channel << 7) | sdp->isp_initiator_id;
        !          1053:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1054:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          1055:                return;
        !          1056:        }
        !          1057:        isp_prt(isp, ISP_LOGINFO, "Initiator ID is %d on Channel %d",
        !          1058:            sdp->isp_initiator_id, channel);
        !          1059:
        !          1060:
        !          1061:        /*
        !          1062:         * Set current per-target parameters to an initial safe minimum.
        !          1063:         */
        !          1064:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          1065:                int lun;
        !          1066:                u_int16_t sdf;
        !          1067:
        !          1068:                if (sdp->isp_devparam[tgt].dev_enable == 0) {
        !          1069:                        continue;
        !          1070:                }
        !          1071: #ifndef        ISP_TARGET_MODE
        !          1072:                sdf = sdp->isp_devparam[tgt].goal_flags;
        !          1073:                sdf &= DPARM_SAFE_DFLT;
        !          1074:                /*
        !          1075:                 * It is not quite clear when this changed over so that
        !          1076:                 * we could force narrow and async for 1000/1020 cards,
        !          1077:                 * but assume that this is only the case for loaded
        !          1078:                 * firmware.
        !          1079:                 */
        !          1080:                if (isp->isp_loaded_fw) {
        !          1081:                        sdf |= DPARM_NARROW | DPARM_ASYNC;
        !          1082:                }
        !          1083: #else
        !          1084:                /*
        !          1085:                 * The !$*!)$!$)* f/w uses the same index into some
        !          1086:                 * internal table to decide how to respond to negotiations,
        !          1087:                 * so if we've said "let's be safe" for ID X, and ID X
        !          1088:                 * selects *us*, the negotiations will back to 'safe'
        !          1089:                 * (as in narrow/async). What the f/w *should* do is
        !          1090:                 * use the initiator id settings to decide how to respond.
        !          1091:                 */
        !          1092:                sdp->isp_devparam[tgt].goal_flags = sdf = DPARM_DEFAULT;
        !          1093: #endif
        !          1094:                mbs.param[0] = MBOX_SET_TARGET_PARAMS;
        !          1095:                mbs.param[1] = (channel << 15) | (tgt << 8);
        !          1096:                mbs.param[2] = sdf;
        !          1097:                if ((sdf & DPARM_SYNC) == 0) {
        !          1098:                        mbs.param[3] = 0;
        !          1099:                } else {
        !          1100:                        mbs.param[3] =
        !          1101:                            (sdp->isp_devparam[tgt].goal_offset << 8) |
        !          1102:                            (sdp->isp_devparam[tgt].goal_period);
        !          1103:                }
        !          1104:                isp_prt(isp, ISP_LOGDEBUG0,
        !          1105:                    "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x",
        !          1106:                    channel, tgt, mbs.param[2], mbs.param[3] >> 8,
        !          1107:                    mbs.param[3] & 0xff);
        !          1108:                isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !          1109:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          1110:                        sdf = DPARM_SAFE_DFLT;
        !          1111:                        mbs.param[0] = MBOX_SET_TARGET_PARAMS;
        !          1112:                        mbs.param[1] = (tgt << 8) | (channel << 15);
        !          1113:                        mbs.param[2] = sdf;
        !          1114:                        mbs.param[3] = 0;
        !          1115:                        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1116:                        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          1117:                                continue;
        !          1118:                        }
        !          1119:                }
        !          1120:
        !          1121:                /*
        !          1122:                 * We don't update any information directly from the f/w
        !          1123:                 * because we need to run at least one command to cause a
        !          1124:                 * new state to be latched up. So, we just assume that we
        !          1125:                 * converge to the values we just had set.
        !          1126:                 *
        !          1127:                 * Ensure that we don't believe tagged queuing is enabled yet.
        !          1128:                 * It turns out that sometimes the ISP just ignores our
        !          1129:                 * attempts to set parameters for devices that it hasn't
        !          1130:                 * seen yet.
        !          1131:                 */
        !          1132:                sdp->isp_devparam[tgt].actv_flags = sdf & ~DPARM_TQING;
        !          1133:                for (lun = 0; lun < (int) isp->isp_maxluns; lun++) {
        !          1134:                        mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
        !          1135:                        mbs.param[1] = (channel << 15) | (tgt << 8) | lun;
        !          1136:                        mbs.param[2] = sdp->isp_max_queue_depth;
        !          1137:                        mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle;
        !          1138:                        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1139:                        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          1140:                                break;
        !          1141:                        }
        !          1142:                }
        !          1143:        }
        !          1144:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          1145:                if (sdp->isp_devparam[tgt].dev_refresh) {
        !          1146:                        isp->isp_sendmarker |= (1 << channel);
        !          1147:                        isp->isp_update |= (1 << channel);
        !          1148:                        break;
        !          1149:                }
        !          1150:        }
        !          1151: }
        !          1152:
        !          1153: /*
        !          1154:  * Fibre Channel specific initialization.
        !          1155:  *
        !          1156:  * Locks are held before coming here.
        !          1157:  */
        !          1158: static void
        !          1159: isp_fibre_init(struct ispsoftc *isp)
        !          1160: {
        !          1161:        fcparam *fcp;
        !          1162:        isp_icb_t local, *icbp = &local;
        !          1163:        mbreg_t mbs;
        !          1164:        int loopid;
        !          1165:        u_int64_t nwwn, pwwn;
        !          1166:
        !          1167:        fcp = isp->isp_param;
        !          1168:
        !          1169:        /*
        !          1170:         * Do this *before* initializing the firmware.
        !          1171:         */
        !          1172:        isp_mark_getpdb_all(isp);
        !          1173:        fcp->isp_fwstate = FW_CONFIG_WAIT;
        !          1174:        fcp->isp_loopstate = LOOP_NIL;
        !          1175:
        !          1176:        /*
        !          1177:         * If we have no role (neither target nor initiator), return.
        !          1178:         */
        !          1179:        if (isp->isp_role == ISP_ROLE_NONE) {
        !          1180:                return;
        !          1181:        }
        !          1182:
        !          1183:        loopid = fcp->isp_loopid;
        !          1184:        MEMZERO(icbp, sizeof (*icbp));
        !          1185:        icbp->icb_version = ICB_VERSION1;
        !          1186:
        !          1187:        /*
        !          1188:         * Firmware Options are either retrieved from NVRAM or
        !          1189:         * are patched elsewhere. We check them for sanity here
        !          1190:         * and make changes based on board revision, but otherwise
        !          1191:         * let others decide policy.
        !          1192:         */
        !          1193:
        !          1194:        /*
        !          1195:         * If this is a 2100 < revision 5, we have to turn off FAIRNESS.
        !          1196:         */
        !          1197:        if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) {
        !          1198:                fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS;
        !          1199:        }
        !          1200:
        !          1201:        /*
        !          1202:         * We have to use FULL LOGIN even though it resets the loop too much
        !          1203:         * because otherwise port database entries don't get updated after
        !          1204:         * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0.
        !          1205:         */
        !          1206:        if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
        !          1207:                fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
        !          1208:        }
        !          1209:
        !          1210:        /*
        !          1211:         * Insist on Port Database Update Async notifications
        !          1212:         */
        !          1213:        fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
        !          1214:
        !          1215:        /*
        !          1216:         * Make sure that target role reflects into fwoptions.
        !          1217:         */
        !          1218:        if (isp->isp_role & ISP_ROLE_TARGET) {
        !          1219:                fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE;
        !          1220:        } else {
        !          1221:                fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE;
        !          1222:        }
        !          1223:
        !          1224:        /*
        !          1225:         * Propagate all of this into the ICB structure.
        !          1226:         */
        !          1227:        icbp->icb_fwoptions = fcp->isp_fwoptions;
        !          1228:        icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
        !          1229:        if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||
        !          1230:            icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
        !          1231:                isp_prt(isp, ISP_LOGERR,
        !          1232:                    "bad frame length (%d) from NVRAM- using %d",
        !          1233:                    fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN);
        !          1234:                icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
        !          1235:        }
        !          1236:        icbp->icb_maxalloc = fcp->isp_maxalloc;
        !          1237:        if (icbp->icb_maxalloc < 1) {
        !          1238:                isp_prt(isp, ISP_LOGERR,
        !          1239:                    "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc);
        !          1240:                icbp->icb_maxalloc = 16;
        !          1241:        }
        !          1242:        icbp->icb_execthrottle = fcp->isp_execthrottle;
        !          1243:        if (icbp->icb_execthrottle < 1) {
        !          1244:                isp_prt(isp, ISP_LOGERR,
        !          1245:                    "bad execution throttle of %d- using 16",
        !          1246:                    fcp->isp_execthrottle);
        !          1247:                icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
        !          1248:        }
        !          1249:        icbp->icb_retry_delay = fcp->isp_retry_delay;
        !          1250:        icbp->icb_retry_count = fcp->isp_retry_count;
        !          1251:        icbp->icb_hardaddr = loopid;
        !          1252:        /*
        !          1253:         * Right now we just set extended options to prefer point-to-point
        !          1254:         * over loop based upon some soft config options.
        !          1255:         *
        !          1256:         * NB: for the 2300, ICBOPT_EXTENDED is required.
        !          1257:         */
        !          1258:        if (IS_2200(isp) || IS_23XX(isp)) {
        !          1259:                icbp->icb_fwoptions |= ICBOPT_EXTENDED;
        !          1260:                /*
        !          1261:                 * Prefer or force Point-To-Point instead Loop?
        !          1262:                 */
        !          1263:                switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {
        !          1264:                case ISP_CFG_NPORT:
        !          1265:                        icbp->icb_xfwoptions |= ICBXOPT_PTP_2_LOOP;
        !          1266:                        break;
        !          1267:                case ISP_CFG_NPORT_ONLY:
        !          1268:                        icbp->icb_xfwoptions |= ICBXOPT_PTP_ONLY;
        !          1269:                        break;
        !          1270:                case ISP_CFG_LPORT_ONLY:
        !          1271:                        icbp->icb_xfwoptions |= ICBXOPT_LOOP_ONLY;
        !          1272:                        break;
        !          1273:                default:
        !          1274:                        icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP;
        !          1275:                        break;
        !          1276:                }
        !          1277:                if (IS_23XX(isp)) {
        !          1278:                        /*
        !          1279:                         * QLogic recommends that FAST Posting be turned
        !          1280:                         * off for 23XX cards and instead allow the HBA
        !          1281:                         * to write response queue entries and interrupt
        !          1282:                         * after a delay (ZIO).
        !          1283:                         *
        !          1284:                         * If we set ZIO, it will disable fast posting,
        !          1285:                         * so we don't need to clear it in fwoptions.
        !          1286:                         */
        !          1287:                        icbp->icb_xfwoptions |= ICBXOPT_ZIO;
        !          1288: #if    0
        !          1289:                        /*
        !          1290:                         * Values, in 100us increments. The default
        !          1291:                         * is 2 (200us) if a value 0 (default) is
        !          1292:                         * selected.
        !          1293:                         */
        !          1294:                        icbp->icb_idelaytimer = 2;
        !          1295: #endif
        !          1296:
        !          1297:                        if (isp->isp_confopts & ISP_CFG_ONEGB) {
        !          1298:                                icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB;
        !          1299:                        } else if (isp->isp_confopts & ISP_CFG_TWOGB) {
        !          1300:                                icbp->icb_zfwoptions |= ICBZOPT_RATE_TWOGB;
        !          1301:                        } else {
        !          1302:                                icbp->icb_zfwoptions |= ICBZOPT_RATE_AUTO;
        !          1303:                        }
        !          1304:                }
        !          1305:        }
        !          1306:
        !          1307: #ifndef        ISP_NO_RIO_FC
        !          1308:        /*
        !          1309:         * RIO seems to be enabled in 2100s for fw >= 1.17.0.
        !          1310:         *
        !          1311:         * I've had some questionable problems with RIO on 2200.
        !          1312:         * More specifically, on a 2204 I had problems with RIO
        !          1313:         * on a Linux system where I was dropping commands right
        !          1314:         * and left. It's not clear to me what the actual problem
        !          1315:         * was.
        !          1316:         *
        !          1317:         * 23XX Cards do not support RIO. Instead they support ZIO.
        !          1318:         */
        !          1319: #if    0
        !          1320:        if (!IS_23XX(isp) && ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
        !          1321:                icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
        !          1322:                icbp->icb_racctimer = 4;
        !          1323:                icbp->icb_idelaytimer = 8;
        !          1324:        }
        !          1325: #endif
        !          1326: #endif
        !          1327:
        !          1328:        /*
        !          1329:         * For 22XX > 2.1.26 && 23XX, set someoptions.
        !          1330:         * XXX: Probably okay for newer 2100 f/w too.
        !          1331:         */
        !          1332:        if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) {
        !          1333:                /*
        !          1334:                 * Turn on LIP F8 async event (1)
        !          1335:                 * Turn on generate AE 8013 on all LIP Resets (2)
        !          1336:                 * Disable LIP F7 switching (8)
        !          1337:                 */
        !          1338:                mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS;
        !          1339:                mbs.param[1] = 0xb;
        !          1340:                mbs.param[2] = 0;
        !          1341:                mbs.param[3] = 0;
        !          1342:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1343:        }
        !          1344:        icbp->icb_logintime = 30;       /* 30 second login timeout */
        !          1345:
        !          1346:        if (IS_23XX(isp)) {
        !          1347:                ISP_WRITE(isp, isp->isp_rqstinrp, 0);
        !          1348:                ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
        !          1349:                ISP_WRITE(isp, isp->isp_respinrp, 0);
        !          1350:                ISP_WRITE(isp, isp->isp_respoutrp, 0);
        !          1351:        }
        !          1352:
        !          1353:        nwwn = ISP_NODEWWN(isp);
        !          1354:        pwwn = ISP_PORTWWN(isp);
        !          1355:        if (nwwn && pwwn) {
        !          1356:                icbp->icb_fwoptions |= ICBOPT_BOTH_WWNS;
        !          1357:                MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn);
        !          1358:                MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
        !          1359:                isp_prt(isp, ISP_LOGDEBUG1,
        !          1360:                    "Setting ICB Node 0x%08x%08x Port 0x%08x%08x",
        !          1361:                    ((u_int32_t) (nwwn >> 32)),
        !          1362:                    ((u_int32_t) (nwwn & 0xffffffff)),
        !          1363:                    ((u_int32_t) (pwwn >> 32)),
        !          1364:                    ((u_int32_t) (pwwn & 0xffffffff)));
        !          1365:        } else {
        !          1366:                isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs");
        !          1367:                icbp->icb_fwoptions &= ~(ICBOPT_BOTH_WWNS|ICBOPT_FULL_LOGIN);
        !          1368:        }
        !          1369:        icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
        !          1370:        icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
        !          1371:        icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
        !          1372:        icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
        !          1373:        icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
        !          1374:        icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
        !          1375:        icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
        !          1376:        icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
        !          1377:        icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
        !          1378:        icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
        !          1379:        isp_prt(isp, ISP_LOGDEBUG0,
        !          1380:            "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x",
        !          1381:            icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions);
        !          1382:
        !          1383:        FC_SCRATCH_ACQUIRE(isp);
        !          1384:        isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch);
        !          1385:
        !          1386:        /*
        !          1387:         * Init the firmware
        !          1388:         */
        !          1389:        mbs.param[0] = MBOX_INIT_FIRMWARE;
        !          1390:        mbs.param[1] = 0;
        !          1391:        mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          1392:        mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          1393:        mbs.param[4] = 0;
        !          1394:        mbs.param[5] = 0;
        !          1395:        mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          1396:        mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          1397:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1398:        FC_SCRATCH_RELEASE(isp);
        !          1399:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          1400:                return;
        !          1401:        }
        !          1402:        isp->isp_reqidx = isp->isp_reqodx = 0;
        !          1403:        isp->isp_residx = 0;
        !          1404:        isp->isp_sendmarker = 1;
        !          1405:
        !          1406:        /*
        !          1407:         * Whatever happens, we're now committed to being here.
        !          1408:         */
        !          1409:        isp->isp_state = ISP_INITSTATE;
        !          1410: }
        !          1411:
        !          1412: /*
        !          1413:  * Fibre Channel Support- get the port database for the id.
        !          1414:  *
        !          1415:  * Locks are held before coming here. Return 0 if success,
        !          1416:  * else failure.
        !          1417:  */
        !          1418:
        !          1419: static int
        !          1420: isp_getmap(struct ispsoftc *isp, fcpos_map_t *map)
        !          1421: {
        !          1422:        fcparam *fcp = (fcparam *) isp->isp_param;
        !          1423:        mbreg_t mbs;
        !          1424:
        !          1425:        mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP;
        !          1426:        mbs.param[1] = 0;
        !          1427:        mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          1428:        mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          1429:        /*
        !          1430:         * Unneeded. For the 2100, except for initializing f/w, registers
        !          1431:         * 4/5 have to not be written to.
        !          1432:         *      mbs.param[4] = 0;
        !          1433:         *      mbs.param[5] = 0;
        !          1434:         *
        !          1435:         */
        !          1436:        mbs.param[6] = 0;
        !          1437:        mbs.param[7] = 0;
        !          1438:        FC_SCRATCH_ACQUIRE(isp);
        !          1439:        isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
        !          1440:        if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          1441:                MEMCPY(map, fcp->isp_scratch, sizeof (fcpos_map_t));
        !          1442:                map->fwmap = mbs.param[1] != 0;
        !          1443:                FC_SCRATCH_RELEASE(isp);
        !          1444:                return (0);
        !          1445:        }
        !          1446:        FC_SCRATCH_RELEASE(isp);
        !          1447:        return (-1);
        !          1448: }
        !          1449:
        !          1450: static void
        !          1451: isp_mark_getpdb_all(struct ispsoftc *isp)
        !          1452: {
        !          1453:        fcparam *fcp = (fcparam *) isp->isp_param;
        !          1454:        int i;
        !          1455:        for (i = 0; i < MAX_FC_TARG; i++) {
        !          1456:                fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0;
        !          1457:        }
        !          1458: }
        !          1459:
        !          1460: static int
        !          1461: isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp)
        !          1462: {
        !          1463:        fcparam *fcp = (fcparam *) isp->isp_param;
        !          1464:        mbreg_t mbs;
        !          1465:
        !          1466:        mbs.param[0] = MBOX_GET_PORT_DB;
        !          1467:        mbs.param[1] = id << 8;
        !          1468:        mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          1469:        mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          1470:        /*
        !          1471:         * Unneeded. For the 2100, except for initializing f/w, registers
        !          1472:         * 4/5 have to not be written to.
        !          1473:         *      mbs.param[4] = 0;
        !          1474:         *      mbs.param[5] = 0;
        !          1475:         *
        !          1476:         */
        !          1477:        mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          1478:        mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          1479:        FC_SCRATCH_ACQUIRE(isp);
        !          1480:        isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
        !          1481:        if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          1482:                isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp);
        !          1483:                FC_SCRATCH_RELEASE(isp);
        !          1484:                return (0);
        !          1485:        }
        !          1486:        FC_SCRATCH_RELEASE(isp);
        !          1487:        return (-1);
        !          1488: }
        !          1489:
        !          1490: static u_int64_t
        !          1491: isp_get_portname(struct ispsoftc *isp, int loopid, int nodename)
        !          1492: {
        !          1493:        u_int64_t wwn = 0;
        !          1494:        mbreg_t mbs;
        !          1495:
        !          1496:        mbs.param[0] = MBOX_GET_PORT_NAME;
        !          1497:        mbs.param[1] = loopid << 8;
        !          1498:        if (nodename)
        !          1499:                mbs.param[1] |= 1;
        !          1500:        isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
        !          1501:        if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          1502:                wwn =
        !          1503:                    (((u_int64_t)(mbs.param[2] & 0xff)) << 56) |
        !          1504:                    (((u_int64_t)(mbs.param[2] >> 8))   << 48) |
        !          1505:                    (((u_int64_t)(mbs.param[3] & 0xff)) << 40) |
        !          1506:                    (((u_int64_t)(mbs.param[3] >> 8))   << 32) |
        !          1507:                    (((u_int64_t)(mbs.param[6] & 0xff)) << 24) |
        !          1508:                    (((u_int64_t)(mbs.param[6] >> 8))   << 16) |
        !          1509:                    (((u_int64_t)(mbs.param[7] & 0xff)) <<  8) |
        !          1510:                    (((u_int64_t)(mbs.param[7] >> 8)));
        !          1511:        }
        !          1512:        return (wwn);
        !          1513: }
        !          1514:
        !          1515: /*
        !          1516:  * Make sure we have good FC link and know our Loop ID.
        !          1517:  */
        !          1518:
        !          1519: static int
        !          1520: isp_fclink_test(struct ispsoftc *isp, int usdelay)
        !          1521: {
        !          1522:        static char *toponames[] = {
        !          1523:                "Private Loop",
        !          1524:                "FL Port",
        !          1525:                "N-Port to N-Port",
        !          1526:                "F Port",
        !          1527:                "F Port (no FLOGI_ACC response)"
        !          1528:        };
        !          1529:        mbreg_t mbs;
        !          1530:        int count, check_for_fabric;
        !          1531:        u_int8_t lwfs;
        !          1532:        fcparam *fcp;
        !          1533:        struct lportdb *lp;
        !          1534:        isp_pdb_t pdb;
        !          1535:
        !          1536:        fcp = isp->isp_param;
        !          1537:
        !          1538:        /*
        !          1539:         * XXX: Here is where we would start a 'loop dead' timeout
        !          1540:         */
        !          1541:
        !          1542:        /*
        !          1543:         * Wait up to N microseconds for F/W to go to a ready state.
        !          1544:         */
        !          1545:        lwfs = FW_CONFIG_WAIT;
        !          1546:        count = 0;
        !          1547:        while (count < usdelay) {
        !          1548:                u_int64_t enano;
        !          1549:                u_int32_t wrk;
        !          1550:                NANOTIME_T hra, hrb;
        !          1551:
        !          1552:                GET_NANOTIME(&hra);
        !          1553:                isp_fw_state(isp);
        !          1554:                if (lwfs != fcp->isp_fwstate) {
        !          1555:                        isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>",
        !          1556:                            isp2100_fw_statename((int)lwfs),
        !          1557:                            isp2100_fw_statename((int)fcp->isp_fwstate));
        !          1558:                        lwfs = fcp->isp_fwstate;
        !          1559:                }
        !          1560:                if (fcp->isp_fwstate == FW_READY) {
        !          1561:                        break;
        !          1562:                }
        !          1563:                GET_NANOTIME(&hrb);
        !          1564:
        !          1565:                /*
        !          1566:                 * Get the elapsed time in nanoseconds.
        !          1567:                 * Always guaranteed to be non-zero.
        !          1568:                 */
        !          1569:                enano = NANOTIME_SUB(&hrb, &hra);
        !          1570:
        !          1571:                isp_prt(isp, ISP_LOGDEBUG1,
        !          1572:                    "usec%d: 0x%lx->0x%lx enano 0x%x%08x",
        !          1573:                    count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb),
        !          1574:                    (u_int32_t)(enano >> 32), (u_int32_t)(enano & 0xffffffff));
        !          1575:
        !          1576:                /*
        !          1577:                 * If the elapsed time is less than 1 millisecond,
        !          1578:                 * delay a period of time up to that millisecond of
        !          1579:                 * waiting.
        !          1580:                 *
        !          1581:                 * This peculiar code is an attempt to try and avoid
        !          1582:                 * invoking u_int64_t math support functions for some
        !          1583:                 * platforms where linkage is a problem.
        !          1584:                 */
        !          1585:                if (enano < (1000 * 1000)) {
        !          1586:                        count += 1000;
        !          1587:                        enano = (1000 * 1000) - enano;
        !          1588:                        while (enano > (u_int64_t) 4000000000U) {
        !          1589:                                USEC_SLEEP(isp, 4000000);
        !          1590:                                enano -= (u_int64_t) 4000000000U;
        !          1591:                        }
        !          1592:                        wrk = enano;
        !          1593:                        wrk /= 1000;
        !          1594:                        USEC_SLEEP(isp, wrk);
        !          1595:                } else {
        !          1596:                        while (enano > (u_int64_t) 4000000000U) {
        !          1597:                                count += 4000000;
        !          1598:                                enano -= (u_int64_t) 4000000000U;
        !          1599:                        }
        !          1600:                        wrk = enano;
        !          1601:                        count += (wrk / 1000);
        !          1602:                }
        !          1603:        }
        !          1604:
        !          1605:        /*
        !          1606:         * If we haven't gone to 'ready' state, return.
        !          1607:         */
        !          1608:        if (fcp->isp_fwstate != FW_READY) {
        !          1609:                return (-1);
        !          1610:        }
        !          1611:
        !          1612:        /*
        !          1613:         * Get our Loop ID (if possible). We really need to have it.
        !          1614:         */
        !          1615:        mbs.param[0] = MBOX_GET_LOOP_ID;
        !          1616:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1617:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          1618:                return (-1);
        !          1619:        }
        !          1620:        fcp->isp_loopid = mbs.param[1];
        !          1621:        if (IS_2200(isp) || IS_23XX(isp)) {
        !          1622:                int topo = (int) mbs.param[6];
        !          1623:                if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
        !          1624:                        topo = TOPO_PTP_STUB;
        !          1625:                fcp->isp_topo = topo;
        !          1626:        } else {
        !          1627:                fcp->isp_topo = TOPO_NL_PORT;
        !          1628:        }
        !          1629:        fcp->isp_portid = fcp->isp_alpa = mbs.param[2] & 0xff;
        !          1630:
        !          1631:        /*
        !          1632:         * Check to see if we're on a fabric by trying to see if we
        !          1633:         * can talk to the fabric name server. This can be a bit
        !          1634:         * tricky because if we're a 2100, we should check always
        !          1635:         * (in case we're connected to a server doing aliasing).
        !          1636:         */
        !          1637:        fcp->isp_onfabric = 0;
        !          1638:
        !          1639:        if (IS_2100(isp)) {
        !          1640:                /*
        !          1641:                 * Don't bother with fabric if we are using really old
        !          1642:                 * 2100 firmware. It's just not worth it.
        !          1643:                 */
        !          1644:                if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) {
        !          1645:                        check_for_fabric = 1;
        !          1646:                } else {
        !          1647:                        check_for_fabric = 0;
        !          1648:                }
        !          1649:        } else if (fcp->isp_topo == TOPO_FL_PORT ||
        !          1650:            fcp->isp_topo == TOPO_F_PORT) {
        !          1651:                check_for_fabric = 1;
        !          1652:        } else
        !          1653:                check_for_fabric = 0;
        !          1654:
        !          1655:        if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) {
        !          1656:                int loopid = FL_PORT_ID;
        !          1657:                if (IS_2100(isp)) {
        !          1658:                        fcp->isp_topo = TOPO_FL_PORT;
        !          1659:                }
        !          1660:
        !          1661:                if (BITS2WORD(pdb.pdb_portid_bits) == 0) {
        !          1662:                        /*
        !          1663:                         * Crock.
        !          1664:                         */
        !          1665:                        fcp->isp_topo = TOPO_NL_PORT;
        !          1666:                        goto not_on_fabric;
        !          1667:                }
        !          1668:                fcp->isp_portid = mbs.param[2] | ((int) mbs.param[3] << 16);
        !          1669:
        !          1670:                /*
        !          1671:                 * Save the Fabric controller's port database entry.
        !          1672:                 */
        !          1673:                lp = &fcp->portdb[loopid];
        !          1674:                lp->node_wwn =
        !          1675:                    (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
        !          1676:                    (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
        !          1677:                    (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
        !          1678:                    (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
        !          1679:                    (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
        !          1680:                    (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
        !          1681:                    (((u_int64_t)pdb.pdb_nodename[6]) <<  8) |
        !          1682:                    (((u_int64_t)pdb.pdb_nodename[7]));
        !          1683:                lp->port_wwn =
        !          1684:                    (((u_int64_t)pdb.pdb_portname[0]) << 56) |
        !          1685:                    (((u_int64_t)pdb.pdb_portname[1]) << 48) |
        !          1686:                    (((u_int64_t)pdb.pdb_portname[2]) << 40) |
        !          1687:                    (((u_int64_t)pdb.pdb_portname[3]) << 32) |
        !          1688:                    (((u_int64_t)pdb.pdb_portname[4]) << 24) |
        !          1689:                    (((u_int64_t)pdb.pdb_portname[5]) << 16) |
        !          1690:                    (((u_int64_t)pdb.pdb_portname[6]) <<  8) |
        !          1691:                    (((u_int64_t)pdb.pdb_portname[7]));
        !          1692:                lp->roles =
        !          1693:                    (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
        !          1694:                lp->portid = BITS2WORD(pdb.pdb_portid_bits);
        !          1695:                lp->loopid = pdb.pdb_loopid;
        !          1696:                lp->loggedin = lp->valid = 1;
        !          1697:                fcp->isp_onfabric = 1;
        !          1698:                (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
        !          1699:                isp_register_fc4_type(isp);
        !          1700:        } else {
        !          1701: not_on_fabric:
        !          1702:                fcp->isp_onfabric = 0;
        !          1703:                fcp->portdb[FL_PORT_ID].valid = 0;
        !          1704:        }
        !          1705:
        !          1706:        fcp->isp_gbspeed = 1;
        !          1707:        if (IS_23XX(isp)) {
        !          1708:                mbs.param[0] = MBOX_GET_SET_DATA_RATE;
        !          1709:                mbs.param[1] = MBGSD_GET_RATE;
        !          1710:                /* mbs.param[2] undefined if we're just getting rate */
        !          1711:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          1712:                if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          1713:                        if (mbs.param[1] == MBGSD_TWOGB) {
        !          1714:                                isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s");
        !          1715:                                fcp->isp_gbspeed = 2;
        !          1716:                        }
        !          1717:                }
        !          1718:        }
        !          1719:
        !          1720:        isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_alpa,
        !          1721:            fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]);
        !          1722:
        !          1723:        /*
        !          1724:         * Announce ourselves, too. This involves synthesizing an entry.
        !          1725:         */
        !          1726:        if (fcp->isp_iid_set == 0) {
        !          1727:                fcp->isp_iid_set = 1;
        !          1728:                fcp->isp_iid = fcp->isp_loopid;
        !          1729:                lp = &fcp->portdb[fcp->isp_iid];
        !          1730:        } else {
        !          1731:                lp = &fcp->portdb[fcp->isp_iid];
        !          1732:                if (fcp->isp_portid != lp->portid ||
        !          1733:                    fcp->isp_loopid != lp->loopid ||
        !          1734:                    fcp->isp_nodewwn != ISP_NODEWWN(isp) ||
        !          1735:                    fcp->isp_portwwn != ISP_PORTWWN(isp)) {
        !          1736:                        lp->valid = 0;
        !          1737:                        count = fcp->isp_iid;
        !          1738:                        (void) isp_async(isp, ISPASYNC_PROMENADE, &count);
        !          1739:                }
        !          1740:        }
        !          1741:        lp->loopid = fcp->isp_loopid;
        !          1742:        lp->portid = fcp->isp_portid;
        !          1743:        lp->node_wwn = ISP_NODEWWN(isp);
        !          1744:        lp->port_wwn = ISP_PORTWWN(isp);
        !          1745:        switch (isp->isp_role) {
        !          1746:        case ISP_ROLE_NONE:
        !          1747:                lp->roles = 0;
        !          1748:                break;
        !          1749:        case ISP_ROLE_TARGET:
        !          1750:                lp->roles = SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT;
        !          1751:                break;
        !          1752:        case ISP_ROLE_INITIATOR:
        !          1753:                lp->roles = SVC3_INI_ROLE >> SVC3_ROLE_SHIFT;
        !          1754:                break;
        !          1755:        case ISP_ROLE_BOTH:
        !          1756:                lp->roles = (SVC3_INI_ROLE|SVC3_TGT_ROLE) >> SVC3_ROLE_SHIFT;
        !          1757:                break;
        !          1758:        }
        !          1759:        lp->loggedin = lp->valid = 1;
        !          1760:        count = fcp->isp_iid;
        !          1761:        (void) isp_async(isp, ISPASYNC_PROMENADE, &count);
        !          1762:        return (0);
        !          1763: }
        !          1764:
        !          1765: static char *
        !          1766: isp2100_fw_statename(int state)
        !          1767: {
        !          1768:        switch(state) {
        !          1769:        case FW_CONFIG_WAIT:    return "Config Wait";
        !          1770:        case FW_WAIT_AL_PA:     return "Waiting for AL_PA";
        !          1771:        case FW_WAIT_LOGIN:     return "Wait Login";
        !          1772:        case FW_READY:          return "Ready";
        !          1773:        case FW_LOSS_OF_SYNC:   return "Loss Of Sync";
        !          1774:        case FW_ERROR:          return "Error";
        !          1775:        case FW_REINIT:         return "Re-Init";
        !          1776:        case FW_NON_PART:       return "Nonparticipating";
        !          1777:        default:                return "?????";
        !          1778:        }
        !          1779: }
        !          1780:
        !          1781: /*
        !          1782:  * Synchronize our soft copy of the port database with what the f/w thinks
        !          1783:  * (with a view toward possibly for a specific target....)
        !          1784:  */
        !          1785:
        !          1786: static int
        !          1787: isp_pdb_sync(struct ispsoftc *isp)
        !          1788: {
        !          1789:        struct lportdb *lp;
        !          1790:        fcparam *fcp = isp->isp_param;
        !          1791:        isp_pdb_t pdb;
        !          1792:        int loopid, base, lim;
        !          1793:
        !          1794:        /*
        !          1795:         * Make sure we're okay for doing this right now.
        !          1796:         */
        !          1797:        if (fcp->isp_loopstate != LOOP_PDB_RCVD &&
        !          1798:            fcp->isp_loopstate != LOOP_FSCAN_DONE &&
        !          1799:            fcp->isp_loopstate != LOOP_LSCAN_DONE) {
        !          1800:                return (-1);
        !          1801:        }
        !          1802:
        !          1803:        if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT ||
        !          1804:            fcp->isp_topo == TOPO_N_PORT) {
        !          1805:                if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
        !          1806:                        if (isp_scan_loop(isp) != 0) {
        !          1807:                                return (-1);
        !          1808:                        }
        !          1809:                }
        !          1810:        }
        !          1811:        fcp->isp_loopstate = LOOP_SYNCING_PDB;
        !          1812:
        !          1813:        /*
        !          1814:         * If we get this far, we've settled our differences with the f/w
        !          1815:         * (for local loop device) and we can say that the loop state is ready.
        !          1816:         */
        !          1817:
        !          1818:        if (fcp->isp_topo == TOPO_NL_PORT) {
        !          1819:                fcp->loop_seen_once = 1;
        !          1820:                fcp->isp_loopstate = LOOP_READY;
        !          1821:                return (0);
        !          1822:        }
        !          1823:
        !          1824:        /*
        !          1825:         * Find all Fabric Entities that didn't make it from one scan to the
        !          1826:         * next and let the world know they went away. Scan the whole database.
        !          1827:         */
        !          1828:        for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
        !          1829:                if (lp->was_fabric_dev && lp->fabric_dev == 0) {
        !          1830:                        loopid = lp - fcp->portdb;
        !          1831:                        lp->valid = 0;  /* should already be set */
        !          1832:                        (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
        !          1833:                        MEMZERO((void *) lp, sizeof (*lp));
        !          1834:                        continue;
        !          1835:                }
        !          1836:                lp->was_fabric_dev = lp->fabric_dev;
        !          1837:        }
        !          1838:
        !          1839:        if (fcp->isp_topo == TOPO_FL_PORT)
        !          1840:                base = FC_SNS_ID+1;
        !          1841:        else
        !          1842:                base = 0;
        !          1843:
        !          1844:        if (fcp->isp_topo == TOPO_N_PORT)
        !          1845:                lim = 1;
        !          1846:        else
        !          1847:                lim = MAX_FC_TARG;
        !          1848:
        !          1849:        /*
        !          1850:         * Now log in any fabric devices that the outer layer has
        !          1851:         * left for us to see. This seems the most sane policy
        !          1852:         * for the moment.
        !          1853:         */
        !          1854:        for (lp = &fcp->portdb[base]; lp < &fcp->portdb[lim]; lp++) {
        !          1855:                u_int32_t portid;
        !          1856:                mbreg_t mbs;
        !          1857:
        !          1858:                loopid = lp - fcp->portdb;
        !          1859:                if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) {
        !          1860:                        continue;
        !          1861:                }
        !          1862:
        !          1863:                /*
        !          1864:                 * Anything here?
        !          1865:                 */
        !          1866:                if (lp->port_wwn == 0) {
        !          1867:                        continue;
        !          1868:                }
        !          1869:
        !          1870:                /*
        !          1871:                 * Don't try to log into yourself.
        !          1872:                 */
        !          1873:                if ((portid = lp->portid) == fcp->isp_portid) {
        !          1874:                        continue;
        !          1875:                }
        !          1876:
        !          1877:
        !          1878:                /*
        !          1879:                 * If we'd been logged in- see if we still are and we haven't
        !          1880:                 * changed. If so, no need to log ourselves out, etc..
        !          1881:                 *
        !          1882:                 * Unfortunately, our charming Qlogic f/w has decided to
        !          1883:                 * return a valid port database entry for a fabric device
        !          1884:                 * that has, in fact, gone away. And it hangs trying to
        !          1885:                 * log it out.
        !          1886:                 */
        !          1887:                if (lp->loggedin && lp->force_logout == 0 &&
        !          1888:                    isp_getpdb(isp, lp->loopid, &pdb) == 0) {
        !          1889:                        int nrole;
        !          1890:                        u_int64_t nwwnn, nwwpn;
        !          1891:                        nwwnn =
        !          1892:                            (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
        !          1893:                            (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
        !          1894:                            (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
        !          1895:                            (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
        !          1896:                            (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
        !          1897:                            (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
        !          1898:                            (((u_int64_t)pdb.pdb_nodename[6]) <<  8) |
        !          1899:                            (((u_int64_t)pdb.pdb_nodename[7]));
        !          1900:                        nwwpn =
        !          1901:                            (((u_int64_t)pdb.pdb_portname[0]) << 56) |
        !          1902:                            (((u_int64_t)pdb.pdb_portname[1]) << 48) |
        !          1903:                            (((u_int64_t)pdb.pdb_portname[2]) << 40) |
        !          1904:                            (((u_int64_t)pdb.pdb_portname[3]) << 32) |
        !          1905:                            (((u_int64_t)pdb.pdb_portname[4]) << 24) |
        !          1906:                            (((u_int64_t)pdb.pdb_portname[5]) << 16) |
        !          1907:                            (((u_int64_t)pdb.pdb_portname[6]) <<  8) |
        !          1908:                            (((u_int64_t)pdb.pdb_portname[7]));
        !          1909:                        nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >>
        !          1910:                            SVC3_ROLE_SHIFT;
        !          1911:                        if (pdb.pdb_loopid == lp->loopid && lp->portid ==
        !          1912:                            (u_int32_t) BITS2WORD(pdb.pdb_portid_bits) &&
        !          1913:                            nwwnn == lp->node_wwn && nwwpn == lp->port_wwn &&
        !          1914:                            lp->roles == nrole && lp->force_logout == 0) {
        !          1915:                                lp->loggedin = lp->valid = 1;
        !          1916:                                isp_prt(isp, ISP_LOGCONFIG, lretained,
        !          1917:                                    (int) (lp - fcp->portdb),
        !          1918:                                    (int) lp->loopid, lp->portid);
        !          1919:                                continue;
        !          1920:                        }
        !          1921:                }
        !          1922:
        !          1923:                if (fcp->isp_fwstate != FW_READY ||
        !          1924:                    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
        !          1925:                        return (-1);
        !          1926:                }
        !          1927:
        !          1928:                /*
        !          1929:                 * Force a logout if we were logged in.
        !          1930:                 */
        !          1931:                if (lp->loggedin) {
        !          1932:                        if (lp->force_logout ||
        !          1933:                            isp_getpdb(isp, lp->loopid, &pdb) == 0) {
        !          1934:                                mbs.param[0] = MBOX_FABRIC_LOGOUT;
        !          1935:                                mbs.param[1] = lp->loopid << 8;
        !          1936:                                mbs.param[2] = 0;
        !          1937:                                mbs.param[3] = 0;
        !          1938:                                isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !          1939:                                isp_prt(isp, ISP_LOGINFO, plogout,
        !          1940:                                    (int) (lp - fcp->portdb), lp->loopid,
        !          1941:                                    lp->portid);
        !          1942:                        }
        !          1943:                        lp->force_logout = lp->loggedin = 0;
        !          1944:                        if (fcp->isp_fwstate != FW_READY ||
        !          1945:                            fcp->isp_loopstate != LOOP_SYNCING_PDB) {
        !          1946:                                return (-1);
        !          1947:                        }
        !          1948:                }
        !          1949:
        !          1950:                /*
        !          1951:                 * And log in....
        !          1952:                 */
        !          1953:                loopid = lp - fcp->portdb;
        !          1954:                lp->loopid = FL_PORT_ID;
        !          1955:                do {
        !          1956:                        mbs.param[0] = MBOX_FABRIC_LOGIN;
        !          1957:                        mbs.param[1] = loopid << 8;
        !          1958:                        mbs.param[2] = portid >> 16;
        !          1959:                        mbs.param[3] = portid & 0xffff;
        !          1960:                        isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED |
        !          1961:                            MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR));
        !          1962:                        if (fcp->isp_fwstate != FW_READY ||
        !          1963:                            fcp->isp_loopstate != LOOP_SYNCING_PDB) {
        !          1964:                                return (-1);
        !          1965:                        }
        !          1966:                        switch (mbs.param[0]) {
        !          1967:                        case MBOX_LOOP_ID_USED:
        !          1968:                                /*
        !          1969:                                 * Try the next available loop id.
        !          1970:                                 */
        !          1971:                                loopid++;
        !          1972:                                break;
        !          1973:                        case MBOX_PORT_ID_USED:
        !          1974:                                /*
        !          1975:                                 * This port is already logged in.
        !          1976:                                 * Snaffle the loop id it's using if it's
        !          1977:                                 * nonzero, otherwise we're hosed.
        !          1978:                                 */
        !          1979:                                if (mbs.param[1] != 0) {
        !          1980:                                        loopid = mbs.param[1];
        !          1981:                                        isp_prt(isp, ISP_LOGINFO, retained,
        !          1982:                                            loopid, (int) (lp - fcp->portdb),
        !          1983:                                            lp->portid);
        !          1984:                                } else {
        !          1985:                                        loopid = MAX_FC_TARG;
        !          1986:                                        break;
        !          1987:                                }
        !          1988:                                /* FALLTHROUGH */
        !          1989:                        case MBOX_COMMAND_COMPLETE:
        !          1990:                                lp->loggedin = 1;
        !          1991:                                lp->loopid = loopid;
        !          1992:                                break;
        !          1993:                        case MBOX_COMMAND_ERROR:
        !          1994:                                isp_prt(isp, ISP_LOGINFO, plogierr,
        !          1995:                                    portid, mbs.param[1]);
        !          1996:                                /* FALLTHROUGH */
        !          1997:                        case MBOX_ALL_IDS_USED: /* We're outta IDs */
        !          1998:                        default:
        !          1999:                                loopid = MAX_FC_TARG;
        !          2000:                                break;
        !          2001:                        }
        !          2002:                } while (lp->loopid == FL_PORT_ID && loopid < MAX_FC_TARG);
        !          2003:
        !          2004:                /*
        !          2005:                 * If we get here and we haven't set a Loop ID,
        !          2006:                 * we failed to log into this device.
        !          2007:                 */
        !          2008:
        !          2009:                if (lp->loopid == FL_PORT_ID) {
        !          2010:                        lp->loopid = 0;
        !          2011:                        continue;
        !          2012:                }
        !          2013:
        !          2014:                /*
        !          2015:                 * Make sure we can get the appropriate port information.
        !          2016:                 */
        !          2017:                if (isp_getpdb(isp, lp->loopid, &pdb) != 0) {
        !          2018:                        isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid);
        !          2019:                        goto dump_em;
        !          2020:                }
        !          2021:
        !          2022:                if (fcp->isp_fwstate != FW_READY ||
        !          2023:                    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
        !          2024:                        return (-1);
        !          2025:                }
        !          2026:
        !          2027:                if (pdb.pdb_loopid != lp->loopid) {
        !          2028:                        isp_prt(isp, ISP_LOGWARN, pdbmfail1,
        !          2029:                            lp->portid, pdb.pdb_loopid);
        !          2030:                        goto dump_em;
        !          2031:                }
        !          2032:
        !          2033:                if (lp->portid != (u_int32_t) BITS2WORD(pdb.pdb_portid_bits)) {
        !          2034:                        isp_prt(isp, ISP_LOGWARN, pdbmfail2,
        !          2035:                            lp->portid, BITS2WORD(pdb.pdb_portid_bits));
        !          2036:                        goto dump_em;
        !          2037:                }
        !          2038:
        !          2039:                lp->roles =
        !          2040:                    (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
        !          2041:                lp->node_wwn =
        !          2042:                    (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
        !          2043:                    (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
        !          2044:                    (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
        !          2045:                    (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
        !          2046:                    (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
        !          2047:                    (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
        !          2048:                    (((u_int64_t)pdb.pdb_nodename[6]) <<  8) |
        !          2049:                    (((u_int64_t)pdb.pdb_nodename[7]));
        !          2050:                lp->port_wwn =
        !          2051:                    (((u_int64_t)pdb.pdb_portname[0]) << 56) |
        !          2052:                    (((u_int64_t)pdb.pdb_portname[1]) << 48) |
        !          2053:                    (((u_int64_t)pdb.pdb_portname[2]) << 40) |
        !          2054:                    (((u_int64_t)pdb.pdb_portname[3]) << 32) |
        !          2055:                    (((u_int64_t)pdb.pdb_portname[4]) << 24) |
        !          2056:                    (((u_int64_t)pdb.pdb_portname[5]) << 16) |
        !          2057:                    (((u_int64_t)pdb.pdb_portname[6]) <<  8) |
        !          2058:                    (((u_int64_t)pdb.pdb_portname[7]));
        !          2059:                /*
        !          2060:                 * Check to make sure this all makes sense.
        !          2061:                 */
        !          2062:                if (lp->node_wwn && lp->port_wwn) {
        !          2063:                        lp->valid = 1;
        !          2064:                        loopid = lp - fcp->portdb;
        !          2065:                        (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
        !          2066:                        continue;
        !          2067:                }
        !          2068: dump_em:
        !          2069:                lp->valid = 0;
        !          2070:                isp_prt(isp, ISP_LOGINFO,
        !          2071:                    ldumped, loopid, lp->loopid, lp->portid);
        !          2072:                mbs.param[0] = MBOX_FABRIC_LOGOUT;
        !          2073:                mbs.param[1] = lp->loopid << 8;
        !          2074:                mbs.param[2] = 0;
        !          2075:                mbs.param[3] = 0;
        !          2076:                isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !          2077:                if (fcp->isp_fwstate != FW_READY ||
        !          2078:                    fcp->isp_loopstate != LOOP_SYNCING_PDB) {
        !          2079:                        return (-1);
        !          2080:                }
        !          2081:        }
        !          2082:        /*
        !          2083:         * If we get here, we've for sure seen not only a valid loop
        !          2084:         * but know what is or isn't on it, so mark this for usage
        !          2085:         * in isp_start.
        !          2086:         */
        !          2087:        fcp->loop_seen_once = 1;
        !          2088:        fcp->isp_loopstate = LOOP_READY;
        !          2089:        return (0);
        !          2090: }
        !          2091:
        !          2092: static int
        !          2093: isp_scan_loop(struct ispsoftc *isp)
        !          2094: {
        !          2095:        struct lportdb *lp;
        !          2096:        fcparam *fcp = isp->isp_param;
        !          2097:        isp_pdb_t pdb;
        !          2098:        int loopid, lim, hival;
        !          2099:
        !          2100:        switch (fcp->isp_topo) {
        !          2101:        case TOPO_NL_PORT:
        !          2102:                hival = FL_PORT_ID;
        !          2103:                break;
        !          2104:        case TOPO_N_PORT:
        !          2105:                hival = 2;
        !          2106:                break;
        !          2107:        case TOPO_FL_PORT:
        !          2108:                hival = FC_PORT_ID;
        !          2109:                break;
        !          2110:        default:
        !          2111:                fcp->isp_loopstate = LOOP_LSCAN_DONE;
        !          2112:                return (0);
        !          2113:        }
        !          2114:        fcp->isp_loopstate = LOOP_SCANNING_LOOP;
        !          2115:
        !          2116:        /*
        !          2117:         * make sure the temp port database is clean...
        !          2118:         */
        !          2119:        MEMZERO((void *)fcp->tport, sizeof (fcp->tport));
        !          2120:
        !          2121:        /*
        !          2122:         * Run through the local loop ports and get port database info
        !          2123:         * for each loop ID.
        !          2124:         *
        !          2125:         * There's a somewhat unexplained situation where the f/w passes back
        !          2126:         * the wrong database entity- if that happens, just restart (up to
        !          2127:         * FL_PORT_ID times).
        !          2128:         */
        !          2129:        for (lim = loopid = 0; loopid < hival; loopid++) {
        !          2130:                lp = &fcp->tport[loopid];
        !          2131:
        !          2132:                /*
        !          2133:                 * Don't even try for ourselves...
        !          2134:                 */
        !          2135:                if (loopid == fcp->isp_loopid)
        !          2136:                        continue;
        !          2137:
        !          2138:                lp->node_wwn = isp_get_portname(isp, loopid, 1);
        !          2139:                if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
        !          2140:                        return (-1);
        !          2141:                if (lp->node_wwn == 0)
        !          2142:                        continue;
        !          2143:                lp->port_wwn = isp_get_portname(isp, loopid, 0);
        !          2144:                if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
        !          2145:                        return (-1);
        !          2146:                if (lp->port_wwn == 0) {
        !          2147:                        lp->node_wwn = 0;
        !          2148:                        continue;
        !          2149:                }
        !          2150:
        !          2151:                /*
        !          2152:                 * Get an entry....
        !          2153:                 */
        !          2154:                if (isp_getpdb(isp, loopid, &pdb) != 0) {
        !          2155:                        if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
        !          2156:                                return (-1);
        !          2157:                        continue;
        !          2158:                }
        !          2159:                if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
        !          2160:                        return (-1);
        !          2161:                }
        !          2162:
        !          2163:                /*
        !          2164:                 * If the returned database element doesn't match what we
        !          2165:                 * asked for, restart the process entirely (up to a point...).
        !          2166:                 */
        !          2167:                if (pdb.pdb_loopid != loopid) {
        !          2168:                        loopid = 0;
        !          2169:                        if (lim++ < hival) {
        !          2170:                                continue;
        !          2171:                        }
        !          2172:                        isp_prt(isp, ISP_LOGWARN,
        !          2173:                            "giving up on synchronizing the port database");
        !          2174:                        return (-1);
        !          2175:                }
        !          2176:
        !          2177:                /*
        !          2178:                 * Save the pertinent info locally.
        !          2179:                 */
        !          2180:                lp->node_wwn =
        !          2181:                    (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
        !          2182:                    (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
        !          2183:                    (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
        !          2184:                    (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
        !          2185:                    (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
        !          2186:                    (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
        !          2187:                    (((u_int64_t)pdb.pdb_nodename[6]) <<  8) |
        !          2188:                    (((u_int64_t)pdb.pdb_nodename[7]));
        !          2189:                lp->port_wwn =
        !          2190:                    (((u_int64_t)pdb.pdb_portname[0]) << 56) |
        !          2191:                    (((u_int64_t)pdb.pdb_portname[1]) << 48) |
        !          2192:                    (((u_int64_t)pdb.pdb_portname[2]) << 40) |
        !          2193:                    (((u_int64_t)pdb.pdb_portname[3]) << 32) |
        !          2194:                    (((u_int64_t)pdb.pdb_portname[4]) << 24) |
        !          2195:                    (((u_int64_t)pdb.pdb_portname[5]) << 16) |
        !          2196:                    (((u_int64_t)pdb.pdb_portname[6]) <<  8) |
        !          2197:                    (((u_int64_t)pdb.pdb_portname[7]));
        !          2198:                lp->roles =
        !          2199:                    (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
        !          2200:                lp->portid = BITS2WORD(pdb.pdb_portid_bits);
        !          2201:                lp->loopid = pdb.pdb_loopid;
        !          2202:        }
        !          2203:
        !          2204:        /*
        !          2205:         * Mark all of the permanent local loop database entries as invalid
        !          2206:         * (except our own entry).
        !          2207:         */
        !          2208:        for (loopid = 0; loopid < hival; loopid++) {
        !          2209:                if (loopid == fcp->isp_iid) {
        !          2210:                        fcp->portdb[loopid].valid = 1;
        !          2211:                        fcp->portdb[loopid].loopid = fcp->isp_loopid;
        !          2212:                        continue;
        !          2213:                }
        !          2214:                fcp->portdb[loopid].valid = 0;
        !          2215:        }
        !          2216:
        !          2217:        /*
        !          2218:         * Now merge our local copy of the port database into our saved copy.
        !          2219:         * Notify the outer layers of new devices arriving.
        !          2220:         */
        !          2221:        for (loopid = 0; loopid < hival; loopid++) {
        !          2222:                int i;
        !          2223:
        !          2224:                /*
        !          2225:                 * If we don't have a non-zero Port WWN, we're not here.
        !          2226:                 */
        !          2227:                if (fcp->tport[loopid].port_wwn == 0) {
        !          2228:                        continue;
        !          2229:                }
        !          2230:
        !          2231:                /*
        !          2232:                 * Skip ourselves.
        !          2233:                 */
        !          2234:                if (loopid == fcp->isp_iid) {
        !          2235:                        continue;
        !          2236:                }
        !          2237:
        !          2238:                /*
        !          2239:                 * For the purposes of deciding whether this is the
        !          2240:                 * 'same' device or not, we only search for an identical
        !          2241:                 * Port WWN. Node WWNs may or may not be the same as
        !          2242:                 * the Port WWN, and there may be multiple different
        !          2243:                 * Port WWNs with the same Node WWN. It would be chaos
        !          2244:                 * to have multiple identical Port WWNs, so we don't
        !          2245:                 * allow that.
        !          2246:                 */
        !          2247:
        !          2248:                for (i = 0; i < hival; i++) {
        !          2249:                        int j;
        !          2250:                        if (fcp->portdb[i].port_wwn == 0)
        !          2251:                                continue;
        !          2252:                        if (fcp->portdb[i].port_wwn !=
        !          2253:                            fcp->tport[loopid].port_wwn)
        !          2254:                                continue;
        !          2255:                        /*
        !          2256:                         * We found this WWN elsewhere- it's changed
        !          2257:                         * loopids then. We don't change its actual
        !          2258:                         * position in our cached port database- we
        !          2259:                         * just change the actual loop ID we'd use.
        !          2260:                         */
        !          2261:                        if (fcp->portdb[i].loopid != loopid) {
        !          2262:                                isp_prt(isp, ISP_LOGINFO, portshift, i,
        !          2263:                                    fcp->portdb[i].loopid,
        !          2264:                                    fcp->portdb[i].portid, loopid,
        !          2265:                                    fcp->tport[loopid].portid);
        !          2266:                        }
        !          2267:                        fcp->portdb[i].portid = fcp->tport[loopid].portid;
        !          2268:                        fcp->portdb[i].loopid = loopid;
        !          2269:                        fcp->portdb[i].valid = 1;
        !          2270:                        fcp->portdb[i].roles = fcp->tport[loopid].roles;
        !          2271:
        !          2272:                        /*
        !          2273:                         * Now make sure this Port WWN doesn't exist elsewhere
        !          2274:                         * in the port database.
        !          2275:                         */
        !          2276:                        for (j = i+1; j < hival; j++) {
        !          2277:                                if (fcp->portdb[i].port_wwn !=
        !          2278:                                    fcp->portdb[j].port_wwn) {
        !          2279:                                        continue;
        !          2280:                                }
        !          2281:                                isp_prt(isp, ISP_LOGWARN, portdup, j, i);
        !          2282:                                /*
        !          2283:                                 * Invalidate the 'old' *and* 'new' ones.
        !          2284:                                 * This is really harsh and not quite right,
        !          2285:                                 * but if this happens, we really don't know
        !          2286:                                 * who is what at this point.
        !          2287:                                 */
        !          2288:                                fcp->portdb[i].valid = 0;
        !          2289:                                fcp->portdb[j].valid = 0;
        !          2290:                        }
        !          2291:                        break;
        !          2292:                }
        !          2293:
        !          2294:                /*
        !          2295:                 * If we didn't traverse the entire port database,
        !          2296:                 * then we found (and remapped) an existing entry.
        !          2297:                 * No need to notify anyone- go for the next one.
        !          2298:                 */
        !          2299:                if (i < hival) {
        !          2300:                        isp_prt(isp, ISP_LOGINFO, retained,
        !          2301:                            fcp->portdb[i].loopid, i, fcp->portdb[i].portid);
        !          2302:                        continue;
        !          2303:                }
        !          2304:
        !          2305:                /*
        !          2306:                 * We've not found this Port WWN anywhere. It's a new entry.
        !          2307:                 * See if we can leave it where it is (with target == loopid).
        !          2308:                 */
        !          2309:                if (fcp->portdb[loopid].port_wwn != 0) {
        !          2310:                        for (lim = 0; lim < hival; lim++) {
        !          2311:                                if (fcp->portdb[lim].port_wwn == 0)
        !          2312:                                        break;
        !          2313:                        }
        !          2314:                        /* "Cannot Happen" */
        !          2315:                        if (lim == hival) {
        !          2316:                                isp_prt(isp, ISP_LOGWARN, "Remap Overflow");
        !          2317:                                continue;
        !          2318:                        }
        !          2319:                        i = lim;
        !          2320:                } else {
        !          2321:                        i = loopid;
        !          2322:                }
        !          2323:
        !          2324:                /*
        !          2325:                 * NB:  The actual loopid we use here is loopid- we may
        !          2326:                 *      in fact be at a completely different index (target).
        !          2327:                 */
        !          2328:                fcp->portdb[i].loopid = loopid;
        !          2329:                fcp->portdb[i].port_wwn = fcp->tport[loopid].port_wwn;
        !          2330:                fcp->portdb[i].node_wwn = fcp->tport[loopid].node_wwn;
        !          2331:                fcp->portdb[i].roles = fcp->tport[loopid].roles;
        !          2332:                fcp->portdb[i].portid = fcp->tport[loopid].portid;
        !          2333:                fcp->portdb[i].valid = 1;
        !          2334:
        !          2335:                /*
        !          2336:                 * Tell the outside world we've arrived.
        !          2337:                 */
        !          2338:                (void) isp_async(isp, ISPASYNC_PROMENADE, &i);
        !          2339:        }
        !          2340:
        !          2341:        /*
        !          2342:         * Now find all previously used targets that are now invalid and
        !          2343:         * notify the outer layers that they're gone.
        !          2344:         */
        !          2345:        for (lp = &fcp->portdb[0]; lp < &fcp->portdb[hival]; lp++) {
        !          2346:                if (lp->valid || lp->port_wwn == 0) {
        !          2347:                        continue;
        !          2348:                }
        !          2349:
        !          2350:                /*
        !          2351:                 * Tell the outside world we've gone
        !          2352:                 * away and erase our pdb entry.
        !          2353:                 *
        !          2354:                 */
        !          2355:                loopid = lp - fcp->portdb;
        !          2356:                (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid);
        !          2357:                MEMZERO((void *) lp, sizeof (*lp));
        !          2358:        }
        !          2359:        fcp->isp_loopstate = LOOP_LSCAN_DONE;
        !          2360:        return (0);
        !          2361: }
        !          2362:
        !          2363:
        !          2364: static int
        !          2365: isp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp)
        !          2366: {
        !          2367:        isp_mboxcmd(isp, mbp, MBLOGNONE);
        !          2368:        if (mbp->param[0] != MBOX_COMMAND_COMPLETE) {
        !          2369:                if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) {
        !          2370:                        FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
        !          2371:                }
        !          2372:                if (mbp->param[0] == MBOX_COMMAND_ERROR) {
        !          2373:                        char tbuf[16];
        !          2374:                        char *m;
        !          2375:                        switch (mbp->param[1]) {
        !          2376:                        case 1:
        !          2377:                                m = "No Loop";
        !          2378:                                break;
        !          2379:                        case 2:
        !          2380:                                m = "Failed to allocate IOCB buffer";
        !          2381:                                break;
        !          2382:                        case 3:
        !          2383:                                m = "Failed to allocate XCB buffer";
        !          2384:                                break;
        !          2385:                        case 4:
        !          2386:                                m = "timeout or transmit failed";
        !          2387:                                break;
        !          2388:                        case 5:
        !          2389:                                m = "no fabric loop";
        !          2390:                                break;
        !          2391:                        case 6:
        !          2392:                                m = "remote device not a target";
        !          2393:                                break;
        !          2394:                        default:
        !          2395:                                SNPRINTF(tbuf, sizeof tbuf, "%x",
        !          2396:                                    mbp->param[1]);
        !          2397:                                m = tbuf;
        !          2398:                                break;
        !          2399:                        }
        !          2400:                        isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
        !          2401:                }
        !          2402:                return (-1);
        !          2403:        }
        !          2404:
        !          2405:        if (FCPARAM(isp)->isp_fwstate != FW_READY ||
        !          2406:            FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) {
        !          2407:                return (-1);
        !          2408:        }
        !          2409:        return(0);
        !          2410: }
        !          2411:
        !          2412: #ifdef ISP_USE_GA_NXT
        !          2413: static int
        !          2414: isp_scan_fabric(struct ispsoftc *isp, int ftype)
        !          2415: {
        !          2416:        fcparam *fcp = isp->isp_param;
        !          2417:        u_int32_t portid, first_portid, last_portid;
        !          2418:        int hicap, last_port_same;
        !          2419:
        !          2420:        if (fcp->isp_onfabric == 0) {
        !          2421:                fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2422:                return (0);
        !          2423:        }
        !          2424:
        !          2425:        FC_SCRATCH_ACQUIRE(isp);
        !          2426:
        !          2427:        /*
        !          2428:         * Since Port IDs are 24 bits, we can check against having seen
        !          2429:         * anything yet with this value.
        !          2430:         */
        !          2431:        last_port_same = 0;
        !          2432:        last_portid = 0xffffffff;       /* not a port */
        !          2433:        first_portid = portid = fcp->isp_portid;
        !          2434:        fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
        !          2435:
        !          2436:        for (hicap = 0; hicap < GA_NXT_MAX; hicap++) {
        !          2437:                mbreg_t mbs;
        !          2438:                sns_screq_t *rq;
        !          2439:                sns_ga_nxt_rsp_t *rs0, *rs1;
        !          2440:                struct lportdb lcl;
        !          2441:                u_int8_t sc[SNS_GA_NXT_RESP_SIZE];
        !          2442:
        !          2443:                rq = (sns_screq_t *)sc;
        !          2444:                MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE);
        !          2445:                rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1;
        !          2446:                rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100);
        !          2447:                rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100);
        !          2448:                rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100);
        !          2449:                rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100);
        !          2450:                rq->snscb_sblen = 6;
        !          2451:                rq->snscb_data[0] = SNS_GA_NXT;
        !          2452:                rq->snscb_data[4] = portid & 0xffff;
        !          2453:                rq->snscb_data[5] = (portid >> 16) & 0xff;
        !          2454:                isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch);
        !          2455:                MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE);
        !          2456:                mbs.param[0] = MBOX_SEND_SNS;
        !          2457:                mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1;
        !          2458:                mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          2459:                mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          2460:                /*
        !          2461:                 * Leave 4 and 5 alone
        !          2462:                 */
        !          2463:                mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          2464:                mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          2465:                if (isp_fabric_mbox_cmd(isp, &mbs)) {
        !          2466:                        if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
        !          2467:                                fcp->isp_loopstate = LOOP_PDB_RCVD;
        !          2468:                        }
        !          2469:                        FC_SCRATCH_RELEASE(isp);
        !          2470:                        return (-1);
        !          2471:                }
        !          2472:                MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE);
        !          2473:                rs1 = (sns_ga_nxt_rsp_t *) sc;
        !          2474:                rs0 = (sns_ga_nxt_rsp_t *) ((u_int8_t *)fcp->isp_scratch+0x100);
        !          2475:                isp_get_ga_nxt_response(isp, rs0, rs1);
        !          2476:                if (rs1->snscb_cthdr.ct_response != FS_ACC) {
        !          2477:                        int level;
        !          2478:                        if (rs1->snscb_cthdr.ct_reason == 9 &&
        !          2479:                            rs1->snscb_cthdr.ct_explanation == 7)
        !          2480:                                level = ISP_LOGDEBUG0;
        !          2481:                        else
        !          2482:                                level = ISP_LOGWARN;
        !          2483:                        isp_prt(isp, level, swrej, "GA_NXT",
        !          2484:                            rs1->snscb_cthdr.ct_reason,
        !          2485:                            rs1->snscb_cthdr.ct_explanation, portid);
        !          2486:                        FC_SCRATCH_RELEASE(isp);
        !          2487:                        fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2488:                        return (0);
        !          2489:                }
        !          2490:                portid =
        !          2491:                    (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
        !          2492:                    (((u_int32_t) rs1->snscb_port_id[1]) << 8) |
        !          2493:                    (((u_int32_t) rs1->snscb_port_id[2]));
        !          2494:
        !          2495:                /*
        !          2496:                 * XXX: We should check to make sure that this entry
        !          2497:                 * XXX: supports the type(s) we are interested in.
        !          2498:                 */
        !          2499:                /*
        !          2500:                 * Okay, we now have information about a fabric object.
        !          2501:                 * If it is the type we're interested in, tell the outer layers
        !          2502:                 * about it. The outer layer needs to  know: Port ID, WWNN,
        !          2503:                 * WWPN, FC4 type, and port type.
        !          2504:                 *
        !          2505:                 * The lportdb structure is adequate for this.
        !          2506:                 */
        !          2507:                MEMZERO(&lcl, sizeof (lcl));
        !          2508:                lcl.port_type = rs1->snscb_port_type;
        !          2509:                lcl.fc4_type = ftype;
        !          2510:                lcl.portid = portid;
        !          2511:                lcl.node_wwn =
        !          2512:                    (((u_int64_t)rs1->snscb_nodename[0]) << 56) |
        !          2513:                    (((u_int64_t)rs1->snscb_nodename[1]) << 48) |
        !          2514:                    (((u_int64_t)rs1->snscb_nodename[2]) << 40) |
        !          2515:                    (((u_int64_t)rs1->snscb_nodename[3]) << 32) |
        !          2516:                    (((u_int64_t)rs1->snscb_nodename[4]) << 24) |
        !          2517:                    (((u_int64_t)rs1->snscb_nodename[5]) << 16) |
        !          2518:                    (((u_int64_t)rs1->snscb_nodename[6]) <<  8) |
        !          2519:                    (((u_int64_t)rs1->snscb_nodename[7]));
        !          2520:                lcl.port_wwn =
        !          2521:                    (((u_int64_t)rs1->snscb_portname[0]) << 56) |
        !          2522:                    (((u_int64_t)rs1->snscb_portname[1]) << 48) |
        !          2523:                    (((u_int64_t)rs1->snscb_portname[2]) << 40) |
        !          2524:                    (((u_int64_t)rs1->snscb_portname[3]) << 32) |
        !          2525:                    (((u_int64_t)rs1->snscb_portname[4]) << 24) |
        !          2526:                    (((u_int64_t)rs1->snscb_portname[5]) << 16) |
        !          2527:                    (((u_int64_t)rs1->snscb_portname[6]) <<  8) |
        !          2528:                    (((u_int64_t)rs1->snscb_portname[7]));
        !          2529:
        !          2530:                /*
        !          2531:                 * Does this fabric object support the type we want?
        !          2532:                 * If not, skip it.
        !          2533:                 */
        !          2534:                if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) {
        !          2535:                        if (first_portid == portid) {
        !          2536:                                lcl.last_fabric_dev = 1;
        !          2537:                        } else {
        !          2538:                                lcl.last_fabric_dev = 0;
        !          2539:                        }
        !          2540:                        (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
        !          2541:                } else {
        !          2542:                        isp_prt(isp, ISP_LOGDEBUG0,
        !          2543:                            "PortID 0x%x doesn't support FC4 type 0x%x",
        !          2544:                            portid, ftype);
        !          2545:                }
        !          2546:                if (first_portid == portid) {
        !          2547:                        fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2548:                        FC_SCRATCH_RELEASE(isp);
        !          2549:                        return (0);
        !          2550:                }
        !          2551:                if (portid == last_portid) {
        !          2552:                        if (last_port_same++ > 20) {
        !          2553:                                isp_prt(isp, ISP_LOGWARN,
        !          2554:                                    "tangled fabric database detected");
        !          2555:                                break;
        !          2556:                        }
        !          2557:                } else {
        !          2558:                        last_port_same = 0 ;
        !          2559:                        last_portid = portid;
        !          2560:                }
        !          2561:        }
        !          2562:        FC_SCRATCH_RELEASE(isp);
        !          2563:        if (hicap >= GA_NXT_MAX) {
        !          2564:                isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX);
        !          2565:        }
        !          2566:        fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2567:        return (0);
        !          2568: }
        !          2569: #else
        !          2570: #define        GIDLEN  ((ISP2100_SCRLEN >> 1) + 16)
        !          2571: #define        NGENT   ((GIDLEN - 16) >> 2)
        !          2572:
        !          2573: #define        IGPOFF  (ISP2100_SCRLEN - GIDLEN)
        !          2574: #define        GXOFF   (256)
        !          2575:
        !          2576: static int
        !          2577: isp_scan_fabric(struct ispsoftc *isp, int ftype)
        !          2578: {
        !          2579:        fcparam *fcp = FCPARAM(isp);
        !          2580:        mbreg_t mbs;
        !          2581:        int i;
        !          2582:        sns_gid_ft_req_t *rq;
        !          2583:        sns_gid_ft_rsp_t *rs0, *rs1;
        !          2584:
        !          2585:        if (fcp->isp_onfabric == 0) {
        !          2586:                fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2587:                return (0);
        !          2588:        }
        !          2589:
        !          2590:        FC_SCRATCH_ACQUIRE(isp);
        !          2591:        fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
        !          2592:
        !          2593:        rq = (sns_gid_ft_req_t *)fcp->tport;
        !          2594:        MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE);
        !          2595:        rq->snscb_rblen = GIDLEN >> 1;
        !          2596:        rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF);
        !          2597:        rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF);
        !          2598:        rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF);
        !          2599:        rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF);
        !          2600:        rq->snscb_sblen = 6;
        !          2601:        rq->snscb_cmd = SNS_GID_FT;
        !          2602:        rq->snscb_mword_div_2 = NGENT;
        !          2603:        rq->snscb_fc4_type = ftype;
        !          2604:        isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch);
        !          2605:        MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE);
        !          2606:        mbs.param[0] = MBOX_SEND_SNS;
        !          2607:        mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1;
        !          2608:        mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          2609:        mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          2610:
        !          2611:        /*
        !          2612:         * Leave 4 and 5 alone
        !          2613:         */
        !          2614:        mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          2615:        mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          2616:        if (isp_fabric_mbox_cmd(isp, &mbs)) {
        !          2617:                if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
        !          2618:                        fcp->isp_loopstate = LOOP_PDB_RCVD;
        !          2619:                }
        !          2620:                FC_SCRATCH_RELEASE(isp);
        !          2621:                return (-1);
        !          2622:        }
        !          2623:        if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2624:                FC_SCRATCH_RELEASE(isp);
        !          2625:                return (-1);
        !          2626:        }
        !          2627:        MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
        !          2628:        rs1 = (sns_gid_ft_rsp_t *) fcp->tport;
        !          2629:        rs0 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+IGPOFF);
        !          2630:        isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
        !          2631:        if (rs1->snscb_cthdr.ct_response != FS_ACC) {
        !          2632:                int level;
        !          2633:                if (rs1->snscb_cthdr.ct_reason == 9 &&
        !          2634:                    rs1->snscb_cthdr.ct_explanation == 7)
        !          2635:                        level = ISP_LOGDEBUG0;
        !          2636:                else
        !          2637:                        level = ISP_LOGWARN;
        !          2638:                isp_prt(isp, level, swrej, "GID_FT",
        !          2639:                    rs1->snscb_cthdr.ct_reason,
        !          2640:                    rs1->snscb_cthdr.ct_explanation, 0);
        !          2641:                FC_SCRATCH_RELEASE(isp);
        !          2642:                fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2643:                return (0);
        !          2644:        }
        !          2645:
        !          2646:        /*
        !          2647:         * Okay, we now have a list of Port IDs for this class of device.
        !          2648:         * Go through the list and for each one get the WWPN/WWNN for it
        !          2649:         * and tell the outer layers about it. The outer layer needs to
        !          2650:         * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type.
        !          2651:         *
        !          2652:         * The lportdb structure is adequate for this.
        !          2653:         */
        !          2654:        i = -1;
        !          2655:        do {
        !          2656:                sns_gxn_id_req_t grqbuf, *gq = &grqbuf;
        !          2657:                sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf;
        !          2658:                struct lportdb lcl;
        !          2659: #if    0
        !          2660:                sns_gff_id_rsp_t *fs0, ffsbuf, *fs1 = &ffsbuf;
        !          2661: #endif
        !          2662:
        !          2663:                i++;
        !          2664:                MEMZERO(&lcl, sizeof (lcl));
        !          2665:                lcl.fc4_type = ftype;
        !          2666:                lcl.portid =
        !          2667:                    (((u_int32_t) rs1->snscb_ports[i].portid[0]) << 16) |
        !          2668:                    (((u_int32_t) rs1->snscb_ports[i].portid[1]) << 8) |
        !          2669:                    (((u_int32_t) rs1->snscb_ports[i].portid[2]));
        !          2670:
        !          2671:                MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
        !          2672:                gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
        !          2673:                gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
        !          2674:                gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
        !          2675:                gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
        !          2676:                gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
        !          2677:                gq->snscb_sblen = 6;
        !          2678:                gq->snscb_cmd = SNS_GPN_ID;
        !          2679:                gq->snscb_portid = lcl.portid;
        !          2680:                isp_put_gxn_id_request(isp, gq,
        !          2681:                    (sns_gxn_id_req_t *) fcp->isp_scratch);
        !          2682:                MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
        !          2683:                mbs.param[0] = MBOX_SEND_SNS;
        !          2684:                mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
        !          2685:                mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          2686:                mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          2687:                /*
        !          2688:                 * Leave 4 and 5 alone
        !          2689:                 */
        !          2690:                mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          2691:                mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          2692:                if (isp_fabric_mbox_cmd(isp, &mbs)) {
        !          2693:                        if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
        !          2694:                                fcp->isp_loopstate = LOOP_PDB_RCVD;
        !          2695:                        }
        !          2696:                        FC_SCRATCH_RELEASE(isp);
        !          2697:                        return (-1);
        !          2698:                }
        !          2699:                if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2700:                        FC_SCRATCH_RELEASE(isp);
        !          2701:                        return (-1);
        !          2702:                }
        !          2703:                MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
        !          2704:                gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
        !          2705:                isp_get_gxn_id_response(isp, gs0, gs1);
        !          2706:                if (gs1->snscb_cthdr.ct_response != FS_ACC) {
        !          2707:                        isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID",
        !          2708:                            gs1->snscb_cthdr.ct_reason,
        !          2709:                            gs1->snscb_cthdr.ct_explanation, lcl.portid);
        !          2710:                        if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2711:                                FC_SCRATCH_RELEASE(isp);
        !          2712:                                return (-1);
        !          2713:                        }
        !          2714:                        continue;
        !          2715:                }
        !          2716:                lcl.port_wwn =
        !          2717:                    (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
        !          2718:                    (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
        !          2719:                    (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
        !          2720:                    (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
        !          2721:                    (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
        !          2722:                    (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
        !          2723:                    (((u_int64_t)gs1->snscb_wwn[6]) <<  8) |
        !          2724:                    (((u_int64_t)gs1->snscb_wwn[7]));
        !          2725:
        !          2726:                MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
        !          2727:                gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
        !          2728:                gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
        !          2729:                gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
        !          2730:                gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
        !          2731:                gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
        !          2732:                gq->snscb_sblen = 6;
        !          2733:                gq->snscb_cmd = SNS_GNN_ID;
        !          2734:                gq->snscb_portid = lcl.portid;
        !          2735:                isp_put_gxn_id_request(isp, gq,
        !          2736:                    (sns_gxn_id_req_t *) fcp->isp_scratch);
        !          2737:                MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
        !          2738:                mbs.param[0] = MBOX_SEND_SNS;
        !          2739:                mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
        !          2740:                mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          2741:                mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          2742:                /*
        !          2743:                 * Leave 4 and 5 alone
        !          2744:                 */
        !          2745:                mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          2746:                mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          2747:                if (isp_fabric_mbox_cmd(isp, &mbs)) {
        !          2748:                        if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
        !          2749:                                fcp->isp_loopstate = LOOP_PDB_RCVD;
        !          2750:                        }
        !          2751:                        FC_SCRATCH_RELEASE(isp);
        !          2752:                        return (-1);
        !          2753:                }
        !          2754:                if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2755:                        FC_SCRATCH_RELEASE(isp);
        !          2756:                        return (-1);
        !          2757:                }
        !          2758:                MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
        !          2759:                gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
        !          2760:                isp_get_gxn_id_response(isp, gs0, gs1);
        !          2761:                if (gs1->snscb_cthdr.ct_response != FS_ACC) {
        !          2762:                        isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID",
        !          2763:                            gs1->snscb_cthdr.ct_reason,
        !          2764:                            gs1->snscb_cthdr.ct_explanation, lcl.portid);
        !          2765:                        if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2766:                                FC_SCRATCH_RELEASE(isp);
        !          2767:                                return (-1);
        !          2768:                        }
        !          2769:                        continue;
        !          2770:                }
        !          2771:                lcl.node_wwn =
        !          2772:                    (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
        !          2773:                    (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
        !          2774:                    (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
        !          2775:                    (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
        !          2776:                    (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
        !          2777:                    (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
        !          2778:                    (((u_int64_t)gs1->snscb_wwn[6]) <<  8) |
        !          2779:                    (((u_int64_t)gs1->snscb_wwn[7]));
        !          2780:
        !          2781:                /*
        !          2782:                 * The QLogic f/w is bouncing this with a parameter error.
        !          2783:                 */
        !          2784: #if    0
        !          2785:                /*
        !          2786:                 * Try and get FC4 Features (FC-GS-3 only).
        !          2787:                 * We can use the sns_gxn_id_req_t for this request.
        !          2788:                 */
        !          2789:                MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
        !          2790:                gq->snscb_rblen = SNS_GFF_ID_RESP_SIZE >> 1;
        !          2791:                gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
        !          2792:                gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
        !          2793:                gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
        !          2794:                gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
        !          2795:                gq->snscb_sblen = 6;
        !          2796:                gq->snscb_cmd = SNS_GFF_ID;
        !          2797:                gq->snscb_portid = lcl.portid;
        !          2798:                isp_put_gxn_id_request(isp, gq,
        !          2799:                    (sns_gxn_id_req_t *) fcp->isp_scratch);
        !          2800:                MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
        !          2801:                mbs.param[0] = MBOX_SEND_SNS;
        !          2802:                mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
        !          2803:                mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          2804:                mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          2805:                /*
        !          2806:                 * Leave 4 and 5 alone
        !          2807:                 */
        !          2808:                mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          2809:                mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          2810:                if (isp_fabric_mbox_cmd(isp, &mbs)) {
        !          2811:                        if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
        !          2812:                                fcp->isp_loopstate = LOOP_PDB_RCVD;
        !          2813:                        }
        !          2814:                        FC_SCRATCH_RELEASE(isp);
        !          2815:                        return (-1);
        !          2816:                }
        !          2817:                if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2818:                        FC_SCRATCH_RELEASE(isp);
        !          2819:                        return (-1);
        !          2820:                }
        !          2821:                MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GFF_ID_RESP_SIZE);
        !          2822:                fs0 = (sns_gff_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
        !          2823:                isp_get_gff_id_response(isp, fs0, fs1);
        !          2824:                if (fs1->snscb_cthdr.ct_response != FS_ACC) {
        !          2825:                        isp_prt(isp, /* ISP_LOGDEBUG0 */ ISP_LOGWARN,
        !          2826:                            swrej, "GFF_ID",
        !          2827:                            fs1->snscb_cthdr.ct_reason,
        !          2828:                            fs1->snscb_cthdr.ct_explanation, lcl.portid);
        !          2829:                        if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
        !          2830:                                FC_SCRATCH_RELEASE(isp);
        !          2831:                                return (-1);
        !          2832:                        }
        !          2833:                } else {
        !          2834:                        int index = (ftype >> 3);
        !          2835:                        int bshft = (ftype & 0x7) * 4;
        !          2836:                        int fc4_fval =
        !          2837:                            (fs1->snscb_fc4_features[index] >> bshft) & 0xf;
        !          2838:                        if (fc4_fval & 0x1) {
        !          2839:                                lcl.roles |=
        !          2840:                                    (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT);
        !          2841:                        }
        !          2842:                        if (fc4_fval & 0x2) {
        !          2843:                                lcl.roles |=
        !          2844:                                    (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
        !          2845:                        }
        !          2846:                }
        !          2847: #endif
        !          2848:
        !          2849:                /*
        !          2850:                 * If we really want to know what kind of port type this is,
        !          2851:                 * we have to run another CT command. Otherwise, we'll leave
        !          2852:                 * it as undefined.
        !          2853:                 *
        !          2854:                lcl.port_type = 0;
        !          2855:                 */
        !          2856:                if (rs1->snscb_ports[i].control & 0x80) {
        !          2857:                        lcl.last_fabric_dev = 1;
        !          2858:                } else {
        !          2859:                        lcl.last_fabric_dev = 0;
        !          2860:                }
        !          2861:                (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
        !          2862:
        !          2863:        } while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1);
        !          2864:
        !          2865:        /*
        !          2866:         * If we're not at the last entry, our list isn't big enough.
        !          2867:         */
        !          2868:        if ((rs1->snscb_ports[i].control & 0x80) == 0) {
        !          2869:                isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area");
        !          2870:        }
        !          2871:
        !          2872:        FC_SCRATCH_RELEASE(isp);
        !          2873:        fcp->isp_loopstate = LOOP_FSCAN_DONE;
        !          2874:        return (0);
        !          2875: }
        !          2876: #endif
        !          2877:
        !          2878: static void
        !          2879: isp_register_fc4_type(struct ispsoftc *isp)
        !          2880: {
        !          2881:        fcparam *fcp = isp->isp_param;
        !          2882:        u_int8_t local[SNS_RFT_ID_REQ_SIZE];
        !          2883:        sns_screq_t *reqp = (sns_screq_t *) local;
        !          2884:        mbreg_t mbs;
        !          2885:
        !          2886:        MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
        !          2887:        reqp->snscb_rblen = SNS_RFT_ID_RESP_SIZE >> 1;
        !          2888:        reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
        !          2889:        reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
        !          2890:        reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100);
        !          2891:        reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100);
        !          2892:        reqp->snscb_sblen = 22;
        !          2893:        reqp->snscb_data[0] = SNS_RFT_ID;
        !          2894:        reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
        !          2895:        reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
        !          2896:        reqp->snscb_data[6] = (1 << FC4_SCSI);
        !          2897: #if    0
        !          2898:        reqp->snscb_data[6] |= (1 << FC4_IP);   /* ISO/IEC 8802-2 LLC/SNAP */
        !          2899: #endif
        !          2900:        FC_SCRATCH_ACQUIRE(isp);
        !          2901:        isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
        !          2902:        mbs.param[0] = MBOX_SEND_SNS;
        !          2903:        mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
        !          2904:        mbs.param[2] = DMA_WD1(fcp->isp_scdma);
        !          2905:        mbs.param[3] = DMA_WD0(fcp->isp_scdma);
        !          2906:        /*
        !          2907:         * Leave 4 and 5 alone
        !          2908:         */
        !          2909:        mbs.param[6] = DMA_WD3(fcp->isp_scdma);
        !          2910:        mbs.param[7] = DMA_WD2(fcp->isp_scdma);
        !          2911:        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          2912:        FC_SCRATCH_RELEASE(isp);
        !          2913:        if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          2914:                isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded");
        !          2915:        }
        !          2916: }
        !          2917:
        !          2918: /*
        !          2919:  * Start a command. Locking is assumed done in the caller.
        !          2920:  */
        !          2921:
        !          2922: int
        !          2923: isp_start(XS_T *xs)
        !          2924: {
        !          2925:        struct ispsoftc *isp;
        !          2926:        u_int16_t nxti, optr, handle;
        !          2927:        u_int8_t local[QENTRY_LEN];
        !          2928:        ispreq_t *reqp, *qep;
        !          2929:        int target, i;
        !          2930:
        !          2931:        XS_INITERR(xs);
        !          2932:        isp = XS_ISP(xs);
        !          2933:
        !          2934:        /*
        !          2935:         * Check to make sure we're supporting initiator role.
        !          2936:         */
        !          2937:        if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
        !          2938:                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          2939:                return (CMD_COMPLETE);
        !          2940:        }
        !          2941:
        !          2942:        /*
        !          2943:         * Now make sure we're running.
        !          2944:         */
        !          2945:
        !          2946:        if (isp->isp_state != ISP_RUNSTATE) {
        !          2947:                isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
        !          2948:                XS_SETERR(xs, HBA_BOTCH);
        !          2949:                return (CMD_COMPLETE);
        !          2950:        }
        !          2951:
        !          2952:        /*
        !          2953:         * Check command CDB length, etc.. We really are limited to 16 bytes
        !          2954:         * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
        !          2955:         * but probably only if we're running fairly new firmware (we'll
        !          2956:         * let the old f/w choke on an extended command queue entry).
        !          2957:         */
        !          2958:
        !          2959:        if (XS_CDBLEN(xs) > (IS_FC(isp)? 16 : 44) || XS_CDBLEN(xs) == 0) {
        !          2960:                isp_prt(isp, ISP_LOGERR,
        !          2961:                    "unsupported cdb length (%d, CDB[0]=0x%x)",
        !          2962:                    XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
        !          2963:                XS_SETERR(xs, HBA_BOTCH);
        !          2964:                return (CMD_COMPLETE);
        !          2965:        }
        !          2966:
        !          2967:        /*
        !          2968:         * Check to see whether we have good firmware state still or
        !          2969:         * need to refresh our port database for this target.
        !          2970:         */
        !          2971:        target = XS_TGT(xs);
        !          2972:        if (IS_FC(isp)) {
        !          2973:                fcparam *fcp = isp->isp_param;
        !          2974:                struct lportdb *lp;
        !          2975: #ifdef HANDLE_LOOPSTATE_IN_OUTER_LAYERS
        !          2976:                if (fcp->isp_fwstate != FW_READY ||
        !          2977:                    fcp->isp_loopstate != LOOP_READY) {
        !          2978:                        return (CMD_RQLATER);
        !          2979:                }
        !          2980:
        !          2981:                /*
        !          2982:                 * If we're not on a Fabric, we can't have a target
        !          2983:                 * above FL_PORT_ID-1.
        !          2984:                 *
        !          2985:                 * If we're on a fabric and *not* connected as an F-port,
        !          2986:                 * we can't have a target less than FC_SNS_ID+1. This
        !          2987:                 * keeps us from having to sort out the difference between
        !          2988:                 * local public loop devices and those which we might get
        !          2989:                 * from a switch's database.
        !          2990:                 */
        !          2991:                if (fcp->isp_onfabric == 0) {
        !          2992:                        if (target >= FL_PORT_ID) {
        !          2993:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          2994:                                return (CMD_COMPLETE);
        !          2995:                        }
        !          2996:                } else {
        !          2997:                        if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
        !          2998:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          2999:                                return (CMD_COMPLETE);
        !          3000:                        }
        !          3001:                        /*
        !          3002:                         * We used to exclude having local loop ports
        !          3003:                         * at the same time that we have fabric ports.
        !          3004:                         * That is, we used to exclude having ports
        !          3005:                         * at < FL_PORT_ID if we're FL-port.
        !          3006:                         *
        !          3007:                         * That's wrong. The only thing that could be
        !          3008:                         * dicey is if the switch you're connected to
        !          3009:                         * has these local loop ports appear on the
        !          3010:                         * fabric and we somehow attach them twice.
        !          3011:                         */
        !          3012:                }
        !          3013: #else
        !          3014:                /*
        !          3015:                 * Check for f/w being in ready state. If the f/w
        !          3016:                 * isn't in ready state, then we don't know our
        !          3017:                 * loop ID and the f/w hasn't completed logging
        !          3018:                 * into all targets on the loop. If this is the
        !          3019:                 * case, then bounce the command. We pretend this is
        !          3020:                 * a SELECTION TIMEOUT error if we've never gone to
        !          3021:                 * FW_READY state at all- in this case we may not
        !          3022:                 * be hooked to a loop at all and we shouldn't hang
        !          3023:                 * the machine for this. Otherwise, defer this command
        !          3024:                 * until later.
        !          3025:                 */
        !          3026:                if (fcp->isp_fwstate != FW_READY) {
        !          3027:                        /*
        !          3028:                         * Give ourselves at most a 250ms delay.
        !          3029:                         */
        !          3030:                        if (isp_fclink_test(isp, 250000)) {
        !          3031:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3032:                                if (fcp->loop_seen_once) {
        !          3033:                                        return (CMD_RQLATER);
        !          3034:                                } else {
        !          3035:                                        return (CMD_COMPLETE);
        !          3036:                                }
        !          3037:                        }
        !          3038:                }
        !          3039:
        !          3040:                /*
        !          3041:                 * If we're not on a Fabric, we can't have a target
        !          3042:                 * above FL_PORT_ID-1.
        !          3043:                 *
        !          3044:                 * If we're on a fabric and *not* connected as an F-port,
        !          3045:                 * we can't have a target less than FC_SNS_ID+1. This
        !          3046:                 * keeps us from having to sort out the difference between
        !          3047:                 * local public loop devices and those which we might get
        !          3048:                 * from a switch's database.
        !          3049:                 */
        !          3050:                if (fcp->isp_onfabric == 0) {
        !          3051:                        if (target >= FL_PORT_ID) {
        !          3052:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3053:                                return (CMD_COMPLETE);
        !          3054:                        }
        !          3055:                } else {
        !          3056:                        if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
        !          3057:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3058:                                return (CMD_COMPLETE);
        !          3059:                        }
        !          3060:                        if (fcp->isp_topo != TOPO_F_PORT &&
        !          3061:                            target < FL_PORT_ID) {
        !          3062:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3063:                                return (CMD_COMPLETE);
        !          3064:                        }
        !          3065:                }
        !          3066:
        !          3067:                /*
        !          3068:                 * If our loop state is such that we haven't yet received
        !          3069:                 * a "Port Database Changed" notification (after a LIP or
        !          3070:                 * a Loop Reset or firmware initialization), then defer
        !          3071:                 * sending commands for a little while, but only if we've
        !          3072:                 * seen a valid loop at one point (otherwise we can get
        !          3073:                 * stuck at initialization time).
        !          3074:                 */
        !          3075:                if (fcp->isp_loopstate < LOOP_PDB_RCVD) {
        !          3076:                        XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3077:                        if (fcp->loop_seen_once) {
        !          3078:                                return (CMD_RQLATER);
        !          3079:                        } else {
        !          3080:                                return (CMD_COMPLETE);
        !          3081:                        }
        !          3082:                }
        !          3083:
        !          3084:                /*
        !          3085:                 * If we're in the middle of loop or fabric scanning
        !          3086:                 * or merging the port databases, retry this command later.
        !          3087:                 */
        !          3088:                if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC ||
        !          3089:                    fcp->isp_loopstate == LOOP_SCANNING_LOOP ||
        !          3090:                    fcp->isp_loopstate == LOOP_SYNCING_PDB) {
        !          3091:                        return (CMD_RQLATER);
        !          3092:                }
        !          3093:
        !          3094:                /*
        !          3095:                 * If our loop state is now such that we've just now
        !          3096:                 * received a Port Database Change notification, then
        !          3097:                 * we have to go off and (re)scan the fabric. We back
        !          3098:                 * out and try again later if this doesn't work.
        !          3099:                 */
        !          3100:                if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) {
        !          3101:                        if (isp_scan_fabric(isp, FC4_SCSI)) {
        !          3102:                                return (CMD_RQLATER);
        !          3103:                        }
        !          3104:                        if (fcp->isp_fwstate != FW_READY ||
        !          3105:                            fcp->isp_loopstate < LOOP_FSCAN_DONE) {
        !          3106:                                return (CMD_RQLATER);
        !          3107:                        }
        !          3108:                }
        !          3109:
        !          3110:                /*
        !          3111:                 * If our loop state is now such that we've just now
        !          3112:                 * received a Port Database Change notification, then
        !          3113:                 * we have to go off and (re)synchronize our port
        !          3114:                 * database.
        !          3115:                 */
        !          3116:                if (fcp->isp_loopstate < LOOP_READY) {
        !          3117:                        if (isp_pdb_sync(isp)) {
        !          3118:                                return (CMD_RQLATER);
        !          3119:                        }
        !          3120:                        if (fcp->isp_fwstate != FW_READY ||
        !          3121:                            fcp->isp_loopstate != LOOP_READY) {
        !          3122:                                return (CMD_RQLATER);
        !          3123:                        }
        !          3124:                }
        !          3125:
        !          3126:                /*
        !          3127:                 * XXX: Here's were we would cancel any loop_dead flag
        !          3128:                 * XXX: also cancel in dead_loop timeout that's running
        !          3129:                 */
        !          3130: #endif
        !          3131:
        !          3132:                /*
        !          3133:                 * Now check whether we should even think about pursuing this.
        !          3134:                 */
        !          3135:                lp = &fcp->portdb[target];
        !          3136:                if (lp->valid == 0) {
        !          3137:                        XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3138:                        return (CMD_COMPLETE);
        !          3139:                }
        !          3140:                if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) {
        !          3141:                        isp_prt(isp, ISP_LOGDEBUG2,
        !          3142:                            "Target %d does not have target service", target);
        !          3143:                        XS_SETERR(xs, HBA_SELTIMEOUT);
        !          3144:                        return (CMD_COMPLETE);
        !          3145:                }
        !          3146:                /*
        !          3147:                 * Now turn target into what the actual Loop ID is.
        !          3148:                 */
        !          3149:                target = lp->loopid;
        !          3150:                xs->sc_link->node_wwn = lp->node_wwn;
        !          3151:                xs->sc_link->port_wwn = lp->port_wwn;
        !          3152:
        !          3153:        }
        !          3154:
        !          3155:        /*
        !          3156:         * Next check to see if any HBA or Device
        !          3157:         * parameters need to be updated.
        !          3158:         */
        !          3159:        if (isp->isp_update != 0) {
        !          3160:                isp_update(isp);
        !          3161:        }
        !          3162:
        !          3163:        if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) {
        !          3164:                isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow");
        !          3165:                XS_SETERR(xs, HBA_BOTCH);
        !          3166:                return (CMD_EAGAIN);
        !          3167:        }
        !          3168:
        !          3169:        /*
        !          3170:         * Now see if we need to synchronize the ISP with respect to anything.
        !          3171:         * We do dual duty here (cough) for synchronizing for busses other
        !          3172:         * than which we got here to send a command to.
        !          3173:         */
        !          3174:        reqp = (ispreq_t *) local;
        !          3175:        if (isp->isp_sendmarker) {
        !          3176:                u_int8_t n = (IS_DUALBUS(isp)? 2: 1);
        !          3177:                /*
        !          3178:                 * Check ports to send markers for...
        !          3179:                 */
        !          3180:                for (i = 0; i < n; i++) {
        !          3181:                        if ((isp->isp_sendmarker & (1 << i)) == 0) {
        !          3182:                                continue;
        !          3183:                        }
        !          3184:                        MEMZERO((void *) reqp, QENTRY_LEN);
        !          3185:                        reqp->req_header.rqs_entry_count = 1;
        !          3186:                        reqp->req_header.rqs_entry_type = RQSTYPE_MARKER;
        !          3187:                        reqp->req_modifier = SYNC_ALL;
        !          3188:                        reqp->req_target = i << 7;      /* insert bus number */
        !          3189:                        isp_put_request(isp, reqp, qep);
        !          3190:                        ISP_ADD_REQUEST(isp, nxti);
        !          3191:                        isp->isp_sendmarker &= ~(1 << i);
        !          3192:                        if (isp_getrqentry(isp, &nxti, &optr, (void *) &qep)) {
        !          3193:                                isp_prt(isp, ISP_LOGDEBUG0,
        !          3194:                                    "Request Queue Overflow+");
        !          3195:                                XS_SETERR(xs, HBA_BOTCH);
        !          3196:                                return (CMD_EAGAIN);
        !          3197:                        }
        !          3198:                }
        !          3199:        }
        !          3200:
        !          3201:        MEMZERO((void *)reqp, QENTRY_LEN);
        !          3202:        reqp->req_header.rqs_entry_count = 1;
        !          3203:        if (IS_FC(isp)) {
        !          3204:                reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
        !          3205:        } else {
        !          3206:                if (XS_CDBLEN(xs) > 12)
        !          3207:                        reqp->req_header.rqs_entry_type = RQSTYPE_CMDONLY;
        !          3208:                else
        !          3209:                        reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
        !          3210:        }
        !          3211:        /* reqp->req_header.rqs_flags = 0; */
        !          3212:        /* reqp->req_header.rqs_seqno = 0; */
        !          3213:        if (IS_FC(isp)) {
        !          3214:                /*
        !          3215:                 * See comment in isp_intr
        !          3216:                 */
        !          3217:                /* XS_RESID(xs) = 0; */
        !          3218:
        !          3219:                /*
        !          3220:                 * Fibre Channel always requires some kind of tag.
        !          3221:                 * The Qlogic drivers seem be happy not to use a tag,
        !          3222:                 * but this breaks for some devices (IBM drives).
        !          3223:                 */
        !          3224:                if (XS_TAG_P(xs)) {
        !          3225:                        ((ispreqt2_t *)reqp)->req_flags = XS_TAG_TYPE(xs);
        !          3226:                } else {
        !          3227:                        /*
        !          3228:                         * If we don't know what tag to use, use HEAD OF QUEUE
        !          3229:                         * for Request Sense or Simple.
        !          3230:                         */
        !          3231:                        if (XS_CDBP(xs)[0] == 0x3)      /* REQUEST SENSE */
        !          3232:                                ((ispreqt2_t *)reqp)->req_flags = REQFLAG_HTAG;
        !          3233:                        else
        !          3234:                                ((ispreqt2_t *)reqp)->req_flags = REQFLAG_STAG;
        !          3235:                }
        !          3236:        } else {
        !          3237:                sdparam *sdp = (sdparam *)isp->isp_param;
        !          3238:                sdp += XS_CHANNEL(xs);
        !          3239:                if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) &&
        !          3240:                    XS_TAG_P(xs)) {
        !          3241:                        reqp->req_flags = XS_TAG_TYPE(xs);
        !          3242:                }
        !          3243:        }
        !          3244:        reqp->req_target = target | (XS_CHANNEL(xs) << 7);
        !          3245:        if (IS_SCSI(isp)) {
        !          3246:                reqp->req_lun_trn = XS_LUN(xs);
        !          3247:                reqp->req_cdblen = XS_CDBLEN(xs);
        !          3248:        } else {
        !          3249:                if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)
        !          3250:                        ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs);
        !          3251:                else
        !          3252:                        ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs);
        !          3253:        }
        !          3254:        MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs));
        !          3255:
        !          3256:        reqp->req_time = XS_TIME(xs) / 1000;
        !          3257:        if (reqp->req_time == 0 && XS_TIME(xs)) {
        !          3258:                reqp->req_time = 1;
        !          3259:        }
        !          3260:
        !          3261:        if (isp_save_xs(isp, xs, &handle)) {
        !          3262:                isp_prt(isp, ISP_LOGDEBUG0, "out of xflist pointers");
        !          3263:                XS_SETERR(xs, HBA_BOTCH);
        !          3264:                return (CMD_EAGAIN);
        !          3265:        }
        !          3266:        reqp->req_handle = handle;
        !          3267:
        !          3268:        /*
        !          3269:         * Set up DMA and/or do any bus swizzling of the request entry
        !          3270:         * so that the Qlogic F/W understands what is being asked of it.
        !          3271:         */
        !          3272:        i = ISP_DMASETUP(isp, xs, reqp, &nxti, optr);
        !          3273:        if (i != CMD_QUEUED) {
        !          3274:                isp_destroy_handle(isp, handle);
        !          3275:                /*
        !          3276:                 * dmasetup sets actual error in packet, and
        !          3277:                 * return what we were given to return.
        !          3278:                 */
        !          3279:                return (i);
        !          3280:        }
        !          3281:        XS_SETERR(xs, HBA_NOERROR);
        !          3282:        isp_prt(isp, ISP_LOGDEBUG2,
        !          3283:            "START cmd for %d.%d.%d cmd 0x%x datalen %ld",
        !          3284:            XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0],
        !          3285:            (long) XS_XFRLEN(xs));
        !          3286:        ISP_ADD_REQUEST(isp, nxti);
        !          3287:        isp->isp_nactive++;
        !          3288:        return (CMD_QUEUED);
        !          3289: }
        !          3290:
        !          3291: /*
        !          3292:  * isp control
        !          3293:  * Locks (ints blocked) assumed held.
        !          3294:  */
        !          3295:
        !          3296: int
        !          3297: isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg)
        !          3298: {
        !          3299:        XS_T *xs;
        !          3300:        mbreg_t mbs;
        !          3301:        int bus, tgt;
        !          3302:        u_int16_t handle;
        !          3303:
        !          3304:        switch (ctl) {
        !          3305:        default:
        !          3306:                isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
        !          3307:                break;
        !          3308:
        !          3309:        case ISPCTL_RESET_BUS:
        !          3310:                /*
        !          3311:                 * Issue a bus reset.
        !          3312:                 */
        !          3313:                mbs.param[0] = MBOX_BUS_RESET;
        !          3314:                mbs.param[2] = 0;
        !          3315:                if (IS_SCSI(isp)) {
        !          3316:                        mbs.param[1] =
        !          3317:                            ((sdparam *) isp->isp_param)->isp_bus_reset_delay;
        !          3318:                        if (mbs.param[1] < 2)
        !          3319:                                mbs.param[1] = 2;
        !          3320:                        bus = *((int *) arg);
        !          3321:                        if (IS_DUALBUS(isp))
        !          3322:                                mbs.param[2] = bus;
        !          3323:                } else {
        !          3324:                        mbs.param[1] = 10;
        !          3325:                        bus = 0;
        !          3326:                }
        !          3327:                isp->isp_sendmarker |= (1 << bus);
        !          3328:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          3329:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          3330:                        break;
        !          3331:                }
        !          3332:                isp_prt(isp, ISP_LOGINFO,
        !          3333:                    "driver initiated bus reset of bus %d", bus);
        !          3334:                return (0);
        !          3335:
        !          3336:        case ISPCTL_RESET_DEV:
        !          3337:                tgt = (*((int *) arg)) & 0xffff;
        !          3338:                bus = (*((int *) arg)) >> 16;
        !          3339:                mbs.param[0] = MBOX_ABORT_TARGET;
        !          3340:                mbs.param[1] = (tgt << 8) | (bus << 15);
        !          3341:                mbs.param[2] = 3;       /* 'delay', in seconds */
        !          3342:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          3343:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          3344:                        break;
        !          3345:                }
        !          3346:                isp_prt(isp, ISP_LOGINFO,
        !          3347:                    "Target %d on Bus %d Reset Succeeded", tgt, bus);
        !          3348:                isp->isp_sendmarker |= (1 << bus);
        !          3349:                return (0);
        !          3350:
        !          3351:        case ISPCTL_ABORT_CMD:
        !          3352:                xs = (XS_T *) arg;
        !          3353:                tgt = XS_TGT(xs);
        !          3354:                handle = isp_find_handle(isp, xs);
        !          3355:                if (handle == 0) {
        !          3356:                        isp_prt(isp, ISP_LOGWARN,
        !          3357:                            "cannot find handle for command to abort");
        !          3358:                        break;
        !          3359:                }
        !          3360:                bus = XS_CHANNEL(xs);
        !          3361:                mbs.param[0] = MBOX_ABORT;
        !          3362:                if (IS_FC(isp)) {
        !          3363:                        if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)  {
        !          3364:                                mbs.param[1] = tgt << 8;
        !          3365:                                mbs.param[4] = 0;
        !          3366:                                mbs.param[5] = 0;
        !          3367:                                mbs.param[6] = XS_LUN(xs);
        !          3368:                        } else {
        !          3369:                                mbs.param[1] = tgt << 8 | XS_LUN(xs);
        !          3370:                        }
        !          3371:                } else {
        !          3372:                        mbs.param[1] =
        !          3373:                            (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs);
        !          3374:                }
        !          3375:                mbs.param[3] = 0;
        !          3376:                mbs.param[2] = handle;
        !          3377:                isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_ERROR);
        !          3378:                if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          3379:                        return (0);
        !          3380:                }
        !          3381:                /*
        !          3382:                 * XXX: Look for command in the REQUEST QUEUE. That is,
        !          3383:                 * XXX: It hasn't been picked up by firmware yet.
        !          3384:                 */
        !          3385:                break;
        !          3386:
        !          3387:        case ISPCTL_UPDATE_PARAMS:
        !          3388:
        !          3389:                isp_update(isp);
        !          3390:                return (0);
        !          3391:
        !          3392:        case ISPCTL_FCLINK_TEST:
        !          3393:
        !          3394:                if (IS_FC(isp)) {
        !          3395:                        int usdelay = (arg)? *((int *) arg) : 250000;
        !          3396:                        return (isp_fclink_test(isp, usdelay));
        !          3397:                }
        !          3398:                break;
        !          3399:
        !          3400:        case ISPCTL_SCAN_FABRIC:
        !          3401:
        !          3402:                if (IS_FC(isp)) {
        !          3403:                        int ftype = (arg)? *((int *) arg) : FC4_SCSI;
        !          3404:                        return (isp_scan_fabric(isp, ftype));
        !          3405:                }
        !          3406:                break;
        !          3407:
        !          3408:        case ISPCTL_SCAN_LOOP:
        !          3409:
        !          3410:                if (IS_FC(isp)) {
        !          3411:                        return (isp_scan_loop(isp));
        !          3412:                }
        !          3413:                break;
        !          3414:
        !          3415:        case ISPCTL_PDB_SYNC:
        !          3416:
        !          3417:                if (IS_FC(isp)) {
        !          3418:                        return (isp_pdb_sync(isp));
        !          3419:                }
        !          3420:                break;
        !          3421:
        !          3422:        case ISPCTL_SEND_LIP:
        !          3423:
        !          3424:                if (IS_FC(isp)) {
        !          3425:                        mbs.param[0] = MBOX_INIT_LIP;
        !          3426:                        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          3427:                        if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          3428:                                return (0);
        !          3429:                        }
        !          3430:                }
        !          3431:                break;
        !          3432:
        !          3433:        case ISPCTL_GET_POSMAP:
        !          3434:
        !          3435:                if (IS_FC(isp) && arg) {
        !          3436:                        return (isp_getmap(isp, arg));
        !          3437:                }
        !          3438:                break;
        !          3439:
        !          3440:        case ISPCTL_RUN_MBOXCMD:
        !          3441:
        !          3442:                isp_mboxcmd(isp, arg, MBLOGALL);
        !          3443:                return(0);
        !          3444:
        !          3445: #ifdef ISP_TARGET_MODE
        !          3446:        case ISPCTL_TOGGLE_TMODE:
        !          3447:        {
        !          3448:
        !          3449:                /*
        !          3450:                 * We don't check/set against role here- that's the
        !          3451:                 * responsibility for the outer layer to coordinate.
        !          3452:                 */
        !          3453:                if (IS_SCSI(isp)) {
        !          3454:                        int param = *(int *)arg;
        !          3455:                        mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
        !          3456:                        mbs.param[1] = param & 0xffff;
        !          3457:                        mbs.param[2] = param >> 16;
        !          3458:                        isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          3459:                        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          3460:                                break;
        !          3461:                        }
        !          3462:                }
        !          3463:                return (0);
        !          3464:        }
        !          3465: #endif
        !          3466:        }
        !          3467:        return (-1);
        !          3468: }
        !          3469:
        !          3470: /*
        !          3471:  * Interrupt Service Routine(s).
        !          3472:  *
        !          3473:  * External (OS) framework has done the appropriate locking,
        !          3474:  * and the locking will be held throughout this function.
        !          3475:  */
        !          3476:
        !          3477: /*
        !          3478:  * Limit our stack depth by sticking with the max likely number
        !          3479:  * of completions on a request queue at any one time.
        !          3480:  */
        !          3481: #ifndef        MAX_REQUESTQ_COMPLETIONS
        !          3482: #define        MAX_REQUESTQ_COMPLETIONS        64
        !          3483: #endif
        !          3484:
        !          3485: void
        !          3486: isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
        !          3487: {
        !          3488:        XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs;
        !          3489:        u_int16_t iptr, optr, junk;
        !          3490:        int i, nlooked = 0, ndone = 0;
        !          3491:
        !          3492: again:
        !          3493:        /*
        !          3494:         * Is this a mailbox related interrupt?
        !          3495:         * The mailbox semaphore will be nonzero if so.
        !          3496:         */
        !          3497:        if (sema) {
        !          3498:                if (mbox & 0x4000) {
        !          3499:                        isp->isp_intmboxc++;
        !          3500:                        if (isp->isp_mboxbsy) {
        !          3501:                                int i = 0, obits = isp->isp_obits;
        !          3502:                                isp->isp_mboxtmp[i++] = mbox;
        !          3503:                                for (i = 1; i < MAX_MAILBOX; i++) {
        !          3504:                                        if ((obits & (1 << i)) == 0) {
        !          3505:                                                continue;
        !          3506:                                        }
        !          3507:                                        isp->isp_mboxtmp[i] =
        !          3508:                                            ISP_READ(isp, MBOX_OFF(i));
        !          3509:                                }
        !          3510:                                if (isp->isp_mbxwrk0) {
        !          3511:                                        if (isp_mbox_continue(isp) == 0) {
        !          3512:                                                return;
        !          3513:                                        }
        !          3514:                                }
        !          3515:                                MBOX_NOTIFY_COMPLETE(isp);
        !          3516:                        } else {
        !          3517:                                isp_prt(isp, ISP_LOGWARN,
        !          3518:                                    "Mbox Command Async (0x%x) with no waiters",
        !          3519:                                    mbox);
        !          3520:                        }
        !          3521:                } else if (isp_parse_async(isp, mbox) < 0) {
        !          3522:                        return;
        !          3523:                }
        !          3524:                if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) ||
        !          3525:                    isp->isp_state != ISP_RUNSTATE) {
        !          3526:                        ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
        !          3527:                        ISP_WRITE(isp, BIU_SEMA, 0);
        !          3528:                        return;
        !          3529:                }
        !          3530:        }
        !          3531:
        !          3532:        /*
        !          3533:         * We can't be getting this now.
        !          3534:         */
        !          3535:        if (isp->isp_state != ISP_RUNSTATE) {
        !          3536:                isp_prt(isp, ISP_LOGWARN,
        !          3537:                    "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
        !          3538:                /*
        !          3539:                 * Thank you very much!  *Burrrp*!
        !          3540:                 */
        !          3541:                WRITE_RESPONSE_QUEUE_OUT_POINTER(isp,
        !          3542:                    READ_RESPONSE_QUEUE_IN_POINTER(isp));
        !          3543:
        !          3544:                ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
        !          3545:                ISP_WRITE(isp, BIU_SEMA, 0);
        !          3546:                return;
        !          3547:        }
        !          3548:
        !          3549:        /*
        !          3550:         * Get the current Response Queue Out Pointer.
        !          3551:         *
        !          3552:         * If we're a 2300, we can ask what hardware what it thinks.
        !          3553:         */
        !          3554:        if (IS_23XX(isp)) {
        !          3555:                optr = ISP_READ(isp, isp->isp_respoutrp);
        !          3556:                /*
        !          3557:                 * Debug: to be taken out eventually
        !          3558:                 */
        !          3559:                if (isp->isp_residx != optr) {
        !          3560:                        isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x",
        !          3561:                            optr, isp->isp_residx);
        !          3562:                }
        !          3563:        } else {
        !          3564:                optr = isp->isp_residx;
        !          3565:        }
        !          3566:
        !          3567:        /*
        !          3568:         * You *must* read the Response Queue In Pointer
        !          3569:         * prior to clearing the RISC interrupt.
        !          3570:         *
        !          3571:         * Debounce the 2300 if revision less than 2.
        !          3572:         */
        !          3573:        if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) {
        !          3574:                i = 0;
        !          3575:                do {
        !          3576:                        iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
        !          3577:                        junk = READ_RESPONSE_QUEUE_IN_POINTER(isp);
        !          3578:                } while (junk != iptr && ++i < 1000);
        !          3579:
        !          3580:                if (iptr != junk) {
        !          3581:                        ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
        !          3582:                        isp_prt(isp, ISP_LOGWARN,
        !          3583:                            "Response Queue Out Pointer Unstable (%x, %x)",
        !          3584:                            iptr, junk);
        !          3585:                        return;
        !          3586:                }
        !          3587:        } else {
        !          3588:                iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
        !          3589:        }
        !          3590:        isp->isp_resodx = iptr;
        !          3591:
        !          3592:
        !          3593:        if (optr == iptr && sema == 0) {
        !          3594:                /*
        !          3595:                 * There are a lot of these- reasons unknown- mostly on
        !          3596:                 * faster Alpha machines.
        !          3597:                 *
        !          3598:                 * I tried delaying after writing HCCR_CMD_CLEAR_RISC_INT to
        !          3599:                 * make sure the old interrupt went away (to avoid 'ringing'
        !          3600:                 * effects), but that didn't stop this from occurring.
        !          3601:                 */
        !          3602:                if (IS_23XX(isp)) {
        !          3603:                        USEC_DELAY(100);
        !          3604:                        iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
        !          3605:                        junk = ISP_READ(isp, BIU_R2HSTSLO);
        !          3606:                } else {
        !          3607:                        junk = ISP_READ(isp, BIU_ISR);
        !          3608:                }
        !          3609:                if (optr == iptr) {
        !          3610:                        if (IS_23XX(isp)) {
        !          3611:                                ;
        !          3612:                        } else {
        !          3613:                                sema = ISP_READ(isp, BIU_SEMA);
        !          3614:                                mbox = ISP_READ(isp, OUTMAILBOX0);
        !          3615:                                if ((sema & 0x3) && (mbox & 0x8000)) {
        !          3616:                                        goto again;
        !          3617:                                }
        !          3618:                        }
        !          3619:                        isp->isp_intbogus++;
        !          3620:                        isp_prt(isp, ISP_LOGDEBUG1,
        !          3621:                            "bogus intr- isr %x (%x) iptr %x optr %x",
        !          3622:                            isr, junk, iptr, optr);
        !          3623:                }
        !          3624:        }
        !          3625:        isp->isp_resodx = iptr;
        !          3626:        ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
        !          3627:        ISP_WRITE(isp, BIU_SEMA, 0);
        !          3628:
        !          3629:        if (isp->isp_rspbsy) {
        !          3630:                return;
        !          3631:        }
        !          3632:        isp->isp_rspbsy = 1;
        !          3633:
        !          3634:        while (optr != iptr) {
        !          3635:                ispstatusreq_t local, *sp = &local;
        !          3636:                isphdr_t *hp;
        !          3637:                int type;
        !          3638:                u_int16_t oop;
        !          3639:                int buddaboom = 0;
        !          3640:
        !          3641:                hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);
        !          3642:                oop = optr;
        !          3643:                optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
        !          3644:                nlooked++;
        !          3645:                /*
        !          3646:                 * Synchronize our view of this response queue entry.
        !          3647:                 */
        !          3648:                MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN);
        !          3649:
        !          3650:                type = isp_get_response_type(isp, hp);
        !          3651:
        !          3652:                if (type == RQSTYPE_RESPONSE) {
        !          3653:                        isp_get_response(isp, (ispstatusreq_t *) hp, sp);
        !          3654:                } else if (type == RQSTYPE_RIO2) {
        !          3655:                        isp_rio2_t rio;
        !          3656:                        isp_get_rio2(isp, (isp_rio2_t *) hp, &rio);
        !          3657:                        for (i = 0; i < rio.req_header.rqs_seqno; i++) {
        !          3658:                                isp_fastpost_complete(isp, rio.req_handles[i]);
        !          3659:                        }
        !          3660:                        if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno)
        !          3661:                                isp->isp_fpcchiwater = rio.req_header.rqs_seqno;
        !          3662:                        MEMZERO(hp, QENTRY_LEN);        /* PERF */
        !          3663:                        continue;
        !          3664:                } else {
        !          3665:                        /*
        !          3666:                         * Somebody reachable via isp_handle_other_response
        !          3667:                         * may have updated the response queue pointers for
        !          3668:                         * us, so we reload our goal index.
        !          3669:                         */
        !          3670:                        if (isp_handle_other_response(isp, type, hp, &optr)) {
        !          3671:                                iptr = isp->isp_resodx;
        !          3672:                                MEMZERO(hp, QENTRY_LEN);        /* PERF */
        !          3673:                                continue;
        !          3674:                        }
        !          3675:
        !          3676:                        /*
        !          3677:                         * After this point, we'll just look at the header as
        !          3678:                         * we don't know how to deal with the rest of the
        !          3679:                         * response.
        !          3680:                         */
        !          3681:                        isp_get_response(isp, (ispstatusreq_t *) hp, sp);
        !          3682:
        !          3683:                        /*
        !          3684:                         * It really has to be a bounced request just copied
        !          3685:                         * from the request queue to the response queue. If
        !          3686:                         * not, something bad has happened.
        !          3687:                         */
        !          3688:                        if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) {
        !          3689:                                isp_prt(isp, ISP_LOGERR, notresp,
        !          3690:                                    sp->req_header.rqs_entry_type, oop, optr,
        !          3691:                                    nlooked);
        !          3692:                                if (isp->isp_dblev & ISP_LOGDEBUG0) {
        !          3693:                                        isp_print_bytes(isp, "Queue Entry",
        !          3694:                                            QENTRY_LEN, sp);
        !          3695:                                }
        !          3696:                                MEMZERO(hp, QENTRY_LEN);        /* PERF */
        !          3697:                                continue;
        !          3698:                        }
        !          3699:                        buddaboom = 1;
        !          3700:                }
        !          3701:
        !          3702:                if (sp->req_header.rqs_flags & 0xf) {
        !          3703: #define        _RQS_OFLAGS     \
        !          3704:        ~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET)
        !          3705:                        if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
        !          3706:                                isp_prt(isp, ISP_LOGWARN,
        !          3707:                                    "continuation segment");
        !          3708:                                WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
        !          3709:                                continue;
        !          3710:                        }
        !          3711:                        if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
        !          3712:                                isp_prt(isp, ISP_LOGDEBUG1,
        !          3713:                                    "internal queues full");
        !          3714:                                /*
        !          3715:                                 * We'll synthesize a QUEUE FULL message below.
        !          3716:                                 */
        !          3717:                        }
        !          3718:                        if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
        !          3719:                                isp_prt(isp, ISP_LOGERR,  "bad header flag");
        !          3720:                                buddaboom++;
        !          3721:                        }
        !          3722:                        if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
        !          3723:                                isp_prt(isp, ISP_LOGERR, "bad request packet");
        !          3724:                                buddaboom++;
        !          3725:                        }
        !          3726:                        if (sp->req_header.rqs_flags & _RQS_OFLAGS) {
        !          3727:                                isp_prt(isp, ISP_LOGERR,
        !          3728:                                    "unknown flags (0x%x) in response",
        !          3729:                                    sp->req_header.rqs_flags);
        !          3730:                                buddaboom++;
        !          3731:                        }
        !          3732: #undef _RQS_OFLAGS
        !          3733:                }
        !          3734:                if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) {
        !          3735:                        MEMZERO(hp, QENTRY_LEN);        /* PERF */
        !          3736:                        isp_prt(isp, ISP_LOGERR,
        !          3737:                            "bad request handle %d (type 0x%x, flags 0x%x)",
        !          3738:                            sp->req_handle, sp->req_header.rqs_entry_type,
        !          3739:                            sp->req_header.rqs_flags);
        !          3740:                        WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
        !          3741:                        continue;
        !          3742:                }
        !          3743:                xs = isp_find_xs(isp, sp->req_handle);
        !          3744:                if (xs == NULL) {
        !          3745:                        u_int8_t ts = sp->req_completion_status & 0xff;
        !          3746:                        MEMZERO(hp, QENTRY_LEN);        /* PERF */
        !          3747:                        /*
        !          3748:                         * Only whine if this isn't the expected fallout of
        !          3749:                         * aborting the command.
        !          3750:                         */
        !          3751:                        if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) {
        !          3752:                                isp_prt(isp, ISP_LOGERR,
        !          3753:                                    "cannot find handle 0x%x (type 0x%x)",
        !          3754:                                    sp->req_handle,
        !          3755:                                    sp->req_header.rqs_entry_type);
        !          3756:                        } else if (ts != RQCS_ABORTED) {
        !          3757:                                isp_prt(isp, ISP_LOGERR,
        !          3758:                                    "cannot find handle 0x%x (status 0x%x)",
        !          3759:                                    sp->req_handle, ts);
        !          3760:                        }
        !          3761:                        WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
        !          3762:                        continue;
        !          3763:                }
        !          3764:                isp_destroy_handle(isp, sp->req_handle);
        !          3765:                if (sp->req_status_flags & RQSTF_BUS_RESET) {
        !          3766:                        XS_SETERR(xs, HBA_BUSRESET);
        !          3767:                        isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
        !          3768:                }
        !          3769:                if (buddaboom) {
        !          3770:                        XS_SETERR(xs, HBA_BOTCH);
        !          3771:                }
        !          3772:
        !          3773:                if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) {
        !          3774:                        /*
        !          3775:                         * Fibre Channel F/W doesn't say we got status
        !          3776:                         * if there's Sense Data instead. I guess they
        !          3777:                         * think it goes w/o saying.
        !          3778:                         */
        !          3779:                        sp->req_state_flags |= RQSF_GOT_STATUS;
        !          3780:                }
        !          3781:                if (sp->req_state_flags & RQSF_GOT_STATUS) {
        !          3782:                        *XS_STSP(xs) = sp->req_scsi_status & 0xff;
        !          3783:                }
        !          3784:
        !          3785:                switch (sp->req_header.rqs_entry_type) {
        !          3786:                case RQSTYPE_RESPONSE:
        !          3787:                        XS_SET_STATE_STAT(isp, xs, sp);
        !          3788:                        isp_parse_status(isp, sp, xs);
        !          3789:                        if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
        !          3790:                            (*XS_STSP(xs) == SCSI_BUSY)) {
        !          3791:                                XS_SETERR(xs, HBA_TGTBSY);
        !          3792:                        }
        !          3793:                        if (IS_SCSI(isp)) {
        !          3794:                                XS_RESID(xs) = sp->req_resid;
        !          3795:                                if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
        !          3796:                                    (*XS_STSP(xs) == SCSI_CHECK) &&
        !          3797:                                    (sp->req_state_flags & RQSF_GOT_SENSE)) {
        !          3798:                                        XS_SAVE_SENSE(xs, sp);
        !          3799:                                }
        !          3800:                                /*
        !          3801:                                 * A new synchronous rate was negotiated for
        !          3802:                                 * this target. Mark state such that we'll go
        !          3803:                                 * look up that which has changed later.
        !          3804:                                 */
        !          3805:                                if (sp->req_status_flags & RQSTF_NEGOTIATION) {
        !          3806:                                        int t = XS_TGT(xs);
        !          3807:                                        sdparam *sdp = isp->isp_param;
        !          3808:                                        sdp += XS_CHANNEL(xs);
        !          3809:                                        sdp->isp_devparam[t].dev_refresh = 1;
        !          3810:                                        isp->isp_update |=
        !          3811:                                            (1 << XS_CHANNEL(xs));
        !          3812:                                }
        !          3813:                        } else {
        !          3814:                                if (sp->req_status_flags & RQSF_XFER_COMPLETE) {
        !          3815:                                        XS_RESID(xs) = 0;
        !          3816:                                } else if (sp->req_scsi_status & RQCS_RESID) {
        !          3817:                                        XS_RESID(xs) = sp->req_resid;
        !          3818:                                } else {
        !          3819:                                        XS_RESID(xs) = 0;
        !          3820:                                }
        !          3821:                                if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
        !          3822:                                    (*XS_STSP(xs) == SCSI_CHECK) &&
        !          3823:                                    (sp->req_scsi_status & RQCS_SV)) {
        !          3824:                                        XS_SAVE_SENSE(xs, sp);
        !          3825:                                        /* solely for the benefit of debug */
        !          3826:                                        sp->req_state_flags |= RQSF_GOT_SENSE;
        !          3827:                                }
        !          3828:                        }
        !          3829:                        isp_prt(isp, ISP_LOGDEBUG2,
        !          3830:                           "asked for %ld got resid %ld", (long) XS_XFRLEN(xs),
        !          3831:                           (long) sp->req_resid);
        !          3832:                        break;
        !          3833:                case RQSTYPE_REQUEST:
        !          3834:                        if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
        !          3835:                                /*
        !          3836:                                 * Force Queue Full status.
        !          3837:                                 */
        !          3838:                                *XS_STSP(xs) = SCSI_QFULL;
        !          3839:                                XS_SETERR(xs, HBA_NOERROR);
        !          3840:                        } else if (XS_NOERR(xs)) {
        !          3841:                                /*
        !          3842:                                 * ????
        !          3843:                                 */
        !          3844:                                isp_prt(isp, ISP_LOGDEBUG0,
        !          3845:                                    "Request Queue Entry bounced back");
        !          3846:                                XS_SETERR(xs, HBA_BOTCH);
        !          3847:                        }
        !          3848:                        XS_RESID(xs) = XS_XFRLEN(xs);
        !          3849:                        break;
        !          3850:                default:
        !          3851:                        isp_prt(isp, ISP_LOGWARN,
        !          3852:                            "unhandled response queue type 0x%x",
        !          3853:                            sp->req_header.rqs_entry_type);
        !          3854:                        if (XS_NOERR(xs)) {
        !          3855:                                XS_SETERR(xs, HBA_BOTCH);
        !          3856:                        }
        !          3857:                        break;
        !          3858:                }
        !          3859:
        !          3860:                /*
        !          3861:                 * Free any dma resources. As a side effect, this may
        !          3862:                 * also do any cache flushing necessary for data coherence.                      */
        !          3863:                if (XS_XFRLEN(xs)) {
        !          3864:                        ISP_DMAFREE(isp, xs, sp->req_handle);
        !          3865:                }
        !          3866:
        !          3867:                if (((isp->isp_dblev & (ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
        !          3868:                    ((isp->isp_dblev & ISP_LOGDEBUG1) && ((!XS_NOERR(xs)) ||
        !          3869:                    (*XS_STSP(xs) != SCSI_GOOD)))) {
        !          3870:                        char skey;
        !          3871:                        if (sp->req_state_flags & RQSF_GOT_SENSE) {
        !          3872:                                skey = XS_SNSKEY(xs) & 0xf;
        !          3873:                                if (skey < 10)
        !          3874:                                        skey += '0';
        !          3875:                                else
        !          3876:                                        skey += 'a' - 10;
        !          3877:                        } else if (*XS_STSP(xs) == SCSI_CHECK) {
        !          3878:                                skey = '?';
        !          3879:                        } else {
        !          3880:                                skey = '.';
        !          3881:                        }
        !          3882:                        isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs),
        !          3883:                            XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs),
        !          3884:                            (ulong)XS_RESID(xs),
        !          3885:                            *XS_STSP(xs), skey, XS_ERR(xs));
        !          3886:                }
        !          3887:
        !          3888:                if (isp->isp_nactive > 0)
        !          3889:                    isp->isp_nactive--;
        !          3890:                complist[ndone++] = xs; /* defer completion call until later */
        !          3891:                MEMZERO(hp, QENTRY_LEN);        /* PERF */
        !          3892:                if (ndone == MAX_REQUESTQ_COMPLETIONS) {
        !          3893:                        break;
        !          3894:                }
        !          3895:        }
        !          3896:
        !          3897:        /*
        !          3898:         * If we looked at any commands, then it's valid to find out
        !          3899:         * what the outpointer is. It also is a trigger to update the
        !          3900:         * ISP's notion of what we've seen so far.
        !          3901:         */
        !          3902:        if (nlooked) {
        !          3903:                WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
        !          3904:                /*
        !          3905:                 * While we're at it, read the request queue out pointer.
        !          3906:                 */
        !          3907:                isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
        !          3908:                if (isp->isp_rscchiwater < ndone)
        !          3909:                        isp->isp_rscchiwater = ndone;
        !          3910:        }
        !          3911:
        !          3912:        isp->isp_residx = optr;
        !          3913:        isp->isp_rspbsy = 0;
        !          3914:        for (i = 0; i < ndone; i++) {
        !          3915:                xs = complist[i];
        !          3916:                if (xs) {
        !          3917:                        isp->isp_rsltccmplt++;
        !          3918:                        isp_done(xs);
        !          3919:                }
        !          3920:        }
        !          3921: }
        !          3922:
        !          3923: /*
        !          3924:  * Support routines.
        !          3925:  */
        !          3926:
        !          3927: static int
        !          3928: isp_parse_async(struct ispsoftc *isp, u_int16_t mbox)
        !          3929: {
        !          3930:        int rval = 0;
        !          3931:        int bus;
        !          3932:
        !          3933:        if (IS_DUALBUS(isp)) {
        !          3934:                bus = ISP_READ(isp, OUTMAILBOX6);
        !          3935:        } else {
        !          3936:                bus = 0;
        !          3937:        }
        !          3938:        isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
        !          3939:
        !          3940:        switch (mbox) {
        !          3941:        case ASYNC_BUS_RESET:
        !          3942:                isp->isp_sendmarker |= (1 << bus);
        !          3943: #ifdef ISP_TARGET_MODE
        !          3944:                if (isp_target_async(isp, bus, mbox))
        !          3945:                        rval = -1;
        !          3946: #endif
        !          3947:                isp_async(isp, ISPASYNC_BUS_RESET, &bus);
        !          3948:                break;
        !          3949:        case ASYNC_SYSTEM_ERROR:
        !          3950: #ifdef ISP_FW_CRASH_DUMP
        !          3951:                /*
        !          3952:                 * If we have crash dumps enabled, it's up to the handler
        !          3953:                 * for isp_async to reinit stuff and restart the firmware
        !          3954:                 * after performing the crash dump. The reason we do things
        !          3955:                 * this way is that we may need to activate a kernel thread
        !          3956:                 * to do all the crash dump goop.
        !          3957:                 */
        !          3958:                isp_async(isp, ISPASYNC_FW_CRASH, NULL);
        !          3959: #else
        !          3960:                isp_async(isp, ISPASYNC_FW_CRASH, NULL);
        !          3961:                isp_reinit(isp);
        !          3962:                isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
        !          3963: #endif
        !          3964:                rval = -1;
        !          3965:                break;
        !          3966:
        !          3967:        case ASYNC_RQS_XFER_ERR:
        !          3968:                isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
        !          3969:                break;
        !          3970:
        !          3971:        case ASYNC_RSP_XFER_ERR:
        !          3972:                isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
        !          3973:                break;
        !          3974:
        !          3975:        case ASYNC_QWAKEUP:
        !          3976:                /*
        !          3977:                 * We've just been notified that the Queue has woken up.
        !          3978:                 * We don't need to be chatty about this- just unlatch things
        !          3979:                 * and move on.
        !          3980:                 */
        !          3981:                mbox = READ_REQUEST_QUEUE_OUT_POINTER(isp);
        !          3982:                break;
        !          3983:
        !          3984:        case ASYNC_TIMEOUT_RESET:
        !          3985:                isp_prt(isp, ISP_LOGWARN,
        !          3986:                    "timeout initiated SCSI bus reset of bus %d", bus);
        !          3987:                isp->isp_sendmarker |= (1 << bus);
        !          3988: #ifdef ISP_TARGET_MODE
        !          3989:                if (isp_target_async(isp, bus, mbox))
        !          3990:                        rval = -1;
        !          3991: #endif
        !          3992:                break;
        !          3993:
        !          3994:        case ASYNC_DEVICE_RESET:
        !          3995:                isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus);
        !          3996:                isp->isp_sendmarker |= (1 << bus);
        !          3997: #ifdef ISP_TARGET_MODE
        !          3998:                if (isp_target_async(isp, bus, mbox))
        !          3999:                        rval = -1;
        !          4000: #endif
        !          4001:                break;
        !          4002:
        !          4003:        case ASYNC_EXTMSG_UNDERRUN:
        !          4004:                isp_prt(isp, ISP_LOGWARN, "extended message underrun");
        !          4005:                break;
        !          4006:
        !          4007:        case ASYNC_SCAM_INT:
        !          4008:                isp_prt(isp, ISP_LOGINFO, "SCAM interrupt");
        !          4009:                break;
        !          4010:
        !          4011:        case ASYNC_HUNG_SCSI:
        !          4012:                isp_prt(isp, ISP_LOGERR,
        !          4013:                    "stalled SCSI Bus after DATA Overrun");
        !          4014:                /* XXX: Need to issue SCSI reset at this point */
        !          4015:                break;
        !          4016:
        !          4017:        case ASYNC_KILLED_BUS:
        !          4018:                isp_prt(isp, ISP_LOGERR, "SCSI Bus reset after DATA Overrun");
        !          4019:                break;
        !          4020:
        !          4021:        case ASYNC_BUS_TRANSIT:
        !          4022:                mbox = ISP_READ(isp, OUTMAILBOX2);
        !          4023:                switch (mbox & 0x1c00) {
        !          4024:                case SXP_PINS_LVD_MODE:
        !          4025:                        isp_prt(isp, ISP_LOGINFO, "Transition to LVD mode");
        !          4026:                        SDPARAM(isp)->isp_diffmode = 0;
        !          4027:                        SDPARAM(isp)->isp_ultramode = 0;
        !          4028:                        SDPARAM(isp)->isp_lvdmode = 1;
        !          4029:                        break;
        !          4030:                case SXP_PINS_HVD_MODE:
        !          4031:                        isp_prt(isp, ISP_LOGINFO,
        !          4032:                            "Transition to Differential mode");
        !          4033:                        SDPARAM(isp)->isp_diffmode = 1;
        !          4034:                        SDPARAM(isp)->isp_ultramode = 0;
        !          4035:                        SDPARAM(isp)->isp_lvdmode = 0;
        !          4036:                        break;
        !          4037:                case SXP_PINS_SE_MODE:
        !          4038:                        isp_prt(isp, ISP_LOGINFO,
        !          4039:                            "Transition to Single Ended mode");
        !          4040:                        SDPARAM(isp)->isp_diffmode = 0;
        !          4041:                        SDPARAM(isp)->isp_ultramode = 1;
        !          4042:                        SDPARAM(isp)->isp_lvdmode = 0;
        !          4043:                        break;
        !          4044:                default:
        !          4045:                        isp_prt(isp, ISP_LOGWARN,
        !          4046:                            "Transition to Unknown Mode 0x%x", mbox);
        !          4047:                        break;
        !          4048:                }
        !          4049:                /*
        !          4050:                 * XXX: Set up to renegotiate again!
        !          4051:                 */
        !          4052:                /* Can only be for a 1080... */
        !          4053:                isp->isp_sendmarker |= (1 << bus);
        !          4054:                break;
        !          4055:
        !          4056:        /*
        !          4057:         * We can use bus, which will always be zero for FC cards,
        !          4058:         * as a mailbox pattern accumulator to be checked below.
        !          4059:         */
        !          4060:        case ASYNC_RIO5:
        !          4061:                bus = 0x1ce;    /* outgoing mailbox regs 1-3, 6-7 */
        !          4062:                break;
        !          4063:
        !          4064:        case ASYNC_RIO4:
        !          4065:                bus = 0x14e;    /* outgoing mailbox regs 1-3, 6 */
        !          4066:                break;
        !          4067:
        !          4068:        case ASYNC_RIO3:
        !          4069:                bus = 0x10e;    /* outgoing mailbox regs 1-3 */
        !          4070:                break;
        !          4071:
        !          4072:        case ASYNC_RIO2:
        !          4073:                bus = 0x106;    /* outgoing mailbox regs 1-2 */
        !          4074:                break;
        !          4075:
        !          4076:        case ASYNC_RIO1:
        !          4077:        case ASYNC_CMD_CMPLT:
        !          4078:                bus = 0x102;    /* outgoing mailbox regs 1 */
        !          4079:                break;
        !          4080:
        !          4081:        case ASYNC_RIO_RESP:
        !          4082:                return (rval);
        !          4083:
        !          4084:        case ASYNC_CTIO_DONE:
        !          4085:        {
        !          4086: #ifdef ISP_TARGET_MODE
        !          4087:                int handle =
        !          4088:                    (ISP_READ(isp, OUTMAILBOX2) << 16) |
        !          4089:                    (ISP_READ(isp, OUTMAILBOX1));
        !          4090:                if (isp_target_async(isp, handle, mbox))
        !          4091:                        rval = -1;
        !          4092: #else
        !          4093:                isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done");
        !          4094: #endif
        !          4095:                isp->isp_fphccmplt++;   /* count it as a fast posting intr */
        !          4096:                break;
        !          4097:        }
        !          4098:        case ASYNC_LIP_F8:
        !          4099:        case ASYNC_LIP_OCCURRED:
        !          4100:                FCPARAM(isp)->isp_lipseq =
        !          4101:                    ISP_READ(isp, OUTMAILBOX1);
        !          4102:                FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
        !          4103:                FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
        !          4104:                isp->isp_sendmarker = 1;
        !          4105:                isp_mark_getpdb_all(isp);
        !          4106:                isp_async(isp, ISPASYNC_LIP, NULL);
        !          4107: #ifdef ISP_TARGET_MODE
        !          4108:                if (isp_target_async(isp, bus, mbox))
        !          4109:                        rval = -1;
        !          4110: #endif
        !          4111:                /*
        !          4112:                 * We've had problems with data corruption occurring on
        !          4113:                 * commands that complete (with no apparent error) after
        !          4114:                 * we receive a LIP. This has been observed mostly on
        !          4115:                 * Local Loop topologies. To be safe, let's just mark
        !          4116:                 * all active commands as dead.
        !          4117:                 */
        !          4118:                if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
        !          4119:                    FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
        !          4120:                        int i, j;
        !          4121:                        for (i = j = 0; i < isp->isp_maxcmds; i++) {
        !          4122:                                XS_T *xs;
        !          4123:                                xs = isp->isp_xflist[i];
        !          4124:                                if (xs != NULL) {
        !          4125:                                        j++;
        !          4126:                                        XS_SETERR(xs, HBA_BUSRESET);
        !          4127:                                }
        !          4128:                        }
        !          4129:                        if (j) {
        !          4130:                                isp_prt(isp, ISP_LOGERR,
        !          4131:                                    "LIP destroyed %d active commands", j);
        !          4132:                        }
        !          4133:                }
        !          4134:                break;
        !          4135:
        !          4136:        case ASYNC_LOOP_UP:
        !          4137:                isp->isp_sendmarker = 1;
        !          4138:                FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
        !          4139:                FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
        !          4140:                isp_mark_getpdb_all(isp);
        !          4141:                isp_async(isp, ISPASYNC_LOOP_UP, NULL);
        !          4142: #ifdef ISP_TARGET_MODE
        !          4143:                if (isp_target_async(isp, bus, mbox))
        !          4144:                        rval = -1;
        !          4145: #endif
        !          4146:                break;
        !          4147:
        !          4148:        case ASYNC_LOOP_DOWN:
        !          4149:                isp->isp_sendmarker = 1;
        !          4150:                FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
        !          4151:                FCPARAM(isp)->isp_loopstate = LOOP_NIL;
        !          4152:                isp_mark_getpdb_all(isp);
        !          4153:                isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
        !          4154: #ifdef ISP_TARGET_MODE
        !          4155:                if (isp_target_async(isp, bus, mbox))
        !          4156:                        rval = -1;
        !          4157: #endif
        !          4158:                break;
        !          4159:
        !          4160:        case ASYNC_LOOP_RESET:
        !          4161:                isp->isp_sendmarker = 1;
        !          4162:                FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
        !          4163:                FCPARAM(isp)->isp_loopstate = LOOP_NIL;
        !          4164:                isp_mark_getpdb_all(isp);
        !          4165:                isp_async(isp, ISPASYNC_LOOP_RESET, NULL);
        !          4166: #ifdef ISP_TARGET_MODE
        !          4167:                if (isp_target_async(isp, bus, mbox))
        !          4168:                        rval = -1;
        !          4169: #endif
        !          4170:                break;
        !          4171:
        !          4172:        case ASYNC_PDB_CHANGED:
        !          4173:                isp->isp_sendmarker = 1;
        !          4174:                FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
        !          4175:                isp_mark_getpdb_all(isp);
        !          4176:                isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB);
        !          4177:                break;
        !          4178:
        !          4179:        case ASYNC_CHANGE_NOTIFY:
        !          4180:                /*
        !          4181:                 * Not correct, but it will force us to rescan the loop.
        !          4182:                 */
        !          4183:                FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
        !          4184:                isp_mark_getpdb_all(isp);
        !          4185:                isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS);
        !          4186:                break;
        !          4187:
        !          4188:        case ASYNC_PTPMODE:
        !          4189:                if (FCPARAM(isp)->isp_onfabric)
        !          4190:                        FCPARAM(isp)->isp_topo = TOPO_F_PORT;
        !          4191:                else
        !          4192:                        FCPARAM(isp)->isp_topo = TOPO_N_PORT;
        !          4193:                isp_mark_getpdb_all(isp);
        !          4194:                isp->isp_sendmarker = 1;
        !          4195:                FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
        !          4196:                FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
        !          4197:                isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
        !          4198: #ifdef ISP_TARGET_MODE
        !          4199:                if (isp_target_async(isp, bus, mbox))
        !          4200:                        rval = -1;
        !          4201: #endif
        !          4202:                isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode");
        !          4203:                break;
        !          4204:
        !          4205:        case ASYNC_CONNMODE:
        !          4206:                mbox = ISP_READ(isp, OUTMAILBOX1);
        !          4207:                isp_mark_getpdb_all(isp);
        !          4208:                switch (mbox) {
        !          4209:                case ISP_CONN_LOOP:
        !          4210:                        isp_prt(isp, ISP_LOGINFO,
        !          4211:                            "Point-to-Point -> Loop mode");
        !          4212:                        break;
        !          4213:                case ISP_CONN_PTP:
        !          4214:                        isp_prt(isp, ISP_LOGINFO,
        !          4215:                            "Loop -> Point-to-Point mode");
        !          4216:                        break;
        !          4217:                case ISP_CONN_BADLIP:
        !          4218:                        isp_prt(isp, ISP_LOGWARN,
        !          4219:                            "Point-to-Point -> Loop mode (BAD LIP)");
        !          4220:                        break;
        !          4221:                case ISP_CONN_FATAL:
        !          4222:                        isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
        !          4223: #ifdef ISP_FW_CRASH_DUMP
        !          4224:                        isp_async(isp, ISPASYNC_FW_CRASH, NULL);
        !          4225: #else
        !          4226:                        isp_async(isp, ISPASYNC_FW_CRASH, NULL);
        !          4227:                        isp_reinit(isp);
        !          4228:                        isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
        !          4229: #endif
        !          4230:                        return (-1);
        !          4231:                case ISP_CONN_LOOPBACK:
        !          4232:                        isp_prt(isp, ISP_LOGWARN,
        !          4233:                            "Looped Back in Point-to-Point mode");
        !          4234:                        break;
        !          4235:                default:
        !          4236:                        isp_prt(isp, ISP_LOGWARN,
        !          4237:                            "Unknown connection mode (0x%x)", mbox);
        !          4238:                        break;
        !          4239:                }
        !          4240:                isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
        !          4241:                isp->isp_sendmarker = 1;
        !          4242:                FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
        !          4243:                FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
        !          4244:                break;
        !          4245:
        !          4246:        default:
        !          4247:                isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
        !          4248:                break;
        !          4249:        }
        !          4250:
        !          4251:        if (bus & 0x100) {
        !          4252:                int i, nh;
        !          4253:                u_int16_t handles[5];
        !          4254:
        !          4255:                for (nh = 0, i = 1; i < MAX_MAILBOX; i++) {
        !          4256:                        if ((bus & (1 << i)) == 0) {
        !          4257:                                continue;
        !          4258:                        }
        !          4259:                        handles[nh++] = ISP_READ(isp, MBOX_OFF(i));
        !          4260:                }
        !          4261:                for (i = 0; i < nh; i++) {
        !          4262:                        isp_fastpost_complete(isp, handles[i]);
        !          4263:                        isp_prt(isp,  ISP_LOGDEBUG3,
        !          4264:                            "fast post completion of %u", handles[i]);
        !          4265:                }
        !          4266:                if (isp->isp_fpcchiwater < nh)
        !          4267:                        isp->isp_fpcchiwater = nh;
        !          4268:        } else {
        !          4269:                isp->isp_intoasync++;
        !          4270:        }
        !          4271:        return (rval);
        !          4272: }
        !          4273:
        !          4274: /*
        !          4275:  * Handle other response entries. A pointer to the request queue output
        !          4276:  * index is here in case we want to eat several entries at once, although
        !          4277:  * this is not used currently.
        !          4278:  */
        !          4279:
        !          4280: static int
        !          4281: isp_handle_other_response(struct ispsoftc *isp, int type,
        !          4282:     isphdr_t *hp, u_int16_t *optrp)
        !          4283: {
        !          4284:        switch (type) {
        !          4285:        case RQSTYPE_STATUS_CONT:
        !          4286:                isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response");
        !          4287:                return (1);
        !          4288:        case RQSTYPE_ATIO:
        !          4289:        case RQSTYPE_CTIO:
        !          4290:        case RQSTYPE_ENABLE_LUN:
        !          4291:        case RQSTYPE_MODIFY_LUN:
        !          4292:        case RQSTYPE_NOTIFY:
        !          4293:        case RQSTYPE_NOTIFY_ACK:
        !          4294:        case RQSTYPE_CTIO1:
        !          4295:        case RQSTYPE_ATIO2:
        !          4296:        case RQSTYPE_CTIO2:
        !          4297:        case RQSTYPE_CTIO3:
        !          4298:                isp->isp_rsltccmplt++;  /* count as a response completion */
        !          4299: #ifdef ISP_TARGET_MODE
        !          4300:                if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) {
        !          4301:                        return (1);
        !          4302:                }
        !          4303: #endif
        !          4304:                /* FALLTHROUGH */
        !          4305:        case RQSTYPE_REQUEST:
        !          4306:        default:
        !          4307:                if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) {
        !          4308:                        return (1);
        !          4309:                }
        !          4310:                isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
        !          4311:                    isp_get_response_type(isp, hp));
        !          4312:                return (0);
        !          4313:        }
        !          4314: }
        !          4315:
        !          4316: static void
        !          4317: isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
        !          4318: {
        !          4319:        switch (sp->req_completion_status & 0xff) {
        !          4320:        case RQCS_COMPLETE:
        !          4321:                if (XS_NOERR(xs)) {
        !          4322:                        XS_SETERR(xs, HBA_NOERROR);
        !          4323:                }
        !          4324:                return;
        !          4325:
        !          4326:        case RQCS_INCOMPLETE:
        !          4327:                if ((sp->req_state_flags & RQSF_GOT_TARGET) == 0) {
        !          4328:                        isp_prt(isp, ISP_LOGDEBUG1,
        !          4329:                            "Selection Timeout for %d.%d.%d",
        !          4330:                            XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4331:                        if (XS_NOERR(xs)) {
        !          4332:                                XS_SETERR(xs, HBA_SELTIMEOUT);
        !          4333:                        }
        !          4334:                        return;
        !          4335:                }
        !          4336:                isp_prt(isp, ISP_LOGERR,
        !          4337:                    "command incomplete for %d.%d.%d, state 0x%x",
        !          4338:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
        !          4339:                    sp->req_state_flags);
        !          4340:                break;
        !          4341:
        !          4342:        case RQCS_DMA_ERROR:
        !          4343:                isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d",
        !          4344:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4345:                break;
        !          4346:
        !          4347:        case RQCS_TRANSPORT_ERROR:
        !          4348:        {
        !          4349:                char buf[172];
        !          4350:                SNPRINTF(buf, sizeof (buf), "states=>");
        !          4351:                if (sp->req_state_flags & RQSF_GOT_BUS) {
        !          4352:                        SNPRINTF(buf, sizeof (buf), "%s GOT_BUS", buf);
        !          4353:                }
        !          4354:                if (sp->req_state_flags & RQSF_GOT_TARGET) {
        !          4355:                        SNPRINTF(buf, sizeof (buf), "%s GOT_TGT", buf);
        !          4356:                }
        !          4357:                if (sp->req_state_flags & RQSF_SENT_CDB) {
        !          4358:                        SNPRINTF(buf, sizeof (buf), "%s SENT_CDB", buf);
        !          4359:                }
        !          4360:                if (sp->req_state_flags & RQSF_XFRD_DATA) {
        !          4361:                        SNPRINTF(buf, sizeof (buf), "%s XFRD_DATA", buf);
        !          4362:                }
        !          4363:                if (sp->req_state_flags & RQSF_GOT_STATUS) {
        !          4364:                        SNPRINTF(buf, sizeof (buf), "%s GOT_STS", buf);
        !          4365:                }
        !          4366:                if (sp->req_state_flags & RQSF_GOT_SENSE) {
        !          4367:                        SNPRINTF(buf, sizeof (buf), "%s GOT_SNS", buf);
        !          4368:                }
        !          4369:                if (sp->req_state_flags & RQSF_XFER_COMPLETE) {
        !          4370:                        SNPRINTF(buf, sizeof (buf), "%s XFR_CMPLT", buf);
        !          4371:                }
        !          4372:                SNPRINTF(buf, sizeof (buf), "%s\nstatus=>", buf);
        !          4373:                if (sp->req_status_flags & RQSTF_DISCONNECT) {
        !          4374:                        SNPRINTF(buf, sizeof (buf), "%s Disconnect", buf);
        !          4375:                }
        !          4376:                if (sp->req_status_flags & RQSTF_SYNCHRONOUS) {
        !          4377:                        SNPRINTF(buf, sizeof (buf), "%s Sync_xfr", buf);
        !          4378:                }
        !          4379:                if (sp->req_status_flags & RQSTF_PARITY_ERROR) {
        !          4380:                        SNPRINTF(buf, sizeof (buf), "%s Parity", buf);
        !          4381:                }
        !          4382:                if (sp->req_status_flags & RQSTF_BUS_RESET) {
        !          4383:                        SNPRINTF(buf, sizeof (buf), "%s Bus_Reset", buf);
        !          4384:                }
        !          4385:                if (sp->req_status_flags & RQSTF_DEVICE_RESET) {
        !          4386:                        SNPRINTF(buf, sizeof (buf), "%s Device_Reset", buf);
        !          4387:                }
        !          4388:                if (sp->req_status_flags & RQSTF_ABORTED) {
        !          4389:                        SNPRINTF(buf, sizeof (buf), "%s Aborted", buf);
        !          4390:                }
        !          4391:                if (sp->req_status_flags & RQSTF_TIMEOUT) {
        !          4392:                        SNPRINTF(buf, sizeof (buf), "%s Timeout", buf);
        !          4393:                }
        !          4394:                if (sp->req_status_flags & RQSTF_NEGOTIATION) {
        !          4395:                        SNPRINTF(buf, sizeof (buf), "%s Negotiation", buf);
        !          4396:                }
        !          4397:                isp_prt(isp, ISP_LOGERR, "%s", buf);
        !          4398:                isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s",
        !          4399:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf);
        !          4400:                break;
        !          4401:        }
        !          4402:        case RQCS_RESET_OCCURRED:
        !          4403:                isp_prt(isp, ISP_LOGWARN,
        !          4404:                    "bus reset destroyed command for %d.%d.%d",
        !          4405:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4406:                isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
        !          4407:                if (XS_NOERR(xs)) {
        !          4408:                        XS_SETERR(xs, HBA_BUSRESET);
        !          4409:                }
        !          4410:                return;
        !          4411:
        !          4412:        case RQCS_ABORTED:
        !          4413:                isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
        !          4414:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4415:                isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
        !          4416:                if (XS_NOERR(xs)) {
        !          4417:                        XS_SETERR(xs, HBA_ABORTED);
        !          4418:                }
        !          4419:                return;
        !          4420:
        !          4421:        case RQCS_TIMEOUT:
        !          4422:                isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d",
        !          4423:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4424:                /*
        !          4425:                 * Check to see if we logged out the device.
        !          4426:                 */
        !          4427:                if (IS_FC(isp)) {
        !          4428:                        if ((sp->req_completion_status & RQSTF_LOGOUT) &&
        !          4429:                            FCPARAM(isp)->portdb[XS_TGT(xs)].valid &&
        !          4430:                            FCPARAM(isp)->portdb[XS_TGT(xs)].fabric_dev) {
        !          4431:                                FCPARAM(isp)->portdb[XS_TGT(xs)].relogin = 1;
        !          4432:                        }
        !          4433:                }
        !          4434:                if (XS_NOERR(xs)) {
        !          4435:                        XS_SETERR(xs, HBA_CMDTIMEOUT);
        !          4436:                }
        !          4437:                return;
        !          4438:
        !          4439:        case RQCS_DATA_OVERRUN:
        !          4440:                XS_RESID(xs) = sp->req_resid;
        !          4441:                isp_prt(isp, ISP_LOGERR, "data overrun for command on %d.%d.%d",
        !          4442:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4443:                if (XS_NOERR(xs)) {
        !          4444:                        XS_SETERR(xs, HBA_DATAOVR);
        !          4445:                }
        !          4446:                return;
        !          4447:
        !          4448:        case RQCS_COMMAND_OVERRUN:
        !          4449:                isp_prt(isp, ISP_LOGERR,
        !          4450:                    "command overrun for command on %d.%d.%d",
        !          4451:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4452:                break;
        !          4453:
        !          4454:        case RQCS_STATUS_OVERRUN:
        !          4455:                isp_prt(isp, ISP_LOGERR,
        !          4456:                    "status overrun for command on %d.%d.%d",
        !          4457:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4458:                break;
        !          4459:
        !          4460:        case RQCS_BAD_MESSAGE:
        !          4461:                isp_prt(isp, ISP_LOGERR,
        !          4462:                    "msg not COMMAND COMPLETE after status %d.%d.%d",
        !          4463:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4464:                break;
        !          4465:
        !          4466:        case RQCS_NO_MESSAGE_OUT:
        !          4467:                isp_prt(isp, ISP_LOGERR,
        !          4468:                    "No MESSAGE OUT phase after selection on %d.%d.%d",
        !          4469:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4470:                break;
        !          4471:
        !          4472:        case RQCS_EXT_ID_FAILED:
        !          4473:                isp_prt(isp, ISP_LOGERR, "EXTENDED IDENTIFY failed %d.%d.%d",
        !          4474:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4475:                break;
        !          4476:
        !          4477:        case RQCS_IDE_MSG_FAILED:
        !          4478:                isp_prt(isp, ISP_LOGERR,
        !          4479:                    "INITIATOR DETECTED ERROR rejected by %d.%d.%d",
        !          4480:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4481:                break;
        !          4482:
        !          4483:        case RQCS_ABORT_MSG_FAILED:
        !          4484:                isp_prt(isp, ISP_LOGERR, "ABORT OPERATION rejected by %d.%d.%d",
        !          4485:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4486:                break;
        !          4487:
        !          4488:        case RQCS_REJECT_MSG_FAILED:
        !          4489:                isp_prt(isp, ISP_LOGERR, "MESSAGE REJECT rejected by %d.%d.%d",
        !          4490:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4491:                break;
        !          4492:
        !          4493:        case RQCS_NOP_MSG_FAILED:
        !          4494:                isp_prt(isp, ISP_LOGERR, "NOP rejected by %d.%d.%d",
        !          4495:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4496:                break;
        !          4497:
        !          4498:        case RQCS_PARITY_ERROR_MSG_FAILED:
        !          4499:                isp_prt(isp, ISP_LOGERR,
        !          4500:                    "MESSAGE PARITY ERROR rejected by %d.%d.%d",
        !          4501:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4502:                break;
        !          4503:
        !          4504:        case RQCS_DEVICE_RESET_MSG_FAILED:
        !          4505:                isp_prt(isp, ISP_LOGWARN,
        !          4506:                    "BUS DEVICE RESET rejected by %d.%d.%d",
        !          4507:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4508:                break;
        !          4509:
        !          4510:        case RQCS_ID_MSG_FAILED:
        !          4511:                isp_prt(isp, ISP_LOGERR, "IDENTIFY rejected by %d.%d.%d",
        !          4512:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4513:                break;
        !          4514:
        !          4515:        case RQCS_UNEXP_BUS_FREE:
        !          4516:                isp_prt(isp, ISP_LOGERR, "%d.%d.%d had an unexpected bus free",
        !          4517:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4518:                break;
        !          4519:
        !          4520:        case RQCS_DATA_UNDERRUN:
        !          4521:        {
        !          4522:                if (IS_FC(isp)) {
        !          4523:                        int ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
        !          4524:                        if (!ru_marked || sp->req_resid > XS_XFRLEN(xs)) {
        !          4525:                                isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs),
        !          4526:                                    XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid,
        !          4527:                                    (ru_marked)? "marked" : "not marked");
        !          4528:                                if (XS_NOERR(xs)) {
        !          4529:                                        XS_SETERR(xs, HBA_BOTCH);
        !          4530:                                }
        !          4531:                                return;
        !          4532:                        }
        !          4533:                }
        !          4534:                XS_RESID(xs) = sp->req_resid;
        !          4535:                if (XS_NOERR(xs)) {
        !          4536:                        XS_SETERR(xs, HBA_NOERROR);
        !          4537:                }
        !          4538:                return;
        !          4539:        }
        !          4540:
        !          4541:        case RQCS_XACT_ERR1:
        !          4542:                isp_prt(isp, ISP_LOGERR, xact1, XS_CHANNEL(xs),
        !          4543:                    XS_TGT(xs), XS_LUN(xs));
        !          4544:                break;
        !          4545:
        !          4546:        case RQCS_XACT_ERR2:
        !          4547:                isp_prt(isp, ISP_LOGERR, xact2,
        !          4548:                    XS_LUN(xs), XS_TGT(xs), XS_CHANNEL(xs));
        !          4549:                break;
        !          4550:
        !          4551:        case RQCS_XACT_ERR3:
        !          4552:                isp_prt(isp, ISP_LOGERR, xact3,
        !          4553:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4554:                break;
        !          4555:
        !          4556:        case RQCS_BAD_ENTRY:
        !          4557:                isp_prt(isp, ISP_LOGERR, "Invalid IOCB entry type detected");
        !          4558:                break;
        !          4559:
        !          4560:        case RQCS_QUEUE_FULL:
        !          4561:                isp_prt(isp, ISP_LOGDEBUG0,
        !          4562:                    "internal queues full for %d.%d.%d status 0x%x",
        !          4563:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), *XS_STSP(xs));
        !          4564:
        !          4565:                /*
        !          4566:                 * If QFULL or some other status byte is set, then this
        !          4567:                 * isn't an error, per se.
        !          4568:                 *
        !          4569:                 * Unfortunately, some QLogic f/w writers have, in
        !          4570:                 * some cases, ommitted to *set* status to QFULL.
        !          4571:                 *
        !          4572:
        !          4573:                if (*XS_STSP(xs) != SCSI_GOOD && XS_NOERR(xs)) {
        !          4574:                        XS_SETERR(xs, HBA_NOERROR);
        !          4575:                        return;
        !          4576:                }
        !          4577:
        !          4578:                 *
        !          4579:                 *
        !          4580:                 */
        !          4581:
        !          4582:                *XS_STSP(xs) = SCSI_QFULL;
        !          4583:                XS_SETERR(xs, HBA_NOERROR);
        !          4584:                return;
        !          4585:
        !          4586:        case RQCS_PHASE_SKIPPED:
        !          4587:                isp_prt(isp, ISP_LOGERR, pskip, XS_CHANNEL(xs),
        !          4588:                    XS_TGT(xs), XS_LUN(xs));
        !          4589:                break;
        !          4590:
        !          4591:        case RQCS_ARQS_FAILED:
        !          4592:                isp_prt(isp, ISP_LOGERR,
        !          4593:                    "Auto Request Sense failed for %d.%d.%d",
        !          4594:                    XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
        !          4595:                if (XS_NOERR(xs)) {
        !          4596:                        XS_SETERR(xs, HBA_ARQFAIL);
        !          4597:                }
        !          4598:                return;
        !          4599:
        !          4600:        case RQCS_WIDE_FAILED:
        !          4601:                isp_prt(isp, ISP_LOGERR,
        !          4602:                    "Wide Negotiation failed for %d.%d.%d",
        !          4603:                    XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
        !          4604:                if (IS_SCSI(isp)) {
        !          4605:                        sdparam *sdp = isp->isp_param;
        !          4606:                        sdp += XS_CHANNEL(xs);
        !          4607:                        sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_WIDE;
        !          4608:                        sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
        !          4609:                        isp->isp_update |= (1 << XS_CHANNEL(xs));
        !          4610:                }
        !          4611:                if (XS_NOERR(xs)) {
        !          4612:                        XS_SETERR(xs, HBA_NOERROR);
        !          4613:                }
        !          4614:                return;
        !          4615:
        !          4616:        case RQCS_SYNCXFER_FAILED:
        !          4617:                isp_prt(isp, ISP_LOGERR,
        !          4618:                    "SDTR Message failed for target %d.%d.%d",
        !          4619:                    XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
        !          4620:                if (IS_SCSI(isp)) {
        !          4621:                        sdparam *sdp = isp->isp_param;
        !          4622:                        sdp += XS_CHANNEL(xs);
        !          4623:                        sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_SYNC;
        !          4624:                        sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
        !          4625:                        isp->isp_update |= (1 << XS_CHANNEL(xs));
        !          4626:                }
        !          4627:                break;
        !          4628:
        !          4629:        case RQCS_LVD_BUSERR:
        !          4630:                isp_prt(isp, ISP_LOGERR,
        !          4631:                    "Bad LVD condition while talking to %d.%d.%d",
        !          4632:                    XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
        !          4633:                break;
        !          4634:
        !          4635:        case RQCS_PORT_UNAVAILABLE:
        !          4636:                /*
        !          4637:                 * No such port on the loop. Moral equivalent of SELTIMEO
        !          4638:                 */
        !          4639:        case RQCS_PORT_LOGGED_OUT:
        !          4640:                /*
        !          4641:                 * It was there (maybe)- treat as a selection timeout.
        !          4642:                 */
        !          4643:                if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE)
        !          4644:                        isp_prt(isp, ISP_LOGINFO,
        !          4645:                            "port unavailable for target %d", XS_TGT(xs));
        !          4646:                else
        !          4647:                        isp_prt(isp, ISP_LOGINFO,
        !          4648:                            "port logout for target %d", XS_TGT(xs));
        !          4649:                /*
        !          4650:                 * If we're on a local loop, force a LIP (which is overkill)
        !          4651:                 * to force a re-login of this unit. If we're on fabric,
        !          4652:                 * then we'll have to relogin as a matter of course.
        !          4653:                 */
        !          4654:                if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
        !          4655:                    FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
        !          4656:                        mbreg_t mbs;
        !          4657:                        mbs.param[0] = MBOX_INIT_LIP;
        !          4658:                        isp_mboxcmd_qnw(isp, &mbs, 1);
        !          4659:                }
        !          4660:
        !          4661:                /*
        !          4662:                 * Probably overkill.
        !          4663:                 */
        !          4664:                isp->isp_sendmarker = 1;
        !          4665:                FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
        !          4666:                isp_mark_getpdb_all(isp);
        !          4667:                isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
        !          4668:                if (XS_NOERR(xs)) {
        !          4669:                        XS_SETERR(xs, HBA_SELTIMEOUT);
        !          4670:                }
        !          4671:                return;
        !          4672:
        !          4673:        case RQCS_PORT_CHANGED:
        !          4674:                isp_prt(isp, ISP_LOGWARN,
        !          4675:                    "port changed for target %d", XS_TGT(xs));
        !          4676:                if (XS_NOERR(xs)) {
        !          4677:                        XS_SETERR(xs, HBA_SELTIMEOUT);
        !          4678:                }
        !          4679:                return;
        !          4680:
        !          4681:        case RQCS_PORT_BUSY:
        !          4682:                isp_prt(isp, ISP_LOGWARN,
        !          4683:                    "port busy for target %d", XS_TGT(xs));
        !          4684:                if (XS_NOERR(xs)) {
        !          4685:                        XS_SETERR(xs, HBA_TGTBSY);
        !          4686:                }
        !          4687:                return;
        !          4688:
        !          4689:        default:
        !          4690:                isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x",
        !          4691:                    sp->req_completion_status);
        !          4692:                break;
        !          4693:        }
        !          4694:        if (XS_NOERR(xs)) {
        !          4695:                XS_SETERR(xs, HBA_BOTCH);
        !          4696:        }
        !          4697: }
        !          4698:
        !          4699: static void
        !          4700: isp_fastpost_complete(struct ispsoftc *isp, u_int16_t fph)
        !          4701: {
        !          4702:        XS_T *xs;
        !          4703:
        !          4704:        if (fph == 0) {
        !          4705:                return;
        !          4706:        }
        !          4707:        xs = isp_find_xs(isp, fph);
        !          4708:        if (xs == NULL) {
        !          4709:                isp_prt(isp, ISP_LOGWARN,
        !          4710:                    "Command for fast post handle 0x%x not found", fph);
        !          4711:                return;
        !          4712:        }
        !          4713:        isp_destroy_handle(isp, fph);
        !          4714:
        !          4715:        /*
        !          4716:         * Since we don't have a result queue entry item,
        !          4717:         * we must believe that SCSI status is zero and
        !          4718:         * that all data transferred.
        !          4719:         */
        !          4720:        XS_SET_STATE_STAT(isp, xs, NULL);
        !          4721:        XS_RESID(xs) = 0;
        !          4722:        *XS_STSP(xs) = SCSI_GOOD;
        !          4723:        if (XS_XFRLEN(xs)) {
        !          4724:                ISP_DMAFREE(isp, xs, fph);
        !          4725:        }
        !          4726:        if (isp->isp_nactive)
        !          4727:                isp->isp_nactive--;
        !          4728:        isp->isp_fphccmplt++;
        !          4729:        isp_done(xs);
        !          4730: }
        !          4731:
        !          4732: static int
        !          4733: isp_mbox_continue(struct ispsoftc *isp)
        !          4734: {
        !          4735:        mbreg_t mbs;
        !          4736:        u_int16_t *ptr;
        !          4737:
        !          4738:        switch (isp->isp_lastmbxcmd) {
        !          4739:        case MBOX_WRITE_RAM_WORD:
        !          4740:        case MBOX_READ_RAM_WORD:
        !          4741:        case MBOX_READ_RAM_WORD_EXTENDED:
        !          4742:                break;
        !          4743:        default:
        !          4744:                return (1);
        !          4745:        }
        !          4746:        if (isp->isp_mboxtmp[0] != MBOX_COMMAND_COMPLETE) {
        !          4747:                isp->isp_mbxwrk0 = 0;
        !          4748:                return (-1);
        !          4749:        }
        !          4750:
        !          4751:
        !          4752:        /*
        !          4753:         * Clear the previous interrupt.
        !          4754:         */
        !          4755:        ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
        !          4756:        ISP_WRITE(isp, BIU_SEMA, 0);
        !          4757:
        !          4758:        /*
        !          4759:         * Continue with next word.
        !          4760:         */
        !          4761:        ptr = isp->isp_mbxworkp;
        !          4762:        switch (isp->isp_lastmbxcmd) {
        !          4763:        case MBOX_WRITE_RAM_WORD:
        !          4764:                mbs.param[2] = *ptr++;
        !          4765:                mbs.param[1] = isp->isp_mbxwrk1++;
        !          4766:                break;
        !          4767:        case MBOX_READ_RAM_WORD:
        !          4768:        case MBOX_READ_RAM_WORD_EXTENDED:
        !          4769:                *ptr++ = isp->isp_mboxtmp[2];
        !          4770:                mbs.param[1] = isp->isp_mbxwrk1++;
        !          4771:                break;
        !          4772:        }
        !          4773:        isp->isp_mbxworkp = ptr;
        !          4774:        mbs.param[0] = isp->isp_lastmbxcmd;
        !          4775:        isp->isp_mbxwrk0 -= 1;
        !          4776:        isp_mboxcmd_qnw(isp, &mbs, 0);
        !          4777:        return (0);
        !          4778: }
        !          4779:
        !          4780:
        !          4781: #define        HIBYT(x)                        ((x) >> 0x8)
        !          4782: #define        LOBYT(x)                        ((x)  & 0xff)
        !          4783: #define        ISPOPMAP(a, b)                  (((a) << 8) | (b))
        !          4784: static const u_int16_t mbpscsi[] = {
        !          4785:        ISPOPMAP(0x01, 0x01),   /* 0x00: MBOX_NO_OP */
        !          4786:        ISPOPMAP(0x1f, 0x01),   /* 0x01: MBOX_LOAD_RAM */
        !          4787:        ISPOPMAP(0x03, 0x01),   /* 0x02: MBOX_EXEC_FIRMWARE */
        !          4788:        ISPOPMAP(0x1f, 0x01),   /* 0x03: MBOX_DUMP_RAM */
        !          4789:        ISPOPMAP(0x07, 0x07),   /* 0x04: MBOX_WRITE_RAM_WORD */
        !          4790:        ISPOPMAP(0x03, 0x07),   /* 0x05: MBOX_READ_RAM_WORD */
        !          4791:        ISPOPMAP(0x3f, 0x3f),   /* 0x06: MBOX_MAILBOX_REG_TEST */
        !          4792:        ISPOPMAP(0x03, 0x07),   /* 0x07: MBOX_VERIFY_CHECKSUM   */
        !          4793:        ISPOPMAP(0x01, 0x0f),   /* 0x08: MBOX_ABOUT_FIRMWARE */
        !          4794:        ISPOPMAP(0x00, 0x00),   /* 0x09: */
        !          4795:        ISPOPMAP(0x00, 0x00),   /* 0x0a: */
        !          4796:        ISPOPMAP(0x00, 0x00),   /* 0x0b: */
        !          4797:        ISPOPMAP(0x00, 0x00),   /* 0x0c: */
        !          4798:        ISPOPMAP(0x00, 0x00),   /* 0x0d: */
        !          4799:        ISPOPMAP(0x01, 0x05),   /* 0x0e: MBOX_CHECK_FIRMWARE */
        !          4800:        ISPOPMAP(0x00, 0x00),   /* 0x0f: */
        !          4801:        ISPOPMAP(0x1f, 0x1f),   /* 0x10: MBOX_INIT_REQ_QUEUE */
        !          4802:        ISPOPMAP(0x3f, 0x3f),   /* 0x11: MBOX_INIT_RES_QUEUE */
        !          4803:        ISPOPMAP(0x0f, 0x0f),   /* 0x12: MBOX_EXECUTE_IOCB */
        !          4804:        ISPOPMAP(0x03, 0x03),   /* 0x13: MBOX_WAKE_UP   */
        !          4805:        ISPOPMAP(0x01, 0x3f),   /* 0x14: MBOX_STOP_FIRMWARE */
        !          4806:        ISPOPMAP(0x0f, 0x0f),   /* 0x15: MBOX_ABORT */
        !          4807:        ISPOPMAP(0x03, 0x03),   /* 0x16: MBOX_ABORT_DEVICE */
        !          4808:        ISPOPMAP(0x07, 0x07),   /* 0x17: MBOX_ABORT_TARGET */
        !          4809:        ISPOPMAP(0x07, 0x07),   /* 0x18: MBOX_BUS_RESET */
        !          4810:        ISPOPMAP(0x03, 0x07),   /* 0x19: MBOX_STOP_QUEUE */
        !          4811:        ISPOPMAP(0x03, 0x07),   /* 0x1a: MBOX_START_QUEUE */
        !          4812:        ISPOPMAP(0x03, 0x07),   /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
        !          4813:        ISPOPMAP(0x03, 0x07),   /* 0x1c: MBOX_ABORT_QUEUE */
        !          4814:        ISPOPMAP(0x03, 0x4f),   /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
        !          4815:        ISPOPMAP(0x00, 0x00),   /* 0x1e: */
        !          4816:        ISPOPMAP(0x01, 0x07),   /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
        !          4817:        ISPOPMAP(0x01, 0x07),   /* 0x20: MBOX_GET_INIT_SCSI_ID */
        !          4818:        ISPOPMAP(0x01, 0x07),   /* 0x21: MBOX_GET_SELECT_TIMEOUT */
        !          4819:        ISPOPMAP(0x01, 0xc7),   /* 0x22: MBOX_GET_RETRY_COUNT   */
        !          4820:        ISPOPMAP(0x01, 0x07),   /* 0x23: MBOX_GET_TAG_AGE_LIMIT */
        !          4821:        ISPOPMAP(0x01, 0x03),   /* 0x24: MBOX_GET_CLOCK_RATE */
        !          4822:        ISPOPMAP(0x01, 0x07),   /* 0x25: MBOX_GET_ACT_NEG_STATE */
        !          4823:        ISPOPMAP(0x01, 0x07),   /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */
        !          4824:        ISPOPMAP(0x01, 0x07),   /* 0x27: MBOX_GET_PCI_PARAMS */
        !          4825:        ISPOPMAP(0x03, 0x4f),   /* 0x28: MBOX_GET_TARGET_PARAMS */
        !          4826:        ISPOPMAP(0x03, 0x0f),   /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */
        !          4827:        ISPOPMAP(0x01, 0x07),   /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */
        !          4828:        ISPOPMAP(0x00, 0x00),   /* 0x2b: */
        !          4829:        ISPOPMAP(0x00, 0x00),   /* 0x2c: */
        !          4830:        ISPOPMAP(0x00, 0x00),   /* 0x2d: */
        !          4831:        ISPOPMAP(0x00, 0x00),   /* 0x2e: */
        !          4832:        ISPOPMAP(0x00, 0x00),   /* 0x2f: */
        !          4833:        ISPOPMAP(0x03, 0x03),   /* 0x30: MBOX_SET_INIT_SCSI_ID */
        !          4834:        ISPOPMAP(0x07, 0x07),   /* 0x31: MBOX_SET_SELECT_TIMEOUT */
        !          4835:        ISPOPMAP(0xc7, 0xc7),   /* 0x32: MBOX_SET_RETRY_COUNT   */
        !          4836:        ISPOPMAP(0x07, 0x07),   /* 0x33: MBOX_SET_TAG_AGE_LIMIT */
        !          4837:        ISPOPMAP(0x03, 0x03),   /* 0x34: MBOX_SET_CLOCK_RATE */
        !          4838:        ISPOPMAP(0x07, 0x07),   /* 0x35: MBOX_SET_ACT_NEG_STATE */
        !          4839:        ISPOPMAP(0x07, 0x07),   /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */
        !          4840:        ISPOPMAP(0x07, 0x07),   /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */
        !          4841:        ISPOPMAP(0x4f, 0x4f),   /* 0x38: MBOX_SET_TARGET_PARAMS */
        !          4842:        ISPOPMAP(0x0f, 0x0f),   /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */
        !          4843:        ISPOPMAP(0x07, 0x07),   /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */
        !          4844:        ISPOPMAP(0x00, 0x00),   /* 0x3b: */
        !          4845:        ISPOPMAP(0x00, 0x00),   /* 0x3c: */
        !          4846:        ISPOPMAP(0x00, 0x00),   /* 0x3d: */
        !          4847:        ISPOPMAP(0x00, 0x00),   /* 0x3e: */
        !          4848:        ISPOPMAP(0x00, 0x00),   /* 0x3f: */
        !          4849:        ISPOPMAP(0x01, 0x03),   /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */
        !          4850:        ISPOPMAP(0x3f, 0x01),   /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */
        !          4851:        ISPOPMAP(0x03, 0x07),   /* 0x42: MBOX_EXEC_BIOS_IOCB */
        !          4852:        ISPOPMAP(0x00, 0x00),   /* 0x43: */
        !          4853:        ISPOPMAP(0x00, 0x00),   /* 0x44: */
        !          4854:        ISPOPMAP(0x03, 0x03),   /* 0x45: SET SYSTEM PARAMETER */
        !          4855:        ISPOPMAP(0x01, 0x03),   /* 0x46: GET SYSTEM PARAMETER */
        !          4856:        ISPOPMAP(0x00, 0x00),   /* 0x47: */
        !          4857:        ISPOPMAP(0x01, 0xcf),   /* 0x48: GET SCAM CONFIGURATION */
        !          4858:        ISPOPMAP(0xcf, 0xcf),   /* 0x49: SET SCAM CONFIGURATION */
        !          4859:        ISPOPMAP(0x03, 0x03),   /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */
        !          4860:        ISPOPMAP(0x01, 0x03),   /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */
        !          4861:        ISPOPMAP(0x00, 0x00),   /* 0x4c: */
        !          4862:        ISPOPMAP(0x00, 0x00),   /* 0x4d: */
        !          4863:        ISPOPMAP(0x00, 0x00),   /* 0x4e: */
        !          4864:        ISPOPMAP(0x00, 0x00),   /* 0x4f: */
        !          4865:        ISPOPMAP(0xdf, 0xdf),   /* 0x50: LOAD RAM A64 */
        !          4866:        ISPOPMAP(0xdf, 0xdf),   /* 0x51: DUMP RAM A64 */
        !          4867:        ISPOPMAP(0xdf, 0xff),   /* 0x52: INITIALIZE REQUEST QUEUE A64 */
        !          4868:        ISPOPMAP(0xef, 0xff),   /* 0x53: INITIALIZE RESPONSE QUEUE A64 */
        !          4869:        ISPOPMAP(0xcf, 0x01),   /* 0x54: EXECUTE IOCB A64 */
        !          4870:        ISPOPMAP(0x07, 0x01),   /* 0x55: ENABLE TARGET MODE */
        !          4871:        ISPOPMAP(0x03, 0x0f),   /* 0x56: GET TARGET STATUS */
        !          4872:        ISPOPMAP(0x00, 0x00),   /* 0x57: */
        !          4873:        ISPOPMAP(0x00, 0x00),   /* 0x58: */
        !          4874:        ISPOPMAP(0x00, 0x00),   /* 0x59: */
        !          4875:        ISPOPMAP(0x03, 0x03),   /* 0x5a: SET DATA OVERRUN RECOVERY MODE */
        !          4876:        ISPOPMAP(0x01, 0x03),   /* 0x5b: GET DATA OVERRUN RECOVERY MODE */
        !          4877:        ISPOPMAP(0x0f, 0x0f),   /* 0x5c: SET HOST DATA */
        !          4878:        ISPOPMAP(0x01, 0x01)    /* 0x5d: GET NOST DATA */
        !          4879: };
        !          4880:
        !          4881: #ifdef SMALL_KERNEL
        !          4882: #define ISP_STRIPPED
        !          4883: #endif
        !          4884:
        !          4885: #ifndef        ISP_STRIPPED
        !          4886: static char *scsi_mbcmd_names[] = {
        !          4887:        "NO-OP",
        !          4888:        "LOAD RAM",
        !          4889:        "EXEC FIRMWARE",
        !          4890:        "DUMP RAM",
        !          4891:        "WRITE RAM WORD",
        !          4892:        "READ RAM WORD",
        !          4893:        "MAILBOX REG TEST",
        !          4894:        "VERIFY CHECKSUM",
        !          4895:        "ABOUT FIRMWARE",
        !          4896:        NULL,
        !          4897:        NULL,
        !          4898:        NULL,
        !          4899:        NULL,
        !          4900:        NULL,
        !          4901:        "CHECK FIRMWARE",
        !          4902:        NULL,
        !          4903:        "INIT REQUEST QUEUE",
        !          4904:        "INIT RESULT QUEUE",
        !          4905:        "EXECUTE IOCB",
        !          4906:        "WAKE UP",
        !          4907:        "STOP FIRMWARE",
        !          4908:        "ABORT",
        !          4909:        "ABORT DEVICE",
        !          4910:        "ABORT TARGET",
        !          4911:        "BUS RESET",
        !          4912:        "STOP QUEUE",
        !          4913:        "START QUEUE",
        !          4914:        "SINGLE STEP QUEUE",
        !          4915:        "ABORT QUEUE",
        !          4916:        "GET DEV QUEUE STATUS",
        !          4917:        NULL,
        !          4918:        "GET FIRMWARE STATUS",
        !          4919:        "GET INIT SCSI ID",
        !          4920:        "GET SELECT TIMEOUT",
        !          4921:        "GET RETRY COUNT",
        !          4922:        "GET TAG AGE LIMIT",
        !          4923:        "GET CLOCK RATE",
        !          4924:        "GET ACT NEG STATE",
        !          4925:        "GET ASYNC DATA SETUP TIME",
        !          4926:        "GET PCI PARAMS",
        !          4927:        "GET TARGET PARAMS",
        !          4928:        "GET DEV QUEUE PARAMS",
        !          4929:        "GET RESET DELAY PARAMS",
        !          4930:        NULL,
        !          4931:        NULL,
        !          4932:        NULL,
        !          4933:        NULL,
        !          4934:        NULL,
        !          4935:        "SET INIT SCSI ID",
        !          4936:        "SET SELECT TIMEOUT",
        !          4937:        "SET RETRY COUNT",
        !          4938:        "SET TAG AGE LIMIT",
        !          4939:        "SET CLOCK RATE",
        !          4940:        "SET ACT NEG STATE",
        !          4941:        "SET ASYNC DATA SETUP TIME",
        !          4942:        "SET PCI CONTROL PARAMS",
        !          4943:        "SET TARGET PARAMS",
        !          4944:        "SET DEV QUEUE PARAMS",
        !          4945:        "SET RESET DELAY PARAMS",
        !          4946:        NULL,
        !          4947:        NULL,
        !          4948:        NULL,
        !          4949:        NULL,
        !          4950:        NULL,
        !          4951:        "RETURN BIOS BLOCK ADDR",
        !          4952:        "WRITE FOUR RAM WORDS",
        !          4953:        "EXEC BIOS IOCB",
        !          4954:        NULL,
        !          4955:        NULL,
        !          4956:        "SET SYSTEM PARAMETER",
        !          4957:        "GET SYSTEM PARAMETER",
        !          4958:        NULL,
        !          4959:        "GET SCAM CONFIGURATION",
        !          4960:        "SET SCAM CONFIGURATION",
        !          4961:        "SET FIRMWARE FEATURES",
        !          4962:        "GET FIRMWARE FEATURES",
        !          4963:        NULL,
        !          4964:        NULL,
        !          4965:        NULL,
        !          4966:        NULL,
        !          4967:        "LOAD RAM A64",
        !          4968:        "DUMP RAM A64",
        !          4969:        "INITIALIZE REQUEST QUEUE A64",
        !          4970:        "INITIALIZE RESPONSE QUEUE A64",
        !          4971:        "EXECUTE IOCB A64",
        !          4972:        "ENABLE TARGET MODE",
        !          4973:        "GET TARGET MODE STATE",
        !          4974:        NULL,
        !          4975:        NULL,
        !          4976:        NULL,
        !          4977:        "SET DATA OVERRUN RECOVERY MODE",
        !          4978:        "GET DATA OVERRUN RECOVERY MODE",
        !          4979:        "SET HOST DATA",
        !          4980:        "GET NOST DATA",
        !          4981: };
        !          4982: #endif
        !          4983:
        !          4984: static const u_int16_t mbpfc[] = {
        !          4985:        ISPOPMAP(0x01, 0x01),   /* 0x00: MBOX_NO_OP */
        !          4986:        ISPOPMAP(0x1f, 0x01),   /* 0x01: MBOX_LOAD_RAM */
        !          4987:        ISPOPMAP(0x03, 0x01),   /* 0x02: MBOX_EXEC_FIRMWARE */
        !          4988:        ISPOPMAP(0xdf, 0x01),   /* 0x03: MBOX_DUMP_RAM */
        !          4989:        ISPOPMAP(0x07, 0x07),   /* 0x04: MBOX_WRITE_RAM_WORD */
        !          4990:        ISPOPMAP(0x03, 0x07),   /* 0x05: MBOX_READ_RAM_WORD */
        !          4991:        ISPOPMAP(0xff, 0xff),   /* 0x06: MBOX_MAILBOX_REG_TEST */
        !          4992:        ISPOPMAP(0x03, 0x05),   /* 0x07: MBOX_VERIFY_CHECKSUM   */
        !          4993:        ISPOPMAP(0x01, 0x4f),   /* 0x08: MBOX_ABOUT_FIRMWARE */
        !          4994:        ISPOPMAP(0xdf, 0x01),   /* 0x09: LOAD RAM */
        !          4995:        ISPOPMAP(0xdf, 0x01),   /* 0x0a: DUMP RAM */
        !          4996:        ISPOPMAP(0x00, 0x00),   /* 0x0b: */
        !          4997:        ISPOPMAP(0x00, 0x00),   /* 0x0c: */
        !          4998:        ISPOPMAP(0x00, 0x00),   /* 0x0d: */
        !          4999:        ISPOPMAP(0x01, 0x05),   /* 0x0e: MBOX_CHECK_FIRMWARE */
        !          5000:        ISPOPMAP(0x03, 0x07),   /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED(1) */
        !          5001:        ISPOPMAP(0x1f, 0x11),   /* 0x10: MBOX_INIT_REQ_QUEUE */
        !          5002:        ISPOPMAP(0x2f, 0x21),   /* 0x11: MBOX_INIT_RES_QUEUE */
        !          5003:        ISPOPMAP(0x0f, 0x01),   /* 0x12: MBOX_EXECUTE_IOCB */
        !          5004:        ISPOPMAP(0x03, 0x03),   /* 0x13: MBOX_WAKE_UP   */
        !          5005:        ISPOPMAP(0x01, 0xff),   /* 0x14: MBOX_STOP_FIRMWARE */
        !          5006:        ISPOPMAP(0x4f, 0x01),   /* 0x15: MBOX_ABORT */
        !          5007:        ISPOPMAP(0x07, 0x01),   /* 0x16: MBOX_ABORT_DEVICE */
        !          5008:        ISPOPMAP(0x07, 0x01),   /* 0x17: MBOX_ABORT_TARGET */
        !          5009:        ISPOPMAP(0x03, 0x03),   /* 0x18: MBOX_BUS_RESET */
        !          5010:        ISPOPMAP(0x07, 0x05),   /* 0x19: MBOX_STOP_QUEUE */
        !          5011:        ISPOPMAP(0x07, 0x05),   /* 0x1a: MBOX_START_QUEUE */
        !          5012:        ISPOPMAP(0x07, 0x05),   /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
        !          5013:        ISPOPMAP(0x07, 0x05),   /* 0x1c: MBOX_ABORT_QUEUE */
        !          5014:        ISPOPMAP(0x07, 0x03),   /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
        !          5015:        ISPOPMAP(0x00, 0x00),   /* 0x1e: */
        !          5016:        ISPOPMAP(0x01, 0x07),   /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
        !          5017:        ISPOPMAP(0x01, 0x4f),   /* 0x20: MBOX_GET_LOOP_ID */
        !          5018:        ISPOPMAP(0x00, 0x00),   /* 0x21: */
        !          5019:        ISPOPMAP(0x01, 0x07),   /* 0x22: MBOX_GET_RETRY_COUNT   */
        !          5020:        ISPOPMAP(0x00, 0x00),   /* 0x23: */
        !          5021:        ISPOPMAP(0x00, 0x00),   /* 0x24: */
        !          5022:        ISPOPMAP(0x00, 0x00),   /* 0x25: */
        !          5023:        ISPOPMAP(0x00, 0x00),   /* 0x26: */
        !          5024:        ISPOPMAP(0x00, 0x00),   /* 0x27: */
        !          5025:        ISPOPMAP(0x01, 0x03),   /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
        !          5026:        ISPOPMAP(0x03, 0x07),   /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
        !          5027:        ISPOPMAP(0x00, 0x00),   /* 0x2a: */
        !          5028:        ISPOPMAP(0x00, 0x00),   /* 0x2b: */
        !          5029:        ISPOPMAP(0x00, 0x00),   /* 0x2c: */
        !          5030:        ISPOPMAP(0x00, 0x00),   /* 0x2d: */
        !          5031:        ISPOPMAP(0x00, 0x00),   /* 0x2e: */
        !          5032:        ISPOPMAP(0x00, 0x00),   /* 0x2f: */
        !          5033:        ISPOPMAP(0x00, 0x00),   /* 0x30: */
        !          5034:        ISPOPMAP(0x00, 0x00),   /* 0x31: */
        !          5035:        ISPOPMAP(0x07, 0x07),   /* 0x32: MBOX_SET_RETRY_COUNT   */
        !          5036:        ISPOPMAP(0x00, 0x00),   /* 0x33: */
        !          5037:        ISPOPMAP(0x00, 0x00),   /* 0x34: */
        !          5038:        ISPOPMAP(0x00, 0x00),   /* 0x35: */
        !          5039:        ISPOPMAP(0x00, 0x00),   /* 0x36: */
        !          5040:        ISPOPMAP(0x00, 0x00),   /* 0x37: */
        !          5041:        ISPOPMAP(0x0f, 0x01),   /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
        !          5042:        ISPOPMAP(0x0f, 0x07),   /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
        !          5043:        ISPOPMAP(0x00, 0x00),   /* 0x3a: */
        !          5044:        ISPOPMAP(0x00, 0x00),   /* 0x3b: */
        !          5045:        ISPOPMAP(0x00, 0x00),   /* 0x3c: */
        !          5046:        ISPOPMAP(0x00, 0x00),   /* 0x3d: */
        !          5047:        ISPOPMAP(0x00, 0x00),   /* 0x3e: */
        !          5048:        ISPOPMAP(0x00, 0x00),   /* 0x3f: */
        !          5049:        ISPOPMAP(0x03, 0x01),   /* 0x40: MBOX_LOOP_PORT_BYPASS */
        !          5050:        ISPOPMAP(0x03, 0x01),   /* 0x41: MBOX_LOOP_PORT_ENABLE */
        !          5051:        ISPOPMAP(0x03, 0x07),   /* 0x42: MBOX_GET_RESOURCE_COUNTS */
        !          5052:        ISPOPMAP(0x01, 0x01),   /* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */
        !          5053:        ISPOPMAP(0x00, 0x00),   /* 0x44: */
        !          5054:        ISPOPMAP(0x00, 0x00),   /* 0x45: */
        !          5055:        ISPOPMAP(0x00, 0x00),   /* 0x46: */
        !          5056:        ISPOPMAP(0xcf, 0x03),   /* 0x47: GET PORT_DATABASE ENHANCED */
        !          5057:        ISPOPMAP(0x00, 0x00),   /* 0x48: */
        !          5058:        ISPOPMAP(0x00, 0x00),   /* 0x49: */
        !          5059:        ISPOPMAP(0x00, 0x00),   /* 0x4a: */
        !          5060:        ISPOPMAP(0x00, 0x00),   /* 0x4b: */
        !          5061:        ISPOPMAP(0x00, 0x00),   /* 0x4c: */
        !          5062:        ISPOPMAP(0x00, 0x00),   /* 0x4d: */
        !          5063:        ISPOPMAP(0x00, 0x00),   /* 0x4e: */
        !          5064:        ISPOPMAP(0x00, 0x00),   /* 0x4f: */
        !          5065:        ISPOPMAP(0x00, 0x00),   /* 0x50: */
        !          5066:        ISPOPMAP(0x00, 0x00),   /* 0x51: */
        !          5067:        ISPOPMAP(0x00, 0x00),   /* 0x52: */
        !          5068:        ISPOPMAP(0x00, 0x00),   /* 0x53: */
        !          5069:        ISPOPMAP(0xcf, 0x01),   /* 0x54: EXECUTE IOCB A64 */
        !          5070:        ISPOPMAP(0x00, 0x00),   /* 0x55: */
        !          5071:        ISPOPMAP(0x00, 0x00),   /* 0x56: */
        !          5072:        ISPOPMAP(0x00, 0x00),   /* 0x57: */
        !          5073:        ISPOPMAP(0x00, 0x00),   /* 0x58: */
        !          5074:        ISPOPMAP(0x00, 0x00),   /* 0x59: */
        !          5075:        ISPOPMAP(0x00, 0x00),   /* 0x5a: */
        !          5076:        ISPOPMAP(0x03, 0x01),   /* 0x5b: MBOX_DRIVER_HEARTBEAT */
        !          5077:        ISPOPMAP(0xcf, 0x01),   /* 0x5c: MBOX_FW_HEARTBEAT */
        !          5078:        ISPOPMAP(0x07, 0x03),   /* 0x5d: MBOX_GET_SET_DATA_RATE */
        !          5079:        ISPOPMAP(0x00, 0x00),   /* 0x5e: */
        !          5080:        ISPOPMAP(0x00, 0x00),   /* 0x5f: */
        !          5081:        ISPOPMAP(0xfd, 0x31),   /* 0x60: MBOX_INIT_FIRMWARE */
        !          5082:        ISPOPMAP(0x00, 0x00),   /* 0x61: */
        !          5083:        ISPOPMAP(0x01, 0x01),   /* 0x62: MBOX_INIT_LIP */
        !          5084:        ISPOPMAP(0xcd, 0x03),   /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
        !          5085:        ISPOPMAP(0xcf, 0x01),   /* 0x64: MBOX_GET_PORT_DB */
        !          5086:        ISPOPMAP(0x07, 0x01),   /* 0x65: MBOX_CLEAR_ACA */
        !          5087:        ISPOPMAP(0x07, 0x01),   /* 0x66: MBOX_TARGET_RESET */
        !          5088:        ISPOPMAP(0x07, 0x01),   /* 0x67: MBOX_CLEAR_TASK_SET */
        !          5089:        ISPOPMAP(0x07, 0x01),   /* 0x68: MBOX_ABORT_TASK_SET */
        !          5090:        ISPOPMAP(0x01, 0x07),   /* 0x69: MBOX_GET_FW_STATE */
        !          5091:        ISPOPMAP(0x03, 0xcf),   /* 0x6a: MBOX_GET_PORT_NAME */
        !          5092:        ISPOPMAP(0xcf, 0x01),   /* 0x6b: MBOX_GET_LINK_STATUS */
        !          5093:        ISPOPMAP(0x0f, 0x01),   /* 0x6c: MBOX_INIT_LIP_RESET */
        !          5094:        ISPOPMAP(0x00, 0x00),   /* 0x6d: */
        !          5095:        ISPOPMAP(0xcf, 0x03),   /* 0x6e: MBOX_SEND_SNS */
        !          5096:        ISPOPMAP(0x0f, 0x07),   /* 0x6f: MBOX_FABRIC_LOGIN */
        !          5097:        ISPOPMAP(0x03, 0x01),   /* 0x70: MBOX_SEND_CHANGE_REQUEST */
        !          5098:        ISPOPMAP(0x03, 0x03),   /* 0x71: MBOX_FABRIC_LOGOUT */
        !          5099:        ISPOPMAP(0x0f, 0x0f),   /* 0x72: MBOX_INIT_LIP_LOGIN */
        !          5100:        ISPOPMAP(0x00, 0x00),   /* 0x73: */
        !          5101:        ISPOPMAP(0x07, 0x01),   /* 0x74: LOGIN LOOP PORT */
        !          5102:        ISPOPMAP(0xcf, 0x03),   /* 0x75: GET PORT/NODE NAME LIST */
        !          5103:        ISPOPMAP(0x4f, 0x01),   /* 0x76: SET VENDOR ID */
        !          5104:        ISPOPMAP(0xcd, 0x01),   /* 0x77: INITIALIZE IP MAILBOX */
        !          5105:        ISPOPMAP(0x00, 0x00),   /* 0x78: */
        !          5106:        ISPOPMAP(0x00, 0x00),   /* 0x79: */
        !          5107:        ISPOPMAP(0x00, 0x00),   /* 0x7a: */
        !          5108:        ISPOPMAP(0x00, 0x00),   /* 0x7b: */
        !          5109:        ISPOPMAP(0x4f, 0x03),   /* 0x7c: Get ID List */
        !          5110:        ISPOPMAP(0xcf, 0x01),   /* 0x7d: SEND LFA */
        !          5111:        ISPOPMAP(0x07, 0x01)    /* 0x7e: Lun RESET */
        !          5112: };
        !          5113: /*
        !          5114:  * Footnotes
        !          5115:  *
        !          5116:  * (1): this sets bits 21..16 in mailbox register #8, which we nominally
        !          5117:  *     do not access at this time in the core driver. The caller is
        !          5118:  *     responsible for setting this register first (Gross!).
        !          5119:  */
        !          5120:
        !          5121: #ifndef        ISP_STRIPPED
        !          5122: static char *fc_mbcmd_names[] = {
        !          5123:        "NO-OP",
        !          5124:        "LOAD RAM",
        !          5125:        "EXEC FIRMWARE",
        !          5126:        "DUMP RAM",
        !          5127:        "WRITE RAM WORD",
        !          5128:        "READ RAM WORD",
        !          5129:        "MAILBOX REG TEST",
        !          5130:        "VERIFY CHECKSUM",
        !          5131:        "ABOUT FIRMWARE",
        !          5132:        "LOAD RAM",
        !          5133:        "DUMP RAM",
        !          5134:        NULL,
        !          5135:        NULL,
        !          5136:        "READ RAM WORD EXTENDED",
        !          5137:        "CHECK FIRMWARE",
        !          5138:        NULL,
        !          5139:        "INIT REQUEST QUEUE",
        !          5140:        "INIT RESULT QUEUE",
        !          5141:        "EXECUTE IOCB",
        !          5142:        "WAKE UP",
        !          5143:        "STOP FIRMWARE",
        !          5144:        "ABORT",
        !          5145:        "ABORT DEVICE",
        !          5146:        "ABORT TARGET",
        !          5147:        "BUS RESET",
        !          5148:        "STOP QUEUE",
        !          5149:        "START QUEUE",
        !          5150:        "SINGLE STEP QUEUE",
        !          5151:        "ABORT QUEUE",
        !          5152:        "GET DEV QUEUE STATUS",
        !          5153:        NULL,
        !          5154:        "GET FIRMWARE STATUS",
        !          5155:        "GET LOOP ID",
        !          5156:        NULL,
        !          5157:        "GET RETRY COUNT",
        !          5158:        NULL,
        !          5159:        NULL,
        !          5160:        NULL,
        !          5161:        NULL,
        !          5162:        NULL,
        !          5163:        "GET FIRMWARE OPTIONS",
        !          5164:        "GET PORT QUEUE PARAMS",
        !          5165:        NULL,
        !          5166:        NULL,
        !          5167:        NULL,
        !          5168:        NULL,
        !          5169:        NULL,
        !          5170:        NULL,
        !          5171:        NULL,
        !          5172:        NULL,
        !          5173:        "SET RETRY COUNT",
        !          5174:        NULL,
        !          5175:        NULL,
        !          5176:        NULL,
        !          5177:        NULL,
        !          5178:        NULL,
        !          5179:        "SET FIRMWARE OPTIONS",
        !          5180:        "SET PORT QUEUE PARAMS",
        !          5181:        NULL,
        !          5182:        NULL,
        !          5183:        NULL,
        !          5184:        NULL,
        !          5185:        NULL,
        !          5186:        NULL,
        !          5187:        "LOOP PORT BYPASS",
        !          5188:        "LOOP PORT ENABLE",
        !          5189:        "GET RESOURCE COUNTS",
        !          5190:        "REQUEST NON PARTICIPATING MODE",
        !          5191:        NULL,
        !          5192:        NULL,
        !          5193:        NULL,
        !          5194:        "GET PORT DATABASE,, ENHANCED",
        !          5195:        NULL,
        !          5196:        NULL,
        !          5197:        NULL,
        !          5198:        NULL,
        !          5199:        NULL,
        !          5200:        NULL,
        !          5201:        NULL,
        !          5202:        NULL,
        !          5203:        NULL,
        !          5204:        NULL,
        !          5205:        NULL,
        !          5206:        NULL,
        !          5207:        "EXECUTE IOCB A64",
        !          5208:        NULL,
        !          5209:        NULL,
        !          5210:        NULL,
        !          5211:        NULL,
        !          5212:        NULL,
        !          5213:        NULL,
        !          5214:        "DRIVER HEARTBEAT",
        !          5215:        NULL,
        !          5216:        "GET/SET DATA RATE",
        !          5217:        NULL,
        !          5218:        NULL,
        !          5219:        "INIT FIRMWARE",
        !          5220:        NULL,
        !          5221:        "INIT LIP",
        !          5222:        "GET FC-AL POSITION MAP",
        !          5223:        "GET PORT DATABASE",
        !          5224:        "CLEAR ACA",
        !          5225:        "TARGET RESET",
        !          5226:        "CLEAR TASK SET",
        !          5227:        "ABORT TASK SET",
        !          5228:        "GET FW STATE",
        !          5229:        "GET PORT NAME",
        !          5230:        "GET LINK STATUS",
        !          5231:        "INIT LIP RESET",
        !          5232:        NULL,
        !          5233:        "SEND SNS",
        !          5234:        "FABRIC LOGIN",
        !          5235:        "SEND CHANGE REQUEST",
        !          5236:        "FABRIC LOGOUT",
        !          5237:        "INIT LIP LOGIN",
        !          5238:        NULL,
        !          5239:        "LOGIN LOOP PORT",
        !          5240:        "GET PORT/NODE NAME LIST",
        !          5241:        "SET VENDOR ID",
        !          5242:        "INITIALIZE IP MAILBOX",
        !          5243:        NULL,
        !          5244:        NULL,
        !          5245:        NULL,
        !          5246:        NULL,
        !          5247:        "Get ID List",
        !          5248:        "SEND LFA",
        !          5249:        "Lun RESET"
        !          5250: };
        !          5251: #endif
        !          5252:
        !          5253: static void
        !          5254: isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay)
        !          5255: {
        !          5256:        unsigned int lim, ibits, obits, box, opcode;
        !          5257:        const u_int16_t *mcp;
        !          5258:
        !          5259:        if (IS_FC(isp)) {
        !          5260:                mcp = mbpfc;
        !          5261:                lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
        !          5262:        } else {
        !          5263:                mcp = mbpscsi;
        !          5264:                lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
        !          5265:        }
        !          5266:        opcode = mbp->param[0];
        !          5267:        ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp);
        !          5268:        obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp);
        !          5269:        for (box = 0; box < MAX_MAILBOX; box++) {
        !          5270:                if (ibits & (1 << box)) {
        !          5271:                        ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
        !          5272:                }
        !          5273:                if (nodelay == 0) {
        !          5274:                        isp->isp_mboxtmp[box] = mbp->param[box] = 0;
        !          5275:                }
        !          5276:        }
        !          5277:        if (nodelay == 0) {
        !          5278:                isp->isp_lastmbxcmd = opcode;
        !          5279:                isp->isp_obits = obits;
        !          5280:                isp->isp_mboxbsy = 1;
        !          5281:        }
        !          5282:        ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
        !          5283:        /*
        !          5284:         * Oddly enough, if we're not delaying for an answer,
        !          5285:         * delay a bit to give the f/w a chance to pick up the
        !          5286:         * command.
        !          5287:         */
        !          5288:        if (nodelay) {
        !          5289:                USEC_DELAY(1000);
        !          5290:        }
        !          5291: }
        !          5292:
        !          5293: static void
        !          5294: isp_mboxcmd(struct ispsoftc *isp, mbreg_t *mbp, int logmask)
        !          5295: {
        !          5296:        char *cname, *xname, tname[16], mname[16];
        !          5297:        unsigned int lim, ibits, obits, box, opcode;
        !          5298:        const u_int16_t *mcp;
        !          5299:
        !          5300:        if (IS_FC(isp)) {
        !          5301:                mcp = mbpfc;
        !          5302:                lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
        !          5303:        } else {
        !          5304:                mcp = mbpscsi;
        !          5305:                lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
        !          5306:        }
        !          5307:
        !          5308:        if ((opcode = mbp->param[0]) >= lim) {
        !          5309:                mbp->param[0] = MBOX_INVALID_COMMAND;
        !          5310:                isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
        !          5311:                return;
        !          5312:        }
        !          5313:
        !          5314:        ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp);
        !          5315:        obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp);
        !          5316:
        !          5317:        if (ibits == 0 && obits == 0) {
        !          5318:                mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
        !          5319:                isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
        !          5320:                return;
        !          5321:        }
        !          5322:
        !          5323:        /*
        !          5324:         * Get exclusive usage of mailbox registers.
        !          5325:         */
        !          5326:        MBOX_ACQUIRE(isp);
        !          5327:
        !          5328:        for (box = 0; box < MAX_MAILBOX; box++) {
        !          5329:                if (ibits & (1 << box)) {
        !          5330:                        ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
        !          5331:                }
        !          5332:                isp->isp_mboxtmp[box] = mbp->param[box] = 0;
        !          5333:        }
        !          5334:
        !          5335:        isp->isp_lastmbxcmd = opcode;
        !          5336:
        !          5337:        /*
        !          5338:         * We assume that we can't overwrite a previous command.
        !          5339:         */
        !          5340:        isp->isp_obits = obits;
        !          5341:        isp->isp_mboxbsy = 1;
        !          5342:
        !          5343:        /*
        !          5344:         * Set Host Interrupt condition so that RISC will pick up mailbox regs.
        !          5345:         */
        !          5346:        ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
        !          5347:
        !          5348:        /*
        !          5349:         * While we haven't finished the command, spin our wheels here.
        !          5350:         */
        !          5351:        MBOX_WAIT_COMPLETE(isp);
        !          5352:
        !          5353:        if (isp->isp_mboxbsy) {
        !          5354:                /*
        !          5355:                 * Command timed out.
        !          5356:                 */
        !          5357:                isp->isp_mboxbsy = 0;
        !          5358:                MBOX_RELEASE(isp);
        !          5359:                return;
        !          5360:        }
        !          5361:
        !          5362:        /*
        !          5363:         * Copy back output registers.
        !          5364:         */
        !          5365:        for (box = 0; box < MAX_MAILBOX; box++) {
        !          5366:                if (obits & (1 << box)) {
        !          5367:                        mbp->param[box] = isp->isp_mboxtmp[box];
        !          5368:                }
        !          5369:        }
        !          5370:
        !          5371:        MBOX_RELEASE(isp);
        !          5372:
        !          5373:        if (logmask == 0 || opcode == MBOX_EXEC_FIRMWARE) {
        !          5374:                return;
        !          5375:        }
        !          5376: #ifdef ISP_STRIPPED
        !          5377:        cname = NULL;
        !          5378: #else
        !          5379:        cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode];
        !          5380: #endif
        !          5381:        if (cname == NULL) {
        !          5382:                cname = tname;
        !          5383:                SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
        !          5384:        }
        !          5385:
        !          5386:        /*
        !          5387:         * Just to be chatty here...
        !          5388:         */
        !          5389:        xname = NULL;
        !          5390:        switch (mbp->param[0]) {
        !          5391:        case MBOX_COMMAND_COMPLETE:
        !          5392:                break;
        !          5393:        case MBOX_INVALID_COMMAND:
        !          5394:                if (logmask & MBLOGMASK(MBOX_COMMAND_COMPLETE))
        !          5395:                        xname = "INVALID COMMAND";
        !          5396:                break;
        !          5397:        case MBOX_HOST_INTERFACE_ERROR:
        !          5398:                if (logmask & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR))
        !          5399:                        xname = "HOST INTERFACE ERROR";
        !          5400:                break;
        !          5401:        case MBOX_TEST_FAILED:
        !          5402:                if (logmask & MBLOGMASK(MBOX_TEST_FAILED))
        !          5403:                        xname = "TEST FAILED";
        !          5404:                break;
        !          5405:        case MBOX_COMMAND_ERROR:
        !          5406:                if (logmask & MBLOGMASK(MBOX_COMMAND_ERROR))
        !          5407:                        xname = "COMMAND ERROR";
        !          5408:                break;
        !          5409:        case MBOX_COMMAND_PARAM_ERROR:
        !          5410:                if (logmask & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR))
        !          5411:                        xname = "COMMAND PARAMETER ERROR";
        !          5412:                break;
        !          5413:        case MBOX_LOOP_ID_USED:
        !          5414:                if (logmask & MBLOGMASK(MBOX_LOOP_ID_USED))
        !          5415:                        xname = "LOOP ID ALREADY IN USE";
        !          5416:                break;
        !          5417:        case MBOX_PORT_ID_USED:
        !          5418:                if (logmask & MBLOGMASK(MBOX_PORT_ID_USED))
        !          5419:                        xname = "PORT ID ALREADY IN USE";
        !          5420:                break;
        !          5421:        case MBOX_ALL_IDS_USED:
        !          5422:                if (logmask & MBLOGMASK(MBOX_ALL_IDS_USED))
        !          5423:                        xname = "ALL LOOP IDS IN USE";
        !          5424:                break;
        !          5425:        case 0:         /* special case */
        !          5426:                xname = "TIMEOUT";
        !          5427:                break;
        !          5428:        default:
        !          5429:                SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
        !          5430:                xname = mname;
        !          5431:                break;
        !          5432:        }
        !          5433:        if (xname)
        !          5434:                isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s)",
        !          5435:                    cname, xname);
        !          5436: }
        !          5437:
        !          5438: static void
        !          5439: isp_fw_state(struct ispsoftc *isp)
        !          5440: {
        !          5441:        if (IS_FC(isp)) {
        !          5442:                mbreg_t mbs;
        !          5443:                fcparam *fcp = isp->isp_param;
        !          5444:
        !          5445:                mbs.param[0] = MBOX_GET_FW_STATE;
        !          5446:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          5447:                if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
        !          5448:                        fcp->isp_fwstate = mbs.param[1];
        !          5449:                }
        !          5450:        }
        !          5451: }
        !          5452:
        !          5453: static void
        !          5454: isp_update(struct ispsoftc *isp)
        !          5455: {
        !          5456:        int bus, upmask;
        !          5457:
        !          5458:        for (bus = 0, upmask = isp->isp_update; upmask != 0; bus++) {
        !          5459:                if (upmask & (1 << bus)) {
        !          5460:                        isp_update_bus(isp, bus);
        !          5461:                }
        !          5462:                upmask &= ~(1 << bus);
        !          5463:        }
        !          5464: }
        !          5465:
        !          5466: static void
        !          5467: isp_update_bus(struct ispsoftc *isp, int bus)
        !          5468: {
        !          5469:        int tgt;
        !          5470:        mbreg_t mbs;
        !          5471:        sdparam *sdp;
        !          5472:
        !          5473:        isp->isp_update &= ~(1 << bus);
        !          5474:        if (IS_FC(isp)) {
        !          5475:                /*
        !          5476:                 * There are no 'per-bus' settings for Fibre Channel.
        !          5477:                 */
        !          5478:                return;
        !          5479:        }
        !          5480:        sdp = isp->isp_param;
        !          5481:        sdp += bus;
        !          5482:
        !          5483:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          5484:                u_int16_t flags, period, offset;
        !          5485:                int get;
        !          5486:
        !          5487:                if (sdp->isp_devparam[tgt].dev_enable == 0) {
        !          5488:                        sdp->isp_devparam[tgt].dev_update = 0;
        !          5489:                        sdp->isp_devparam[tgt].dev_refresh = 0;
        !          5490:                        isp_prt(isp, ISP_LOGDEBUG0,
        !          5491:                            "skipping target %d bus %d update", tgt, bus);
        !          5492:                        continue;
        !          5493:                }
        !          5494:                /*
        !          5495:                 * If the goal is to update the status of the device,
        !          5496:                 * take what's in goal_flags and try and set the device
        !          5497:                 * toward that. Otherwise, if we're just refreshing the
        !          5498:                 * current device state, get the current parameters.
        !          5499:                 */
        !          5500:
        !          5501:                /*
        !          5502:                 * Refresh overrides set
        !          5503:                 */
        !          5504:                if (sdp->isp_devparam[tgt].dev_refresh) {
        !          5505:                        mbs.param[0] = MBOX_GET_TARGET_PARAMS;
        !          5506:                        sdp->isp_devparam[tgt].dev_refresh = 0;
        !          5507:                        get = 1;
        !          5508:                } else if (sdp->isp_devparam[tgt].dev_update) {
        !          5509:                        mbs.param[0] = MBOX_SET_TARGET_PARAMS;
        !          5510:                        /*
        !          5511:                         * Make sure goal_flags has "Renegotiate on Error"
        !          5512:                         * on and "Freeze Queue on Error" off.
        !          5513:                         */
        !          5514:                        sdp->isp_devparam[tgt].goal_flags |= DPARM_RENEG;
        !          5515:                        sdp->isp_devparam[tgt].goal_flags &= ~DPARM_QFRZ;
        !          5516:
        !          5517:                        mbs.param[2] = sdp->isp_devparam[tgt].goal_flags;
        !          5518:
        !          5519:                        /*
        !          5520:                         * Insist that PARITY must be enabled
        !          5521:                         * if SYNC or WIDE is enabled.
        !          5522:                         */
        !          5523:                        if ((mbs.param[2] & (DPARM_SYNC|DPARM_WIDE)) != 0) {
        !          5524:                                mbs.param[2] |= DPARM_PARITY;
        !          5525:                        }
        !          5526:
        !          5527:                        if ((mbs.param[2] & DPARM_SYNC) == 0) {
        !          5528:                                mbs.param[3] = 0;
        !          5529:                        } else {
        !          5530:                                mbs.param[3] =
        !          5531:                                    (sdp->isp_devparam[tgt].goal_offset << 8) |
        !          5532:                                    (sdp->isp_devparam[tgt].goal_period);
        !          5533:                        }
        !          5534:                        /*
        !          5535:                         * A command completion later that has
        !          5536:                         * RQSTF_NEGOTIATION set can cause
        !          5537:                         * the dev_refresh/announce cycle also.
        !          5538:                         *
        !          5539:                         * Note: It is really important to update our current
        !          5540:                         * flags with at least the state of TAG capabilities-
        !          5541:                         * otherwise we might try and send a tagged command
        !          5542:                         * when we have it all turned off. So change it here
        !          5543:                         * to say that current already matches goal.
        !          5544:                         */
        !          5545:                        sdp->isp_devparam[tgt].actv_flags &= ~DPARM_TQING;
        !          5546:                        sdp->isp_devparam[tgt].actv_flags |=
        !          5547:                            (sdp->isp_devparam[tgt].goal_flags & DPARM_TQING);
        !          5548:                        isp_prt(isp, ISP_LOGDEBUG0,
        !          5549:                            "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x",
        !          5550:                            bus, tgt, mbs.param[2], mbs.param[3] >> 8,
        !          5551:                            mbs.param[3] & 0xff);
        !          5552:                        sdp->isp_devparam[tgt].dev_update = 0;
        !          5553:                        sdp->isp_devparam[tgt].dev_refresh = 1;
        !          5554:                        get = 0;
        !          5555:                } else {
        !          5556:                        continue;
        !          5557:                }
        !          5558:                mbs.param[1] = (bus << 15) | (tgt << 8);
        !          5559:                isp_mboxcmd(isp, &mbs, MBLOGALL);
        !          5560:                if (get == 0) {
        !          5561:                        isp->isp_sendmarker |= (1 << bus);
        !          5562:                        continue;
        !          5563:                }
        !          5564:                flags = mbs.param[2];
        !          5565:                period = mbs.param[3] & 0xff;
        !          5566:                offset = mbs.param[3] >> 8;
        !          5567:                sdp->isp_devparam[tgt].actv_flags = flags;
        !          5568:                sdp->isp_devparam[tgt].actv_period = period;
        !          5569:                sdp->isp_devparam[tgt].actv_offset = offset;
        !          5570:                get = (bus << 16) | tgt;
        !          5571:                (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get);
        !          5572:        }
        !          5573:
        !          5574:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          5575:                if (sdp->isp_devparam[tgt].dev_update ||
        !          5576:                    sdp->isp_devparam[tgt].dev_refresh) {
        !          5577:                        isp->isp_update |= (1 << bus);
        !          5578:                        break;
        !          5579:                }
        !          5580:        }
        !          5581: }
        !          5582:
        !          5583: #ifndef        DEFAULT_FRAMESIZE
        !          5584: #define        DEFAULT_FRAMESIZE(isp)          ICB_DFLT_FRMLEN
        !          5585: #endif
        !          5586: #ifndef        DEFAULT_EXEC_THROTTLE
        !          5587: #define        DEFAULT_EXEC_THROTTLE(isp)      ISP_EXEC_THROTTLE
        !          5588: #endif
        !          5589:
        !          5590: static void
        !          5591: isp_setdfltparm(struct ispsoftc *isp, int channel)
        !          5592: {
        !          5593:        int tgt;
        !          5594:        mbreg_t mbs;
        !          5595:        sdparam *sdp;
        !          5596:
        !          5597:        if (IS_FC(isp)) {
        !          5598:                fcparam *fcp = (fcparam *) isp->isp_param;
        !          5599:                int nvfail;
        !          5600:
        !          5601:                fcp += channel;
        !          5602:                if (fcp->isp_gotdparms) {
        !          5603:                        return;
        !          5604:                }
        !          5605:                fcp->isp_gotdparms = 1;
        !          5606:                fcp->isp_maxfrmlen = DEFAULT_FRAMESIZE(isp);
        !          5607:                fcp->isp_maxalloc = ICB_DFLT_ALLOC;
        !          5608:                fcp->isp_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
        !          5609:                fcp->isp_retry_delay = ICB_DFLT_RDELAY;
        !          5610:                fcp->isp_retry_count = ICB_DFLT_RCOUNT;
        !          5611:                /* Platform specific.... */
        !          5612:                fcp->isp_loopid = DEFAULT_LOOPID(isp);
        !          5613:                fcp->isp_nodewwn = DEFAULT_NODEWWN(isp);
        !          5614:                fcp->isp_portwwn = DEFAULT_PORTWWN(isp);
        !          5615:                fcp->isp_fwoptions = 0;
        !          5616:                fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
        !          5617:                fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
        !          5618:                fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
        !          5619: #ifndef        ISP_NO_FASTPOST_FC
        !          5620:                fcp->isp_fwoptions |= ICBOPT_FAST_POST;
        !          5621: #endif
        !          5622:                if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
        !          5623:                        fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
        !          5624:
        !          5625:                /*
        !          5626:                 * Make sure this is turned off now until we get
        !          5627:                 * extended options from NVRAM
        !          5628:                 */
        !          5629:                fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
        !          5630:
        !          5631:                /*
        !          5632:                 * Now try and read NVRAM unless told to not do so.
        !          5633:                 * This will set fcparam's isp_nodewwn && isp_portwwn.
        !          5634:                 */
        !          5635:                if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
        !          5636:                        nvfail = isp_read_nvram(isp);
        !          5637:                        if (nvfail)
        !          5638:                                isp->isp_confopts |= ISP_CFG_NONVRAM;
        !          5639:                } else {
        !          5640:                        nvfail = 1;
        !          5641:                }
        !          5642:                /*
        !          5643:                 * Set node && port to override platform set defaults
        !          5644:                 * unless the nvram read failed (or none was done),
        !          5645:                 * or the platform code wants to use what had been
        !          5646:                 * set in the defaults.
        !          5647:                 */
        !          5648:                if (nvfail) {
        !          5649:                        isp->isp_confopts |= ISP_CFG_OWNWWPN|ISP_CFG_OWNWWNN;
        !          5650:                }
        !          5651:                if (isp->isp_confopts & ISP_CFG_OWNWWNN) {
        !          5652:                        isp_prt(isp, ISP_LOGCONFIG, "Using Node WWN 0x%08x%08x",
        !          5653:                            (u_int32_t) (DEFAULT_NODEWWN(isp) >> 32),
        !          5654:                            (u_int32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff));
        !          5655:                        ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
        !          5656:                } else {
        !          5657:                        /*
        !          5658:                         * We always start out with values derived
        !          5659:                         * from NVRAM or our platform default.
        !          5660:                         */
        !          5661:                        ISP_NODEWWN(isp) = fcp->isp_nodewwn;
        !          5662:                }
        !          5663:                if (isp->isp_confopts & ISP_CFG_OWNWWPN) {
        !          5664:                        isp_prt(isp, ISP_LOGCONFIG, "Using Port WWN 0x%08x%08x",
        !          5665:                            (u_int32_t) (DEFAULT_PORTWWN(isp) >> 32),
        !          5666:                            (u_int32_t) (DEFAULT_PORTWWN(isp) & 0xffffffff));
        !          5667:                        ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
        !          5668:                } else {
        !          5669:                        /*
        !          5670:                         * We always start out with values derived
        !          5671:                         * from NVRAM or our platform default.
        !          5672:                         */
        !          5673:                        ISP_PORTWWN(isp) = fcp->isp_portwwn;
        !          5674:                }
        !          5675:                return;
        !          5676:        }
        !          5677:
        !          5678:        sdp = (sdparam *) isp->isp_param;
        !          5679:        sdp += channel;
        !          5680:
        !          5681:        /*
        !          5682:         * Been there, done that, got the T-shirt...
        !          5683:         */
        !          5684:        if (sdp->isp_gotdparms) {
        !          5685:                return;
        !          5686:        }
        !          5687:        sdp->isp_gotdparms = 1;
        !          5688:
        !          5689:        /*
        !          5690:         * Establish some default parameters.
        !          5691:         */
        !          5692:        sdp->isp_cmd_dma_burst_enable = 0;
        !          5693:        sdp->isp_data_dma_burst_enabl = 1;
        !          5694:        sdp->isp_fifo_threshold = 0;
        !          5695:        sdp->isp_initiator_id = DEFAULT_IID(isp);
        !          5696:        if (isp->isp_type >= ISP_HA_SCSI_1040) {
        !          5697:                sdp->isp_async_data_setup = 9;
        !          5698:        } else {
        !          5699:                sdp->isp_async_data_setup = 6;
        !          5700:        }
        !          5701:        sdp->isp_selection_timeout = 250;
        !          5702:        sdp->isp_max_queue_depth = MAXISPREQUEST(isp);
        !          5703:        sdp->isp_tag_aging = 8;
        !          5704:        sdp->isp_bus_reset_delay = 5;
        !          5705:        /*
        !          5706:         * Don't retry selection, busy or queue full automatically- reflect
        !          5707:         * these back to us.
        !          5708:         */
        !          5709:        sdp->isp_retry_count = 0;
        !          5710:        sdp->isp_retry_delay = 0;
        !          5711:
        !          5712:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          5713:                sdp->isp_devparam[tgt].exc_throttle = ISP_EXEC_THROTTLE;
        !          5714:                sdp->isp_devparam[tgt].dev_enable = 1;
        !          5715:        }
        !          5716:
        !          5717:        /*
        !          5718:         * If we've not been told to avoid reading NVRAM, try and read it.
        !          5719:         * If we're successful reading it, we can then return because NVRAM
        !          5720:         * will tell us what the desired settings are. Otherwise, we establish
        !          5721:         * some reasonable 'fake' nvram and goal defaults.
        !          5722:         */
        !          5723:
        !          5724:        if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
        !          5725:                if (isp_read_nvram(isp) == 0) {
        !          5726:                        return;
        !          5727:                }
        !          5728:        }
        !          5729:
        !          5730:        /*
        !          5731:         * Now try and see whether we have specific values for them.
        !          5732:         */
        !          5733:        if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
        !          5734:                mbs.param[0] = MBOX_GET_ACT_NEG_STATE;
        !          5735:                isp_mboxcmd(isp, &mbs, MBLOGNONE);
        !          5736:                if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          5737:                        sdp->isp_req_ack_active_neg = 1;
        !          5738:                        sdp->isp_data_line_active_neg = 1;
        !          5739:                } else {
        !          5740:                        sdp->isp_req_ack_active_neg =
        !          5741:                            (mbs.param[1+channel] >> 4) & 0x1;
        !          5742:                        sdp->isp_data_line_active_neg =
        !          5743:                            (mbs.param[1+channel] >> 5) & 0x1;
        !          5744:                }
        !          5745:        }
        !          5746:
        !          5747:        isp_prt(isp, ISP_LOGDEBUG0, sc0, sc3,
        !          5748:            0, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
        !          5749:            sdp->isp_bus_reset_delay, sdp->isp_retry_count,
        !          5750:            sdp->isp_retry_delay, sdp->isp_async_data_setup);
        !          5751:        isp_prt(isp, ISP_LOGDEBUG0, sc1, sc3,
        !          5752:            sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
        !          5753:            sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
        !          5754:            sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
        !          5755:
        !          5756:        /*
        !          5757:         * The trick here is to establish a default for the default (honk!)
        !          5758:         * state (goal_flags). Then try and get the current status from
        !          5759:         * the card to fill in the current state. We don't, in fact, set
        !          5760:         * the default to the SAFE default state- that's not the goal state.
        !          5761:         */
        !          5762:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          5763:                u_int8_t off, per;
        !          5764:                sdp->isp_devparam[tgt].actv_offset = 0;
        !          5765:                sdp->isp_devparam[tgt].actv_period = 0;
        !          5766:                sdp->isp_devparam[tgt].actv_flags = 0;
        !          5767:
        !          5768:                sdp->isp_devparam[tgt].goal_flags =
        !          5769:                    sdp->isp_devparam[tgt].nvrm_flags = DPARM_DEFAULT;
        !          5770:
        !          5771:                /*
        !          5772:                 * We default to Wide/Fast for versions less than a 1040
        !          5773:                 * (unless its SBus).
        !          5774:                 */
        !          5775:                if (IS_ULTRA3(isp)) {
        !          5776:                        off = ISP_80M_SYNCPARMS >> 8;
        !          5777:                        per = ISP_80M_SYNCPARMS & 0xff;
        !          5778:                } else if (IS_ULTRA2(isp)) {
        !          5779:                        off = ISP_40M_SYNCPARMS >> 8;
        !          5780:                        per = ISP_40M_SYNCPARMS & 0xff;
        !          5781:                } else if (IS_1240(isp)) {
        !          5782:                        off = ISP_20M_SYNCPARMS >> 8;
        !          5783:                        per = ISP_20M_SYNCPARMS & 0xff;
        !          5784:                } else if ((isp->isp_bustype == ISP_BT_SBUS &&
        !          5785:                    isp->isp_type < ISP_HA_SCSI_1020A) ||
        !          5786:                    (isp->isp_bustype == ISP_BT_PCI &&
        !          5787:                    isp->isp_type < ISP_HA_SCSI_1040) ||
        !          5788:                    (isp->isp_clock && isp->isp_clock < 60) ||
        !          5789:                    (sdp->isp_ultramode == 0)) {
        !          5790:                        off = ISP_10M_SYNCPARMS >> 8;
        !          5791:                        per = ISP_10M_SYNCPARMS & 0xff;
        !          5792:                } else {
        !          5793:                        off = ISP_20M_SYNCPARMS_1040 >> 8;
        !          5794:                        per = ISP_20M_SYNCPARMS_1040 & 0xff;
        !          5795:                }
        !          5796:                sdp->isp_devparam[tgt].goal_offset =
        !          5797:                    sdp->isp_devparam[tgt].nvrm_offset = off;
        !          5798:                sdp->isp_devparam[tgt].goal_period =
        !          5799:                    sdp->isp_devparam[tgt].nvrm_period = per;
        !          5800:
        !          5801:                isp_prt(isp, ISP_LOGDEBUG0, sc2, sc3,
        !          5802:                    channel, tgt, sdp->isp_devparam[tgt].nvrm_flags,
        !          5803:                    sdp->isp_devparam[tgt].nvrm_offset,
        !          5804:                    sdp->isp_devparam[tgt].nvrm_period);
        !          5805:        }
        !          5806: }
        !          5807:
        !          5808: /*
        !          5809:  * Re-initialize the ISP and complete all orphaned commands
        !          5810:  * with a 'botched' notice. The reset/init routines should
        !          5811:  * not disturb an already active list of commands.
        !          5812:  *
        !          5813:  * Locks held prior to coming here.
        !          5814:  */
        !          5815:
        !          5816: void
        !          5817: isp_reinit(struct ispsoftc *isp)
        !          5818: {
        !          5819:        XS_T *xs;
        !          5820:        u_int16_t handle;
        !          5821:
        !          5822:        isp_reset(isp);
        !          5823:        if (isp->isp_state != ISP_RESETSTATE) {
        !          5824:                isp_prt(isp, ISP_LOGERR, "isp_reinit cannot reset card");
        !          5825:        } else if (isp->isp_role != ISP_ROLE_NONE) {
        !          5826:                isp_init(isp);
        !          5827:                if (isp->isp_state == ISP_INITSTATE) {
        !          5828:                        isp->isp_state = ISP_RUNSTATE;
        !          5829:                }
        !          5830:                if (isp->isp_state != ISP_RUNSTATE) {
        !          5831:                        isp_prt(isp, ISP_LOGERR,
        !          5832:                            "isp_reinit cannot restart card");
        !          5833:                }
        !          5834:        }
        !          5835:        isp->isp_nactive = 0;
        !          5836:
        !          5837:        for (handle = 1; (int) handle <= isp->isp_maxcmds; handle++) {
        !          5838:                xs = isp_find_xs(isp, handle);
        !          5839:                if (xs == NULL) {
        !          5840:                        continue;
        !          5841:                }
        !          5842:                isp_destroy_handle(isp, handle);
        !          5843:                if (XS_XFRLEN(xs)) {
        !          5844:                        ISP_DMAFREE(isp, xs, handle);
        !          5845:                        XS_RESID(xs) = XS_XFRLEN(xs);
        !          5846:                } else {
        !          5847:                        XS_RESID(xs) = 0;
        !          5848:                }
        !          5849:                XS_SETERR(xs, HBA_BUSRESET);
        !          5850:                isp_done(xs);
        !          5851:        }
        !          5852: }
        !          5853:
        !          5854: /*
        !          5855:  * NVRAM Routines
        !          5856:  */
        !          5857: static int
        !          5858: isp_read_nvram(struct ispsoftc *isp)
        !          5859: {
        !          5860:        int i, amt;
        !          5861:        u_int8_t csum, minversion;
        !          5862:        union {
        !          5863:                u_int8_t _x[ISP2100_NVRAM_SIZE];
        !          5864:                u_int16_t _s[ISP2100_NVRAM_SIZE>>1];
        !          5865:        } _n;
        !          5866: #define        nvram_data      _n._x
        !          5867: #define        nvram_words     _n._s
        !          5868:
        !          5869:        if (IS_FC(isp)) {
        !          5870:                amt = ISP2100_NVRAM_SIZE;
        !          5871:                minversion = 1;
        !          5872:        } else if (IS_ULTRA2(isp)) {
        !          5873:                amt = ISP1080_NVRAM_SIZE;
        !          5874:                minversion = 0;
        !          5875:        } else {
        !          5876:                amt = ISP_NVRAM_SIZE;
        !          5877:                minversion = 2;
        !          5878:        }
        !          5879:
        !          5880:        /*
        !          5881:         * Just read the first two words first to see if we have a valid
        !          5882:         * NVRAM to continue reading the rest with.
        !          5883:         */
        !          5884:        for (i = 0; i < 2; i++) {
        !          5885:                isp_rdnvram_word(isp, i, &nvram_words[i]);
        !          5886:        }
        !          5887:        if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
        !          5888:            nvram_data[2] != 'P') {
        !          5889:                if (isp->isp_bustype != ISP_BT_SBUS) {
        !          5890:                        isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header");
        !          5891:                        isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x",
        !          5892:                            nvram_data[0], nvram_data[1], nvram_data[2]);
        !          5893:                }
        !          5894:                return (-1);
        !          5895:        }
        !          5896:        for (i = 2; i < amt>>1; i++) {
        !          5897:                isp_rdnvram_word(isp, i, &nvram_words[i]);
        !          5898:        }
        !          5899:        for (csum = 0, i = 0; i < amt; i++) {
        !          5900:                csum += nvram_data[i];
        !          5901:        }
        !          5902:        if (csum != 0) {
        !          5903:                isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
        !          5904:                return (-1);
        !          5905:        }
        !          5906:        if (ISP_NVRAM_VERSION(nvram_data) < minversion) {
        !          5907:                isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood",
        !          5908:                    ISP_NVRAM_VERSION(nvram_data));
        !          5909:                return (-1);
        !          5910:        }
        !          5911:
        !          5912:        if (IS_ULTRA3(isp)) {
        !          5913:                isp_parse_nvram_12160(isp, 0, nvram_data);
        !          5914:                if (IS_12160(isp))
        !          5915:                        isp_parse_nvram_12160(isp, 1, nvram_data);
        !          5916:        } else if (IS_1080(isp)) {
        !          5917:                isp_parse_nvram_1080(isp, 0, nvram_data);
        !          5918:        } else if (IS_1280(isp) || IS_1240(isp)) {
        !          5919:                isp_parse_nvram_1080(isp, 0, nvram_data);
        !          5920:                isp_parse_nvram_1080(isp, 1, nvram_data);
        !          5921:        } else if (IS_SCSI(isp)) {
        !          5922:                isp_parse_nvram_1020(isp, nvram_data);
        !          5923:        } else {
        !          5924:                isp_parse_nvram_2100(isp, nvram_data);
        !          5925:        }
        !          5926:        return (0);
        !          5927: #undef nvram_data
        !          5928: #undef nvram_words
        !          5929: }
        !          5930:
        !          5931: static void
        !          5932: isp_rdnvram_word(struct ispsoftc *isp, int wo, u_int16_t *rp)
        !          5933: {
        !          5934:        int i, cbits;
        !          5935:        u_int16_t bit, rqst;
        !          5936:
        !          5937:        ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
        !          5938:        USEC_DELAY(2);
        !          5939:        ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
        !          5940:        USEC_DELAY(2);
        !          5941:
        !          5942:        if (IS_FC(isp)) {
        !          5943:                wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
        !          5944:                if (IS_2312(isp) && isp->isp_port) {
        !          5945:                        wo += 128;
        !          5946:                }
        !          5947:                rqst = (ISP_NVRAM_READ << 8) | wo;
        !          5948:                cbits = 10;
        !          5949:        } else if (IS_ULTRA2(isp)) {
        !          5950:                wo &= ((ISP1080_NVRAM_SIZE >> 1) - 1);
        !          5951:                rqst = (ISP_NVRAM_READ << 8) | wo;
        !          5952:                cbits = 10;
        !          5953:        } else {
        !          5954:                wo &= ((ISP_NVRAM_SIZE >> 1) - 1);
        !          5955:                rqst = (ISP_NVRAM_READ << 6) | wo;
        !          5956:                cbits = 8;
        !          5957:        }
        !          5958:
        !          5959:        /*
        !          5960:         * Clock the word select request out...
        !          5961:         */
        !          5962:        for (i = cbits; i >= 0; i--) {
        !          5963:                if ((rqst >> i) & 1) {
        !          5964:                        bit = BIU_NVRAM_SELECT | BIU_NVRAM_DATAOUT;
        !          5965:                } else {
        !          5966:                        bit = BIU_NVRAM_SELECT;
        !          5967:                }
        !          5968:                ISP_WRITE(isp, BIU_NVRAM, bit);
        !          5969:                USEC_DELAY(2);
        !          5970:                ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK);
        !          5971:                USEC_DELAY(2);
        !          5972:                ISP_WRITE(isp, BIU_NVRAM, bit);
        !          5973:                USEC_DELAY(2);
        !          5974:        }
        !          5975:        /*
        !          5976:         * Now read the result back in (bits come back in MSB format).
        !          5977:         */
        !          5978:        *rp = 0;
        !          5979:        for (i = 0; i < 16; i++) {
        !          5980:                u_int16_t rv;
        !          5981:                *rp <<= 1;
        !          5982:                ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
        !          5983:                USEC_DELAY(2);
        !          5984:                rv = ISP_READ(isp, BIU_NVRAM);
        !          5985:                if (rv & BIU_NVRAM_DATAIN) {
        !          5986:                        *rp |= 1;
        !          5987:                }
        !          5988:                USEC_DELAY(2);
        !          5989:                ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
        !          5990:                USEC_DELAY(2);
        !          5991:        }
        !          5992:        ISP_WRITE(isp, BIU_NVRAM, 0);
        !          5993:        USEC_DELAY(2);
        !          5994:        ISP_SWIZZLE_NVRAM_WORD(isp, rp);
        !          5995: }
        !          5996:
        !          5997: static void
        !          5998: isp_parse_nvram_1020(struct ispsoftc *isp, u_int8_t *nvram_data)
        !          5999: {
        !          6000:        sdparam *sdp = (sdparam *) isp->isp_param;
        !          6001:        int tgt;
        !          6002:
        !          6003:        sdp->isp_fifo_threshold =
        !          6004:                ISP_NVRAM_FIFO_THRESHOLD(nvram_data) |
        !          6005:                (ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2);
        !          6006:
        !          6007:        if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
        !          6008:                sdp->isp_initiator_id =
        !          6009:                        ISP_NVRAM_INITIATOR_ID(nvram_data);
        !          6010:
        !          6011:        sdp->isp_bus_reset_delay =
        !          6012:                ISP_NVRAM_BUS_RESET_DELAY(nvram_data);
        !          6013:
        !          6014:        sdp->isp_retry_count =
        !          6015:                ISP_NVRAM_BUS_RETRY_COUNT(nvram_data);
        !          6016:
        !          6017:        sdp->isp_retry_delay =
        !          6018:                ISP_NVRAM_BUS_RETRY_DELAY(nvram_data);
        !          6019:
        !          6020:        sdp->isp_async_data_setup =
        !          6021:                ISP_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data);
        !          6022:
        !          6023:        if (isp->isp_type >= ISP_HA_SCSI_1040) {
        !          6024:                if (sdp->isp_async_data_setup < 9) {
        !          6025:                        sdp->isp_async_data_setup = 9;
        !          6026:                }
        !          6027:        } else {
        !          6028:                if (sdp->isp_async_data_setup != 6) {
        !          6029:                        sdp->isp_async_data_setup = 6;
        !          6030:                }
        !          6031:        }
        !          6032:
        !          6033:        sdp->isp_req_ack_active_neg =
        !          6034:                ISP_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data);
        !          6035:
        !          6036:        sdp->isp_data_line_active_neg =
        !          6037:                ISP_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data);
        !          6038:
        !          6039:        sdp->isp_data_dma_burst_enabl =
        !          6040:                ISP_NVRAM_DATA_DMA_BURST_ENABLE(nvram_data);
        !          6041:
        !          6042:        sdp->isp_cmd_dma_burst_enable =
        !          6043:                ISP_NVRAM_CMD_DMA_BURST_ENABLE(nvram_data);
        !          6044:
        !          6045:        sdp->isp_tag_aging =
        !          6046:                ISP_NVRAM_TAG_AGE_LIMIT(nvram_data);
        !          6047:
        !          6048:        sdp->isp_selection_timeout =
        !          6049:                ISP_NVRAM_SELECTION_TIMEOUT(nvram_data);
        !          6050:
        !          6051:        sdp->isp_max_queue_depth =
        !          6052:                ISP_NVRAM_MAX_QUEUE_DEPTH(nvram_data);
        !          6053:
        !          6054:        sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
        !          6055:
        !          6056:        isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
        !          6057:            0, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
        !          6058:            sdp->isp_bus_reset_delay, sdp->isp_retry_count,
        !          6059:            sdp->isp_retry_delay, sdp->isp_async_data_setup);
        !          6060:        isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
        !          6061:            sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
        !          6062:            sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
        !          6063:            sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
        !          6064:
        !          6065:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          6066:                sdp->isp_devparam[tgt].dev_enable =
        !          6067:                        ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt);
        !          6068:                sdp->isp_devparam[tgt].exc_throttle =
        !          6069:                        ISP_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt);
        !          6070:                sdp->isp_devparam[tgt].nvrm_offset =
        !          6071:                        ISP_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt);
        !          6072:                sdp->isp_devparam[tgt].nvrm_period =
        !          6073:                        ISP_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt);
        !          6074:                /*
        !          6075:                 * We probably shouldn't lie about this, but it
        !          6076:                 * it makes it much safer if we limit NVRAM values
        !          6077:                 * to sanity.
        !          6078:                 */
        !          6079:                if (isp->isp_type < ISP_HA_SCSI_1040) {
        !          6080:                        /*
        !          6081:                         * If we're not ultra, we can't possibly
        !          6082:                         * be a shorter period than this.
        !          6083:                         */
        !          6084:                        if (sdp->isp_devparam[tgt].nvrm_period < 0x19) {
        !          6085:                                sdp->isp_devparam[tgt].nvrm_period = 0x19;
        !          6086:                        }
        !          6087:                        if (sdp->isp_devparam[tgt].nvrm_offset > 0xc) {
        !          6088:                                sdp->isp_devparam[tgt].nvrm_offset = 0x0c;
        !          6089:                        }
        !          6090:                } else {
        !          6091:                        if (sdp->isp_devparam[tgt].nvrm_offset > 0x8) {
        !          6092:                                sdp->isp_devparam[tgt].nvrm_offset = 0x8;
        !          6093:                        }
        !          6094:                }
        !          6095:                sdp->isp_devparam[tgt].nvrm_flags = 0;
        !          6096:                if (ISP_NVRAM_TGT_RENEG(nvram_data, tgt))
        !          6097:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
        !          6098:                sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
        !          6099:                if (ISP_NVRAM_TGT_TQING(nvram_data, tgt))
        !          6100:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
        !          6101:                if (ISP_NVRAM_TGT_SYNC(nvram_data, tgt))
        !          6102:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
        !          6103:                if (ISP_NVRAM_TGT_WIDE(nvram_data, tgt))
        !          6104:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
        !          6105:                if (ISP_NVRAM_TGT_PARITY(nvram_data, tgt))
        !          6106:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
        !          6107:                if (ISP_NVRAM_TGT_DISC(nvram_data, tgt))
        !          6108:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
        !          6109:                sdp->isp_devparam[tgt].actv_flags = 0; /* we don't know */
        !          6110:                isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
        !          6111:                    0, tgt, sdp->isp_devparam[tgt].nvrm_flags,
        !          6112:                    sdp->isp_devparam[tgt].nvrm_offset,
        !          6113:                    sdp->isp_devparam[tgt].nvrm_period);
        !          6114:                sdp->isp_devparam[tgt].goal_offset =
        !          6115:                    sdp->isp_devparam[tgt].nvrm_offset;
        !          6116:                sdp->isp_devparam[tgt].goal_period =
        !          6117:                    sdp->isp_devparam[tgt].nvrm_period;
        !          6118:                sdp->isp_devparam[tgt].goal_flags =
        !          6119:                    sdp->isp_devparam[tgt].nvrm_flags;
        !          6120:        }
        !          6121: }
        !          6122:
        !          6123: static void
        !          6124: isp_parse_nvram_1080(struct ispsoftc *isp, int bus, u_int8_t *nvram_data)
        !          6125: {
        !          6126:        sdparam *sdp = (sdparam *) isp->isp_param;
        !          6127:        int tgt;
        !          6128:
        !          6129:        sdp += bus;
        !          6130:
        !          6131:        sdp->isp_fifo_threshold =
        !          6132:            ISP1080_NVRAM_FIFO_THRESHOLD(nvram_data);
        !          6133:
        !          6134:        if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
        !          6135:                sdp->isp_initiator_id =
        !          6136:                    ISP1080_NVRAM_INITIATOR_ID(nvram_data, bus);
        !          6137:
        !          6138:        sdp->isp_bus_reset_delay =
        !          6139:            ISP1080_NVRAM_BUS_RESET_DELAY(nvram_data, bus);
        !          6140:
        !          6141:        sdp->isp_retry_count =
        !          6142:            ISP1080_NVRAM_BUS_RETRY_COUNT(nvram_data, bus);
        !          6143:
        !          6144:        sdp->isp_retry_delay =
        !          6145:            ISP1080_NVRAM_BUS_RETRY_DELAY(nvram_data, bus);
        !          6146:
        !          6147:        sdp->isp_async_data_setup =
        !          6148:            ISP1080_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data, bus);
        !          6149:
        !          6150:        sdp->isp_req_ack_active_neg =
        !          6151:            ISP1080_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data, bus);
        !          6152:
        !          6153:        sdp->isp_data_line_active_neg =
        !          6154:            ISP1080_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data, bus);
        !          6155:
        !          6156:        sdp->isp_data_dma_burst_enabl =
        !          6157:            ISP1080_NVRAM_BURST_ENABLE(nvram_data);
        !          6158:
        !          6159:        sdp->isp_cmd_dma_burst_enable =
        !          6160:            ISP1080_NVRAM_BURST_ENABLE(nvram_data);
        !          6161:
        !          6162:        sdp->isp_selection_timeout =
        !          6163:            ISP1080_NVRAM_SELECTION_TIMEOUT(nvram_data, bus);
        !          6164:
        !          6165:        sdp->isp_max_queue_depth =
        !          6166:             ISP1080_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
        !          6167:
        !          6168:        isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
        !          6169:            bus, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
        !          6170:            sdp->isp_bus_reset_delay, sdp->isp_retry_count,
        !          6171:            sdp->isp_retry_delay, sdp->isp_async_data_setup);
        !          6172:        isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
        !          6173:            sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
        !          6174:            sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
        !          6175:            sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
        !          6176:
        !          6177:
        !          6178:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          6179:                sdp->isp_devparam[tgt].dev_enable =
        !          6180:                    ISP1080_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
        !          6181:                sdp->isp_devparam[tgt].exc_throttle =
        !          6182:                        ISP1080_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt, bus);
        !          6183:                sdp->isp_devparam[tgt].nvrm_offset =
        !          6184:                        ISP1080_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt, bus);
        !          6185:                sdp->isp_devparam[tgt].nvrm_period =
        !          6186:                        ISP1080_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt, bus);
        !          6187:                sdp->isp_devparam[tgt].nvrm_flags = 0;
        !          6188:                if (ISP1080_NVRAM_TGT_RENEG(nvram_data, tgt, bus))
        !          6189:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
        !          6190:                sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
        !          6191:                if (ISP1080_NVRAM_TGT_TQING(nvram_data, tgt, bus))
        !          6192:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
        !          6193:                if (ISP1080_NVRAM_TGT_SYNC(nvram_data, tgt, bus))
        !          6194:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
        !          6195:                if (ISP1080_NVRAM_TGT_WIDE(nvram_data, tgt, bus))
        !          6196:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
        !          6197:                if (ISP1080_NVRAM_TGT_PARITY(nvram_data, tgt, bus))
        !          6198:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
        !          6199:                if (ISP1080_NVRAM_TGT_DISC(nvram_data, tgt, bus))
        !          6200:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
        !          6201:                sdp->isp_devparam[tgt].actv_flags = 0;
        !          6202:                isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
        !          6203:                    bus, tgt, sdp->isp_devparam[tgt].nvrm_flags,
        !          6204:                    sdp->isp_devparam[tgt].nvrm_offset,
        !          6205:                    sdp->isp_devparam[tgt].nvrm_period);
        !          6206:                sdp->isp_devparam[tgt].goal_offset =
        !          6207:                    sdp->isp_devparam[tgt].nvrm_offset;
        !          6208:                sdp->isp_devparam[tgt].goal_period =
        !          6209:                    sdp->isp_devparam[tgt].nvrm_period;
        !          6210:                sdp->isp_devparam[tgt].goal_flags =
        !          6211:                    sdp->isp_devparam[tgt].nvrm_flags;
        !          6212:        }
        !          6213: }
        !          6214:
        !          6215: static void
        !          6216: isp_parse_nvram_12160(struct ispsoftc *isp, int bus, u_int8_t *nvram_data)
        !          6217: {
        !          6218:        sdparam *sdp = (sdparam *) isp->isp_param;
        !          6219:        int tgt;
        !          6220:
        !          6221:        sdp += bus;
        !          6222:
        !          6223:        sdp->isp_fifo_threshold =
        !          6224:            ISP12160_NVRAM_FIFO_THRESHOLD(nvram_data);
        !          6225:
        !          6226:        if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
        !          6227:                sdp->isp_initiator_id =
        !          6228:                    ISP12160_NVRAM_INITIATOR_ID(nvram_data, bus);
        !          6229:
        !          6230:        sdp->isp_bus_reset_delay =
        !          6231:            ISP12160_NVRAM_BUS_RESET_DELAY(nvram_data, bus);
        !          6232:
        !          6233:        sdp->isp_retry_count =
        !          6234:            ISP12160_NVRAM_BUS_RETRY_COUNT(nvram_data, bus);
        !          6235:
        !          6236:        sdp->isp_retry_delay =
        !          6237:            ISP12160_NVRAM_BUS_RETRY_DELAY(nvram_data, bus);
        !          6238:
        !          6239:        sdp->isp_async_data_setup =
        !          6240:            ISP12160_NVRAM_ASYNC_DATA_SETUP_TIME(nvram_data, bus);
        !          6241:
        !          6242:        sdp->isp_req_ack_active_neg =
        !          6243:            ISP12160_NVRAM_REQ_ACK_ACTIVE_NEGATION(nvram_data, bus);
        !          6244:
        !          6245:        sdp->isp_data_line_active_neg =
        !          6246:            ISP12160_NVRAM_DATA_LINE_ACTIVE_NEGATION(nvram_data, bus);
        !          6247:
        !          6248:        sdp->isp_data_dma_burst_enabl =
        !          6249:            ISP12160_NVRAM_BURST_ENABLE(nvram_data);
        !          6250:
        !          6251:        sdp->isp_cmd_dma_burst_enable =
        !          6252:            ISP12160_NVRAM_BURST_ENABLE(nvram_data);
        !          6253:
        !          6254:        sdp->isp_selection_timeout =
        !          6255:            ISP12160_NVRAM_SELECTION_TIMEOUT(nvram_data, bus);
        !          6256:
        !          6257:        sdp->isp_max_queue_depth =
        !          6258:             ISP12160_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
        !          6259:
        !          6260:        isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
        !          6261:            bus, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
        !          6262:            sdp->isp_bus_reset_delay, sdp->isp_retry_count,
        !          6263:            sdp->isp_retry_delay, sdp->isp_async_data_setup);
        !          6264:        isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
        !          6265:            sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
        !          6266:            sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
        !          6267:            sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
        !          6268:
        !          6269:        for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
        !          6270:                sdp->isp_devparam[tgt].dev_enable =
        !          6271:                    ISP12160_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
        !          6272:                sdp->isp_devparam[tgt].exc_throttle =
        !          6273:                        ISP12160_NVRAM_TGT_EXEC_THROTTLE(nvram_data, tgt, bus);
        !          6274:                sdp->isp_devparam[tgt].nvrm_offset =
        !          6275:                        ISP12160_NVRAM_TGT_SYNC_OFFSET(nvram_data, tgt, bus);
        !          6276:                sdp->isp_devparam[tgt].nvrm_period =
        !          6277:                        ISP12160_NVRAM_TGT_SYNC_PERIOD(nvram_data, tgt, bus);
        !          6278:                sdp->isp_devparam[tgt].nvrm_flags = 0;
        !          6279:                if (ISP12160_NVRAM_TGT_RENEG(nvram_data, tgt, bus))
        !          6280:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_RENEG;
        !          6281:                sdp->isp_devparam[tgt].nvrm_flags |= DPARM_ARQ;
        !          6282:                if (ISP12160_NVRAM_TGT_TQING(nvram_data, tgt, bus))
        !          6283:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_TQING;
        !          6284:                if (ISP12160_NVRAM_TGT_SYNC(nvram_data, tgt, bus))
        !          6285:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_SYNC;
        !          6286:                if (ISP12160_NVRAM_TGT_WIDE(nvram_data, tgt, bus))
        !          6287:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_WIDE;
        !          6288:                if (ISP12160_NVRAM_TGT_PARITY(nvram_data, tgt, bus))
        !          6289:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_PARITY;
        !          6290:                if (ISP12160_NVRAM_TGT_DISC(nvram_data, tgt, bus))
        !          6291:                        sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
        !          6292:                sdp->isp_devparam[tgt].actv_flags = 0;
        !          6293:                isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
        !          6294:                    bus, tgt, sdp->isp_devparam[tgt].nvrm_flags,
        !          6295:                    sdp->isp_devparam[tgt].nvrm_offset,
        !          6296:                    sdp->isp_devparam[tgt].nvrm_period);
        !          6297:                sdp->isp_devparam[tgt].goal_offset =
        !          6298:                    sdp->isp_devparam[tgt].nvrm_offset;
        !          6299:                sdp->isp_devparam[tgt].goal_period =
        !          6300:                    sdp->isp_devparam[tgt].nvrm_period;
        !          6301:                sdp->isp_devparam[tgt].goal_flags =
        !          6302:                    sdp->isp_devparam[tgt].nvrm_flags;
        !          6303:        }
        !          6304: }
        !          6305:
        !          6306: static void
        !          6307: isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data)
        !          6308: {
        !          6309:        fcparam *fcp = (fcparam *) isp->isp_param;
        !          6310:        u_int64_t wwn;
        !          6311:
        !          6312:        /*
        !          6313:         * There is NVRAM storage for both Port and Node entities-
        !          6314:         * but the Node entity appears to be unused on all the cards
        !          6315:         * I can find. However, we should account for this being set
        !          6316:         * at some point in the future.
        !          6317:         *
        !          6318:         * Qlogic WWNs have an NAA of 2, but usually nothing shows up in
        !          6319:         * bits 48..60. In the case of the 2202, it appears that they do
        !          6320:         * use bit 48 to distinguish between the two instances on the card.
        !          6321:         * The 2204, which I've never seen, *probably* extends this method.
        !          6322:         */
        !          6323:        wwn = ISP2100_NVRAM_PORT_NAME(nvram_data);
        !          6324:        if (wwn) {
        !          6325:                isp_prt(isp, ISP_LOGCONFIG, "NVRAM Port WWN 0x%08x%08x",
        !          6326:                    (u_int32_t) (wwn >> 32), (u_int32_t) (wwn & 0xffffffff));
        !          6327:                if ((wwn >> 60) == 0) {
        !          6328:                        wwn |= (((u_int64_t) 2)<< 60);
        !          6329:                }
        !          6330:        }
        !          6331:        fcp->isp_portwwn = wwn;
        !          6332:        if (IS_2200(isp) || IS_23XX(isp)) {
        !          6333:                wwn = ISP2200_NVRAM_NODE_NAME(nvram_data);
        !          6334:                if (wwn) {
        !          6335:                        isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
        !          6336:                            (u_int32_t) (wwn >> 32),
        !          6337:                            (u_int32_t) (wwn & 0xffffffff));
        !          6338:                        if ((wwn >> 60) == 0) {
        !          6339:                                wwn |= (((u_int64_t) 2)<< 60);
        !          6340:                        }
        !          6341:                }
        !          6342:        } else {
        !          6343:                wwn &= ~((u_int64_t) 0xfff << 48);
        !          6344:        }
        !          6345:        fcp->isp_nodewwn = wwn;
        !          6346:
        !          6347:        /*
        !          6348:         * Make sure we have both Node and Port as non-zero values.
        !          6349:         */
        !          6350:        if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) {
        !          6351:                fcp->isp_portwwn = fcp->isp_nodewwn;
        !          6352:        } else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) {
        !          6353:                fcp->isp_nodewwn = fcp->isp_portwwn;
        !          6354:        }
        !          6355:
        !          6356:        /*
        !          6357:         * Make the Node and Port values sane if they're NAA == 2.
        !          6358:         * This means to clear bits 48..56 for the Node WWN and
        !          6359:         * make sure that there's some non-zero value in 48..56
        !          6360:         * for the Port WWN.
        !          6361:         */
        !          6362:        if (fcp->isp_nodewwn && fcp->isp_portwwn) {
        !          6363:                if ((fcp->isp_nodewwn & (((u_int64_t) 0xfff) << 48)) != 0 &&
        !          6364:                    (fcp->isp_nodewwn >> 60) == 2) {
        !          6365:                        fcp->isp_nodewwn &= ~((u_int64_t) 0xfff << 48);
        !          6366:                }
        !          6367:                if ((fcp->isp_portwwn & (((u_int64_t) 0xfff) << 48)) == 0 &&
        !          6368:                    (fcp->isp_portwwn >> 60) == 2) {
        !          6369:                        fcp->isp_portwwn |= ((u_int64_t) 1 << 56);
        !          6370:                }
        !          6371:        }
        !          6372:
        !          6373:        isp_prt(isp, ISP_LOGDEBUG0,
        !          6374:            "NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x loopid %x",
        !          6375:            ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data),
        !          6376:            ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data),
        !          6377:            ISP2100_NVRAM_OPTIONS(nvram_data),
        !          6378:            ISP2100_NVRAM_HARDLOOPID(nvram_data));
        !          6379:
        !          6380:        fcp->isp_maxalloc =
        !          6381:                ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
        !          6382:        if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0)
        !          6383:                fcp->isp_maxfrmlen =
        !          6384:                        ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
        !          6385:        fcp->isp_retry_delay =
        !          6386:                ISP2100_NVRAM_RETRY_DELAY(nvram_data);
        !          6387:        fcp->isp_retry_count =
        !          6388:                ISP2100_NVRAM_RETRY_COUNT(nvram_data);
        !          6389:        if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0)
        !          6390:                fcp->isp_loopid =
        !          6391:                        ISP2100_NVRAM_HARDLOOPID(nvram_data);
        !          6392:        if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0)
        !          6393:                fcp->isp_execthrottle =
        !          6394:                        ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data);
        !          6395:        fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data);
        !          6396: }
        !          6397:
        !          6398: #ifdef ISP_FW_CRASH_DUMP
        !          6399: static void isp2200_fw_dump(struct ispsoftc *);
        !          6400: static void isp2300_fw_dump(struct ispsoftc *);
        !          6401:
        !          6402: static void
        !          6403: isp2200_fw_dump(struct ispsoftc *isp)
        !          6404: {
        !          6405:        int i, j;
        !          6406:        mbreg_t mbs;
        !          6407:        u_int16_t *ptr;
        !          6408:
        !          6409:        ptr = FCPARAM(isp)->isp_dump_data;
        !          6410:        if (ptr == NULL) {
        !          6411:                isp_prt(isp, ISP_LOGERR,
        !          6412:                   "No place to dump RISC registers and SRAM");
        !          6413:                return;
        !          6414:        }
        !          6415:        if (*ptr++) {
        !          6416:                isp_prt(isp, ISP_LOGERR,
        !          6417:                   "dump area for RISC registers and SRAM already used");
        !          6418:                return;
        !          6419:        }
        !          6420:        ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
        !          6421:        for (i = 0; i < 100; i++) {
        !          6422:                USEC_DELAY(100);
        !          6423:                if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
        !          6424:                        break;
        !          6425:                }
        !          6426:        }
        !          6427:        if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
        !          6428:                /*
        !          6429:                 * PBIU Registers
        !          6430:                 */
        !          6431:                for (i = 0; i < 8; i++) {
        !          6432:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
        !          6433:                }
        !          6434:
        !          6435:                /*
        !          6436:                 * Mailbox Registers
        !          6437:                 */
        !          6438:                for (i = 0; i < 8; i++) {
        !          6439:                        *ptr++ = ISP_READ(isp, MBOX_BLOCK + (i << 1));
        !          6440:                }
        !          6441:
        !          6442:                /*
        !          6443:                 * DMA Registers
        !          6444:                 */
        !          6445:                for (i = 0; i < 48; i++) {
        !          6446:                        *ptr++ = ISP_READ(isp, DMA_BLOCK + 0x20 + (i << 1));
        !          6447:                }
        !          6448:
        !          6449:                /*
        !          6450:                 * RISC H/W Registers
        !          6451:                 */
        !          6452:                ISP_WRITE(isp, BIU2100_CSR, 0);
        !          6453:                for (i = 0; i < 16; i++) {
        !          6454:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
        !          6455:                }
        !          6456:
        !          6457:                /*
        !          6458:                 * RISC GP Registers
        !          6459:                 */
        !          6460:                for (j = 0; j < 8; j++) {
        !          6461:                        ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 8));
        !          6462:                        for (i = 0; i < 16; i++) {
        !          6463:                                *ptr++ =
        !          6464:                                    ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6465:                        }
        !          6466:                }
        !          6467:
        !          6468:                /*
        !          6469:                 * Frame Buffer Hardware Registers
        !          6470:                 */
        !          6471:                ISP_WRITE(isp, BIU2100_CSR, 0x10);
        !          6472:                for (i = 0; i < 16; i++) {
        !          6473:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6474:                }
        !          6475:
        !          6476:                /*
        !          6477:                 * Fibre Protocol Module 0 Hardware Registers
        !          6478:                 */
        !          6479:                ISP_WRITE(isp, BIU2100_CSR, 0x20);
        !          6480:                for (i = 0; i < 64; i++) {
        !          6481:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6482:                }
        !          6483:
        !          6484:                /*
        !          6485:                 * Fibre Protocol Module 1 Hardware Registers
        !          6486:                 */
        !          6487:                ISP_WRITE(isp, BIU2100_CSR, 0x30);
        !          6488:                for (i = 0; i < 64; i++) {
        !          6489:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6490:                }
        !          6491:        } else {
        !          6492:                isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
        !          6493:                return;
        !          6494:        }
        !          6495:        isp_prt(isp, ISP_LOGALL,
        !          6496:           "isp_fw_dump: RISC registers dumped successfully");
        !          6497:        ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
        !          6498:        for (i = 0; i < 100; i++) {
        !          6499:                USEC_DELAY(100);
        !          6500:                if (ISP_READ(isp, OUTMAILBOX0) == 0) {
        !          6501:                        break;
        !          6502:                }
        !          6503:        }
        !          6504:        if (ISP_READ(isp, OUTMAILBOX0) != 0) {
        !          6505:                isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
        !          6506:                return;
        !          6507:        }
        !          6508:        ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
        !          6509:        for (i = 0; i < 100; i++) {
        !          6510:                USEC_DELAY(100);
        !          6511:                if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
        !          6512:                        break;
        !          6513:                }
        !          6514:        }
        !          6515:        if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
        !          6516:                isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause After Reset");
        !          6517:                return;
        !          6518:        }
        !          6519:        ISP_WRITE(isp, RISC_EMB, 0xf2);
        !          6520:        ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
        !          6521:        for (i = 0; i < 100; i++) {
        !          6522:                USEC_DELAY(100);
        !          6523:                if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
        !          6524:                        break;
        !          6525:                }
        !          6526:        }
        !          6527:        ENABLE_INTS(isp);
        !          6528:        mbs.param[0] = MBOX_READ_RAM_WORD;
        !          6529:        mbs.param[1] = 0x1000;
        !          6530:        isp->isp_mbxworkp = (void *) ptr;
        !          6531:        isp->isp_mbxwrk0 = 0xefff;      /* continuation count */
        !          6532:        isp->isp_mbxwrk1 = 0x1001;      /* next SRAM address */
        !          6533:        isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
        !          6534:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          6535:                isp_prt(isp, ISP_LOGWARN,
        !          6536:                    "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
        !          6537:                return;
        !          6538:        }
        !          6539:        ptr = isp->isp_mbxworkp;        /* finish fetch of final word */
        !          6540:        *ptr++ = isp->isp_mboxtmp[2];
        !          6541:        isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped successfully");
        !          6542:        FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
        !          6543:        (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0);
        !          6544: }
        !          6545:
        !          6546: static void
        !          6547: isp2300_fw_dump(struct ispsoftc *isp)
        !          6548: {
        !          6549:        int i, j;
        !          6550:        mbreg_t mbs;
        !          6551:        u_int16_t *ptr;
        !          6552:
        !          6553:        ptr = FCPARAM(isp)->isp_dump_data;
        !          6554:        if (ptr == NULL) {
        !          6555:                isp_prt(isp, ISP_LOGERR,
        !          6556:                   "No place to dump RISC registers and SRAM");
        !          6557:                return;
        !          6558:        }
        !          6559:        if (*ptr++) {
        !          6560:                isp_prt(isp, ISP_LOGERR,
        !          6561:                   "dump area for RISC registers and SRAM already used");
        !          6562:                return;
        !          6563:        }
        !          6564:        ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
        !          6565:        for (i = 0; i < 100; i++) {
        !          6566:                USEC_DELAY(100);
        !          6567:                if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
        !          6568:                        break;
        !          6569:                }
        !          6570:        }
        !          6571:        if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
        !          6572:                /*
        !          6573:                 * PBIU registers
        !          6574:                 */
        !          6575:                for (i = 0; i < 8; i++) {
        !          6576:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
        !          6577:                }
        !          6578:
        !          6579:                /*
        !          6580:                 * ReqQ-RspQ-Risc2Host Status registers
        !          6581:                 */
        !          6582:                for (i = 0; i < 8; i++) {
        !          6583:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x10 + (i << 1));
        !          6584:                }
        !          6585:
        !          6586:                /*
        !          6587:                 * Mailbox Registers
        !          6588:                 */
        !          6589:                for (i = 0; i < 32; i++) {
        !          6590:                        *ptr++ =
        !          6591:                            ISP_READ(isp, PCI_MBOX_REGS2300_OFF + (i << 1));
        !          6592:                }
        !          6593:
        !          6594:                /*
        !          6595:                 * Auto Request Response DMA registers
        !          6596:                 */
        !          6597:                ISP_WRITE(isp, BIU2100_CSR, 0x40);
        !          6598:                for (i = 0; i < 32; i++) {
        !          6599:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6600:                }
        !          6601:
        !          6602:                /*
        !          6603:                 * DMA registers
        !          6604:                 */
        !          6605:                ISP_WRITE(isp, BIU2100_CSR, 0x50);
        !          6606:                for (i = 0; i < 48; i++) {
        !          6607:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6608:                }
        !          6609:
        !          6610:                /*
        !          6611:                 * RISC hardware registers
        !          6612:                 */
        !          6613:                ISP_WRITE(isp, BIU2100_CSR, 0);
        !          6614:                for (i = 0; i < 16; i++) {
        !          6615:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
        !          6616:                }
        !          6617:
        !          6618:                /*
        !          6619:                 * RISC GP? registers
        !          6620:                 */
        !          6621:                for (j = 0; j < 8; j++) {
        !          6622:                        ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 9));
        !          6623:                        for (i = 0; i < 16; i++) {
        !          6624:                                *ptr++ =
        !          6625:                                    ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6626:                        }
        !          6627:                }
        !          6628:
        !          6629:                /*
        !          6630:                 * frame buffer hardware registers
        !          6631:                 */
        !          6632:                ISP_WRITE(isp, BIU2100_CSR, 0x10);
        !          6633:                for (i = 0; i < 64; i++) {
        !          6634:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6635:                }
        !          6636:
        !          6637:                /*
        !          6638:                 * FPM B0 hardware registers
        !          6639:                 */
        !          6640:                ISP_WRITE(isp, BIU2100_CSR, 0x20);
        !          6641:                for (i = 0; i < 64; i++) {
        !          6642:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6643:                }
        !          6644:
        !          6645:                /*
        !          6646:                 * FPM B1 hardware registers
        !          6647:                 */
        !          6648:                ISP_WRITE(isp, BIU2100_CSR, 0x30);
        !          6649:                for (i = 0; i < 64; i++) {
        !          6650:                        *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
        !          6651:                }
        !          6652:        } else {
        !          6653:                isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
        !          6654:                return;
        !          6655:        }
        !          6656:        isp_prt(isp, ISP_LOGALL,
        !          6657:           "isp_fw_dump: RISC registers dumped successfully");
        !          6658:        ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
        !          6659:        for (i = 0; i < 100; i++) {
        !          6660:                USEC_DELAY(100);
        !          6661:                if (ISP_READ(isp, OUTMAILBOX0) == 0) {
        !          6662:                        break;
        !          6663:                }
        !          6664:        }
        !          6665:        if (ISP_READ(isp, OUTMAILBOX0) != 0) {
        !          6666:                isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
        !          6667:                return;
        !          6668:        }
        !          6669:        ENABLE_INTS(isp);
        !          6670:        mbs.param[0] = MBOX_READ_RAM_WORD;
        !          6671:        mbs.param[1] = 0x800;
        !          6672:        isp->isp_mbxworkp = (void *) ptr;
        !          6673:        isp->isp_mbxwrk0 = 0xf7ff;      /* continuation count */
        !          6674:        isp->isp_mbxwrk1 = 0x801;       /* next SRAM address */
        !          6675:        isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
        !          6676:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          6677:                isp_prt(isp, ISP_LOGWARN,
        !          6678:                    "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
        !          6679:                return;
        !          6680:        }
        !          6681:        ptr = isp->isp_mbxworkp;        /* finish fetch of final word */
        !          6682:        *ptr++ = isp->isp_mboxtmp[2];
        !          6683:
        !          6684:        /*
        !          6685:         * We don't have access to mailbox registers 8.. onward
        !          6686:         * in our 'common' device model- so we have to set it
        !          6687:         * here and hope it stays the same!
        !          6688:         */
        !          6689:        ISP_WRITE(isp, PCI_MBOX_REGS2300_OFF + (8 << 1), 0x1);
        !          6690:
        !          6691:        mbs.param[0] = MBOX_READ_RAM_WORD_EXTENDED;
        !          6692:        mbs.param[1] = 0;
        !          6693:        isp->isp_mbxworkp = (void *) ptr;
        !          6694:        isp->isp_mbxwrk0 = 0xffff;      /* continuation count */
        !          6695:        isp->isp_mbxwrk1 = 0x1;         /* next SRAM address */
        !          6696:        isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
        !          6697:        if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
        !          6698:                isp_prt(isp, ISP_LOGWARN,
        !          6699:                    "RAM DUMP FAILED @ WORD %x", 0x10000 + isp->isp_mbxwrk1);
        !          6700:                return;
        !          6701:        }
        !          6702:        ptr = isp->isp_mbxworkp;        /* finish final word */
        !          6703:        *ptr++ = mbs.param[2];
        !          6704:        isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped successfully");
        !          6705:        FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
        !          6706:        (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0);
        !          6707: }
        !          6708:
        !          6709: void
        !          6710: isp_fw_dump(struct ispsoftc *isp)
        !          6711: {
        !          6712:        if (IS_2200(isp))
        !          6713:                isp2200_fw_dump(isp);
        !          6714:        else if (IS_23XX(isp))
        !          6715:                isp2300_fw_dump(isp);
        !          6716: }
        !          6717: #endif

CVSweb