diff options
-rw-r--r-- | sys/dev/isp/isp.c | 4774 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 475 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.h | 141 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 2623 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.h | 89 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 518 | ||||
-rw-r--r-- | sys/dev/isp/isp_sbus.c | 103 | ||||
-rw-r--r-- | sys/dev/isp/isp_stds.h | 200 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.c | 592 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.h | 356 | ||||
-rw-r--r-- | sys/dev/isp/isp_tpublic.h | 26 | ||||
-rw-r--r-- | sys/dev/isp/ispmbox.h | 620 | ||||
-rw-r--r-- | sys/dev/isp/ispreg.h | 191 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 239 |
14 files changed, 7601 insertions, 3346 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index b880a45..4f5537f 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -64,26 +64,9 @@ __FBSDID("$FreeBSD$"); /* * Local static data */ -static const char portshift[] = - "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)"; -static const char portdup[] = - "Target %d duplicates Target %d- killing off both"; -static const char retained[] = - "Retaining Loop ID 0x%x for Target %d (Port 0x%x)"; -static const char lretained[] = - "Retained login of Target %d (Loop ID 0x%x) Port 0x%x"; -static const char plogout[] = - "Logging out Target %d at Loop ID 0x%x (Port 0x%x)"; -static const char plogierr[] = - "Command Error in PLOGI for Port 0x%x (0x%x)"; -static const char nopdb[] = - "Could not get PDB for Device @ Port 0x%x"; -static const char pdbmfail1[] = - "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)"; -static const char pdbmfail2[] = - "PDB Port info for Device @ Port 0x%x does not match up (0x%x)"; -static const char ldumped[] = - "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch"; +static const char fconf[] = + "PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n" + " database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)"; static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; static const char xact1[] = @@ -95,9 +78,9 @@ static const char xact3[] = static const char pskip[] = "SCSI phase skipped for target %d.%d.%d"; static const char topology[] = - "Loop ID %d, Port ID 0x%x, Loop State 0x%x, Topology '%s'"; -static const char swrej[] = - "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x"; + "HBA PortID 0x%06x N-Port Handle %d, Connection Topology '%s'"; +static const char ourwwn[] = + "HBA WWNN 0x%08x%08x HBA WWPN 0x%08x%08x"; static const char finmsg[] = "%d.%d.%d: FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x"; static const char sc0[] = @@ -115,38 +98,52 @@ static const char bun[] = */ static int isp_parse_async(ispsoftc_t *, uint16_t); static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, - uint16_t *); + uint32_t *); static void -isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *); +isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); +static void +isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *); static void isp_fastpost_complete(ispsoftc_t *, uint16_t); static int isp_mbox_continue(ispsoftc_t *); static void isp_scsi_init(ispsoftc_t *); static void isp_scsi_channel_init(ispsoftc_t *, int); static void isp_fibre_init(ispsoftc_t *); -static void isp_mark_getpdb_all(ispsoftc_t *); -static int isp_getmap(ispsoftc_t *, fcpos_map_t *); -static int isp_getpdb(ispsoftc_t *, int, isp_pdb_t *); +static void isp_fibre_init_2400(ispsoftc_t *); +static void isp_dump_portdb(ispsoftc_t *); +static void isp_mark_portdb(ispsoftc_t *, int); +static void isp_plogx_24xx(ispsoftc_t *, uint16_t, uint32_t, int *); +static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t); +static void isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); +static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int); static uint64_t isp_get_portname(ispsoftc_t *, int, int); static int isp_fclink_test(ispsoftc_t *, int); static const char *isp2100_fw_statename(int); static int isp_pdb_sync(ispsoftc_t *); static int isp_scan_loop(ispsoftc_t *); -static int isp_fabric_mbox_cmd(ispsoftc_t *, mbreg_t *); -static int isp_scan_fabric(ispsoftc_t *, int); -static void isp_register_fc4_type(ispsoftc_t *); +static int isp_gid_ft_sns(ispsoftc_t *); +static int isp_gid_ft_ct_passthru(ispsoftc_t *); +static int isp_scan_fabric(ispsoftc_t *); +static int isp_login_device(ispsoftc_t *, uint32_t, isp_pdb_t *, uint16_t *); +static int isp_register_fc4_type(ispsoftc_t *); +static int isp_register_fc4_type_24xx(ispsoftc_t *); +static uint16_t isp_nxt_handle(ispsoftc_t *, uint16_t); static void isp_fw_state(ispsoftc_t *); static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int); -static void isp_mboxcmd(ispsoftc_t *, mbreg_t *, int); +static void isp_mboxcmd(ispsoftc_t *, mbreg_t *); static void isp_update(ispsoftc_t *); static void isp_update_bus(ispsoftc_t *, int); static void isp_setdfltparm(ispsoftc_t *, int); static int isp_read_nvram(ispsoftc_t *); +static int isp_read_nvram_2400(ispsoftc_t *); static void isp_rdnvram_word(ispsoftc_t *, int, uint16_t *); +static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *); static void isp_parse_nvram_1020(ispsoftc_t *, uint8_t *); static void isp_parse_nvram_1080(ispsoftc_t *, int, uint8_t *); static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *); +static void isp_fix_nvram_wwns(ispsoftc_t *); static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *); +static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *); /* * Reset Hardware. @@ -160,9 +157,10 @@ void isp_reset(ispsoftc_t *isp) { mbreg_t mbs; - uint32_t code_org; + uint32_t code_org, val; int loops, i, dodnld = 1; - char *btype = "????"; + static const char *btype = "????"; + static const char dcrc[] = "Downloaded RISC Code Checksum Failure"; isp->isp_state = ISP_NILSTATE; @@ -202,10 +200,16 @@ isp_reset(ispsoftc_t *isp) /* * Just in case it was paused... */ - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, + HCCR_2400_CMD_RELEASE); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + } MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { isp->isp_romfw_rev[0] = mbs.param[1]; isp->isp_romfw_rev[1] = mbs.param[2]; @@ -215,21 +219,51 @@ isp_reset(ispsoftc_t *isp) isp->isp_touched = 1; } - DISABLE_INTS(isp); + ISP_DISABLE_INTS(isp); + + /* + * Pick an initial maxcmds value which will be used + * to allocate xflist pointer space. It may be changed + * later by the firmware. + */ + if (IS_24XX(isp)) { + isp->isp_maxcmds = 4096; + } else if (IS_2322(isp)) { + isp->isp_maxcmds = 2048; + } else if (IS_23XX(isp) || IS_2200(isp)) { + isp->isp_maxcmds = 1024; + } else { + isp->isp_maxcmds = 512; + } + + /* + * Set up DMA for the request and result queues. + * + * We do this now so we can use the request queue + * for a dma + */ + if (ISP_MBOXDMASETUP(isp) != 0) { + isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); + return; + } + /* * Set up default request/response queue in-pointer/out-pointer * register indices. */ - if (IS_23XX(isp)) { + if (IS_24XX(isp)) { + isp->isp_rqstinrp = BIU2400_REQINP; + isp->isp_rqstoutrp = BIU2400_REQOUTP; + isp->isp_respinrp = BIU2400_RSPINP; + isp->isp_respoutrp = BIU2400_RSPOUTP; + isp->isp_atioinrp = BIU2400_ATIO_RSPINP; + isp->isp_atiooutrp = BIU2400_ATIO_REQINP; + } else if (IS_23XX(isp)) { isp->isp_rqstinrp = BIU_REQINP; isp->isp_rqstoutrp = BIU_REQOUTP; isp->isp_respinrp = BIU_RSPINP; isp->isp_respoutrp = BIU_RSPOUTP; - ISP_WRITE(isp, isp->isp_rqstinrp, 0); - ISP_WRITE(isp, isp->isp_rqstoutrp, 0); - ISP_WRITE(isp, isp->isp_respinrp, 0); - ISP_WRITE(isp, isp->isp_respoutrp, 0); } else { isp->isp_rqstinrp = INMAILBOX4; isp->isp_rqstoutrp = OUTMAILBOX4; @@ -241,7 +275,13 @@ isp_reset(ispsoftc_t *isp) * Put the board into PAUSE mode (so we can read the SXP registers * or write FPM/FBM registers). */ - ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + } if (IS_FC(isp)) { switch (isp->isp_type) { @@ -260,20 +300,24 @@ isp_reset(ispsoftc_t *isp) case ISP_HA_FC_2322: btype = "2322"; break; - case ISP_HA_FC_2422: + case ISP_HA_FC_2400: btype = "2422"; break; default: break; } - /* - * While we're paused, reset the FPM module and FBM fifos. - */ - ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); - ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); - ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + + if (!IS_24XX(isp)) { + /* + * While we're paused, reset the FPM module and FBM + * fifos. + */ + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); + ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); + ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + } } else if (IS_1240(isp)) { sdparam *sdp = isp->isp_param; btype = "1240"; @@ -443,8 +487,6 @@ isp_reset(ispsoftc_t *isp) */ ISP_RESET0(isp); -again: - /* * Hit the chip over the head with hammer, * and give the ISP a chance to recover. @@ -466,6 +508,42 @@ again: DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT); + } else if (IS_24XX(isp)) { + /* + * Stop DMA and wait for it to stop. + */ + ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4)); + for (val = loops = 0; loops < 30000; loops++) { + USEC_DELAY(10); + val = ISP_READ(isp, BIU2400_CSR); + if ((val & BIU2400_DMA_ACTIVE) == 0) { + break; + } + } + if (val & BIU2400_DMA_ACTIVE) { + isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset"); + return; + } + /* + * Hold it in SOFT_RESET and STOP state for 100us. + */ + ISP_WRITE(isp, BIU2400_CSR, + BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4)); + USEC_DELAY(100); + for (loops = 0; loops < 10000; loops++) { + USEC_DELAY(5); + val = ISP_READ(isp, OUTMAILBOX0); + } + for (val = loops = 0; loops < 500000; loops ++) { + val = ISP_READ(isp, BIU2400_CSR); + if ((val & BIU2400_SOFT_RESET) == 0) { + break; + } + } + if (val & BIU2400_SOFT_RESET) { + isp_prt(isp, ISP_LOGERR, "Failed to come out of reset"); + return; + } } else { ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET); /* @@ -490,8 +568,13 @@ again: loops = MBOX_DELAY_COUNT; for (;;) { if (IS_SCSI(isp)) { - if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET)) + if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET)) { break; + } + } else if (IS_24XX(isp)) { + if (ISP_READ(isp, OUTMAILBOX0) == 0) { + break; + } } else { if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET)) break; @@ -510,24 +593,40 @@ again: if (IS_SCSI(isp)) { ISP_WRITE(isp, BIU_CONF1, 0); - } else { + } else if (!IS_24XX(isp)) { ISP_WRITE(isp, BIU2100_CSR, 0); } /* * Reset RISC Processor */ - ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); - USEC_DELAY(100); - /* Clear semaphore register (just to be sure) */ - ISP_WRITE(isp, BIU_SEMA, 0); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); + USEC_DELAY(100); + ISP_WRITE(isp, BIU_SEMA, 0); + } + /* - * Establish some initial burst rate stuff. - * (only for the 1XX0 boards). This really should - * be done later after fetching from NVRAM. + * Post-RISC Reset stuff. */ - if (IS_SCSI(isp)) { + if (IS_24XX(isp)) { + for (val = loops = 0; loops < 5000000; loops++) { + USEC_DELAY(5); + val = ISP_READ(isp, OUTMAILBOX0); + if (val == 0) { + break; + } + } + if (val != 0) { + isp_prt(isp, ISP_LOGERR, "reset didn't clear"); + return; + } + } else if (IS_SCSI(isp)) { uint16_t tmp = isp->isp_mdvec->dv_conf1; /* * Busted FIFO. Turn off all but burst enables. @@ -540,15 +639,36 @@ again: ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST); ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST); } - ISP_WRITE(isp, RISC_MTR, 0x1212); + if (SDPARAM(isp)->isp_ptisp) { + if (SDPARAM(isp)->isp_ultramode) { + while (ISP_READ(isp, RISC_MTR) != 0x1313) { + ISP_WRITE(isp, RISC_MTR, 0x1313); + ISP_WRITE(isp, HCCR, HCCR_CMD_STEP); + } + } else { + ISP_WRITE(isp, RISC_MTR, 0x1212); + } + /* + * PTI specific register + */ + ISP_WRITE(isp, RISC_EMB, DUAL_BANK); + } else { + ISP_WRITE(isp, RISC_MTR, 0x1212); + } + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); } else { ISP_WRITE(isp, RISC_MTR2100, 0x1212); if (IS_2200(isp) || IS_23XX(isp)) { ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE); } + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); } - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */ + ISP_WRITE(isp, isp->isp_rqstinrp, 0); + ISP_WRITE(isp, isp->isp_rqstoutrp, 0); + ISP_WRITE(isp, isp->isp_respinrp, 0); + ISP_WRITE(isp, isp->isp_respoutrp, 0); + /* * Do MD specific post initialization @@ -561,8 +681,8 @@ again: * Avoid doing this on the 2312 because you can generate a PCI * parity error (chip breakage). */ - if (IS_23XX(isp)) { - USEC_DELAY(5); + if (IS_2312(isp)) { + USEC_DELAY(100); } else { loops = MBOX_DELAY_COUNT; while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) { @@ -586,12 +706,13 @@ again: */ MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_NO_OP; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } - if (IS_SCSI(isp)) { + if (IS_SCSI(isp) || IS_24XX(isp)) { MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_MAILBOX_REG_TEST; mbs.param[1] = 0xdead; @@ -599,7 +720,10 @@ again: mbs.param[3] = 0xffff; mbs.param[4] = 0x1111; mbs.param[5] = 0xa5a5; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.param[6] = 0x0000; + mbs.param[7] = 0x0000; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -629,12 +753,170 @@ again: dodnld = 0; } - if (IS_23XX(isp)) { + if (IS_24XX(isp)) { + code_org = ISP_CODE_ORG_2400; + } else if (IS_23XX(isp)) { code_org = ISP_CODE_ORG_2300; } else { code_org = ISP_CODE_ORG; } - if (dodnld) { + + if (dodnld && IS_24XX(isp)) { + uint32_t *ptr = isp->isp_mdvec->dv_ispfw; + + /* + * NB: Whatever you do do, do *not* issue the VERIFY FIRMWARE + * NB: command to the 2400 while loading new firmware. This + * NB: causes the new f/w to start and immediately crash back + * NB: to the ROM. + */ + + /* + * Keep loading until we run out of f/w. + */ + code_org = ptr[2]; /* 1st load address is our start addr */ + + for (;;) { + uint32_t la, wi, wl; + + isp_prt(isp, ISP_LOGDEBUG0, + "load 0x%x words of code at load address 0x%x", + ptr[3], ptr[2]); + + wi = 0; + la = ptr[2]; + wl = ptr[3]; + + while (wi < ptr[3]) { + uint32_t *cp; + uint32_t nw; + + nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 2; + if (nw > wl) { + nw = wl; + } + cp = isp->isp_rquest; + for (i = 0; i < nw; i++) { + cp[i] = ptr[wi++]; + wl--; + } + MEMORYBARRIER(isp, SYNC_REQUEST, + 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp))); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_LOAD_RISC_RAM; + mbs.param[1] = la; + mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); + mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); + mbs.param[4] = nw >> 16; + mbs.param[5] = nw; + mbs.param[6] = DMA_WD3(isp->isp_rquest_dma); + mbs.param[7] = DMA_WD2(isp->isp_rquest_dma); + mbs.param[8] = la >> 16; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, + "F/W Risc Ram Load Failed"); + return; + } + la += nw; + } + + if (ptr[1] == 0) { + break; + } + ptr += ptr[3]; + } + isp->isp_loaded_fw = 1; + } else if (dodnld && IS_23XX(isp)) { + uint16_t *ptr = isp->isp_mdvec->dv_ispfw; + uint16_t wi, wl, segno; + uint32_t la; + + la = code_org; + segno = 0; + + for (;;) { + uint32_t nxtaddr; + + isp_prt(isp, ISP_LOGDEBUG0, + "load 0x%x words of code at load address 0x%x", + ptr[3], la); + + wi = 0; + wl = ptr[3]; + + while (wi < ptr[3]) { + uint16_t *cp; + uint32_t nw; + + nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 1; + if (nw > wl) { + nw = wl; + } + if (nw > (1 << 15)) { + nw = 1 << 15; + } + cp = isp->isp_rquest; + for (i = 0; i < nw; i++) { + cp[i] = ptr[wi++]; + wl--; + } + MEMORYBARRIER(isp, SYNC_REQUEST, + 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp))); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_LOAD_RISC_RAM; + mbs.param[1] = la; + mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); + mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); + mbs.param[4] = nw; + mbs.param[6] = DMA_WD3(isp->isp_rquest_dma); + mbs.param[7] = DMA_WD2(isp->isp_rquest_dma); + mbs.param[8] = la >> 16; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, + "F/W Risc Ram Load Failed"); + return; + } + la += nw; + } + + if (!IS_2322(isp)) { + /* + * Verify that it downloaded correctly. + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_VERIFY_CHECKSUM; + mbs.param[1] = code_org; + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, dcrc); + return; + } + break; + } + + if (++segno == 3) { + break; + } + + /* + * If we're a 2322, the firmware actually comes in + * three chunks. We loaded the first at the code_org + * address. The other two chunks, which follow right + * after each other in memory here, get loaded at + * addresses specfied at offset 0x9..0xB. + */ + + nxtaddr = ptr[3]; + ptr = &ptr[nxtaddr]; + la = ptr[5] | ((ptr[4] & 0x3f) << 16); + } + isp->isp_loaded_fw = 1; + } else if (dodnld) { uint16_t *ptr = isp->isp_mdvec->dv_ispfw; isp->isp_mbxworkp = &ptr[1]; @@ -644,76 +926,25 @@ again: mbs.param[0] = MBOX_WRITE_RAM_WORD; mbs.param[1] = code_org; mbs.param[2] = ptr[0]; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org); - dodnld = 0; - goto again; + return; } - /* - * If we're a 2322, the firmware actually comes in three chunks. - * We loaded the first at the code_org address. The other two - * chunks, which follow right after each other in memory here, - * get loaded at addresses specfied at offset 0x9..0xB. + * Verify that it downloaded correctly. */ - if (IS_2322(isp)) { - uint32_t nxtaddr; - uint32_t offset; - - nxtaddr = ptr[3]; - ptr = &ptr[nxtaddr]; - offset = ptr[5] | (((uint32_t)(ptr[4] & 0x3f)) << 16); - isp->isp_mbxworkp = &ptr[1]; - isp->isp_mbxwrk0 = ptr[3] - 1; - isp->isp_mbxwrk1 = offset + 1; - isp->isp_mbxwrk8 = (offset + 1) >> 16; - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED; - mbs.param[1] = offset; - mbs.param[2] = ptr[0]; - mbs.param[8] = offset >> 16; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, - "Receive Sequencer F/W Load Failed"); - return; - } - - nxtaddr = ptr[3]; - ptr = &ptr[nxtaddr]; - offset = ptr[5] | (((uint32_t)(ptr[4] & 0x3f)) << 16); - isp->isp_mbxworkp = &ptr[1]; - isp->isp_mbxwrk0 = ptr[3] - 1; - isp->isp_mbxwrk1 = (offset + 1); - isp->isp_mbxwrk8 = (offset + 1) >> 16; - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED; - mbs.param[1] = offset; - mbs.param[2] = ptr[0]; - mbs.param[8] = offset >> 16; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, - "Transmit Sequencer F/W Load Failed"); - return; - } - } else { - /* - * Verify that it downloaded correctly. - */ - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_VERIFY_CHECKSUM; - mbs.param[1] = code_org; - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, - "Downloaded RISC Code Checksum Failure"); - return; - } - + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_VERIFY_CHECKSUM; + mbs.param[1] = code_org; + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, dcrc); + return; } isp->isp_loaded_fw = 1; } else { @@ -730,28 +961,39 @@ again: MEMZERO(&mbs, sizeof (mbs)); + mbs.timeout = 1000000; mbs.param[0] = MBOX_EXEC_FIRMWARE; - mbs.param[1] = code_org; - if (IS_2322(isp) || IS_24XX(isp)) { + if (IS_24XX(isp)) { + mbs.param[1] = code_org >> 16; + mbs.param[2] = code_org; + if (isp->isp_loaded_fw) { + mbs.param[3] = 0; + } else { + mbs.param[3] = 1; + } + } else if (IS_2322(isp)) { + mbs.param[1] = code_org; if (isp->isp_loaded_fw) { mbs.param[2] = 0; } else { mbs.param[2] = 1; } + } else { + mbs.param[1] = code_org; } - isp_mboxcmd(isp, &mbs, MBLOGNONE); + + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (IS_2322(isp) || IS_24XX(isp)) { if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "EXEC F/W failed: 0x%x", - mbs.param[0]); return; } } /* - * Give it a chance to start. + * Give it a chance to finish starting up. */ - USEC_DELAY(500); + USEC_DELAY(250000); if (IS_SCSI(isp)) { /* @@ -760,18 +1002,25 @@ again: if (isp->isp_clock) { mbs.param[0] = MBOX_SET_CLOCK_RATE; mbs.param[1] = isp->isp_clock; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); /* we will try not to care if this fails */ } } MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } + if (IS_24XX(isp) && mbs.param[1] == 0xdead) { + isp_prt(isp, ISP_LOGERR, "f/w didn't *really* start"); + return; + } + /* * The SBus firmware that we are using apparently does not return * major, minor, micro revisions in the mailbox registers, which @@ -794,7 +1043,7 @@ again: isp->isp_fwrev[2] = mbs.param[3]; } - isp_prt(isp, ISP_LOGCONFIG, + isp_prt(isp, ISP_LOGALL, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d", btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]); @@ -805,9 +1054,9 @@ again: * than 1.17.0, unless it's the firmware we specifically * are loading. * - * Note that all 22XX and 23XX f/w is greater than 1.X.0. + * Note that all 22XX and later f/w is greater than 1.X.0. */ - if (!(ISP_FW_NEWER_THAN(isp, 1, 17, 0))) { + if ((ISP_FW_OLDER_THAN(isp, 1, 17, 1))) { #ifdef USE_SMALLER_2100_FIRMWARE FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN; #else @@ -818,7 +1067,26 @@ again: isp_prt(isp, ISP_LOGDEBUG0, "Firmware Attributes = 0x%x", mbs.param[6]); } - if (IS_2KLOGIN(isp)) { + FCPARAM(isp)->isp_2klogin = 0; + FCPARAM(isp)->isp_sccfw = 0; + FCPARAM(isp)->isp_tmode = 0; + if (IS_24XX(isp)) { + FCPARAM(isp)->isp_2klogin = 1; + FCPARAM(isp)->isp_sccfw = 1; + FCPARAM(isp)->isp_tmode = 1; + } else { + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + FCPARAM(isp)->isp_sccfw = 1; + } + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS) { + FCPARAM(isp)->isp_2klogin = 1; + FCPARAM(isp)->isp_sccfw = 1; + } + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) { + FCPARAM(isp)->isp_tmode = 1; + } + } + if (FCPARAM(isp)->isp_2klogin) { isp_prt(isp, ISP_LOGCONFIG, "2K Logins Supported"); } } @@ -830,24 +1098,22 @@ again: isp->isp_romfw_rev[2]); } - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_GET_FIRMWARE_STATUS; - isp_mboxcmd(isp, &mbs, MBLOGALL); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - return; + if (!IS_24XX(isp)) { + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_GET_FIRMWARE_STATUS; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + if (isp->isp_maxcmds >= mbs.param[2]) { + isp->isp_maxcmds = mbs.param[2]; + } } - isp->isp_maxcmds = mbs.param[2]; - isp_prt(isp, ISP_LOGINFO, - "%d max I/O commands supported", mbs.param[2]); + isp_prt(isp, ISP_LOGCONFIG, + "%d max I/O command limit set", isp->isp_maxcmds); isp_fw_state(isp); - /* - * Set up DMA for the request and result mailboxes. - */ - if (ISP_MBOXDMASETUP(isp) != 0) { - isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); - return; - } isp->isp_state = ISP_RESETSTATE; /* @@ -878,7 +1144,7 @@ again: isp->isp_maxluns = 8; } } else { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { isp->isp_maxluns = 16384; } else { isp->isp_maxluns = 16; @@ -902,8 +1168,22 @@ isp_init(ispsoftc_t *isp) if (IS_DUALBUS(isp)) { isp_setdfltparm(isp, 1); } + if (IS_FC(isp)) { - isp_fibre_init(isp); + /* + * Do this *before* initializing the firmware. + */ + isp_mark_portdb(isp, 0); + FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; + FCPARAM(isp)->isp_loopstate = LOOP_NIL; + + if (isp->isp_role != ISP_ROLE_NONE) { + if (IS_24XX(isp)) { + isp_fibre_init_2400(isp); + } else { + isp_fibre_init(isp); + } + } } else { isp_scsi_init(isp); } @@ -947,8 +1227,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[2] = sdp_chan0->isp_retry_delay; mbs.param[6] = sdp_chan1->isp_retry_count; mbs.param[7] = sdp_chan1->isp_retry_delay; - - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -960,7 +1240,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME; mbs.param[1] = sdp_chan0->isp_async_data_setup; mbs.param[2] = sdp_chan1->isp_async_data_setup; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -976,9 +1257,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[2] = (sdp_chan1->isp_req_ack_active_neg << 4) | (sdp_chan1->isp_data_line_active_neg << 5); - - MEMZERO(&mbs, sizeof (mbs)); - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "failed to set active negation state (%d,%d), (%d,%d)", @@ -998,7 +1278,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[0] = MBOX_SET_TAG_AGE_LIMIT; mbs.param[1] = sdp_chan0->isp_tag_aging; mbs.param[2] = sdp_chan1->isp_tag_aging; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)", sdp_chan0->isp_tag_aging, sdp_chan1->isp_tag_aging); @@ -1012,7 +1293,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[0] = MBOX_SET_SELECT_TIMEOUT; mbs.param[1] = sdp_chan0->isp_selection_timeout; mbs.param[2] = sdp_chan1->isp_selection_timeout; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1035,7 +1317,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[4] = 0; mbs.param[6] = DMA_WD3(isp->isp_result_dma); mbs.param[7] = DMA_WD2(isp->isp_result_dma); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1049,7 +1332,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[5] = 0; mbs.param[6] = DMA_WD3(isp->isp_result_dma); mbs.param[7] = DMA_WD2(isp->isp_result_dma); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1061,7 +1345,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[2] = DMA_WD1(isp->isp_result_dma); mbs.param[3] = DMA_WD0(isp->isp_result_dma); mbs.param[4] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1073,7 +1358,8 @@ isp_scsi_init(ispsoftc_t *isp) mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); mbs.param[5] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1103,7 +1389,8 @@ isp_scsi_init(ispsoftc_t *isp) #endif if (mbs.param[1] != 0) { uint16_t sfeat = mbs.param[1]; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGINFO, "Enabled FW features (0x%x)", sfeat); @@ -1132,7 +1419,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel) MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_SET_INIT_SCSI_ID; mbs.param[1] = (channel << 7) | sdp->isp_initiator_id; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } @@ -1188,7 +1476,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel) "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x", channel, tgt, mbs.param[2], mbs.param[3] >> 8, mbs.param[3] & 0xff); - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { sdf = DPARM_SAFE_DFLT; MEMZERO(&mbs, sizeof (mbs)); @@ -1196,7 +1485,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel) mbs.param[1] = (tgt << 8) | (channel << 15); mbs.param[2] = sdf; mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { continue; } @@ -1220,7 +1510,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel) mbs.param[1] = (channel << 15) | (tgt << 8) | lun; mbs.param[2] = sdp->isp_max_queue_depth; mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -1237,8 +1528,6 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel) /* * Fibre Channel specific initialization. - * - * Locks are held before coming here. */ static void isp_fibre_init(ispsoftc_t *isp) @@ -1246,28 +1535,13 @@ isp_fibre_init(ispsoftc_t *isp) fcparam *fcp; isp_icb_t local, *icbp = &local; mbreg_t mbs; - int loopid; uint64_t nwwn, pwwn; fcp = isp->isp_param; - /* - * Do this *before* initializing the firmware. - */ - isp_mark_getpdb_all(isp); - fcp->isp_fwstate = FW_CONFIG_WAIT; - fcp->isp_loopstate = LOOP_NIL; - - /* - * If we have no role (neither target nor initiator), return. - */ - if (isp->isp_role == ISP_ROLE_NONE) { - return; - } - - loopid = fcp->isp_loopid; MEMZERO(icbp, sizeof (*icbp)); icbp->icb_version = ICB_VERSION1; + icbp->icb_fwoptions = fcp->isp_fwoptions; /* * Firmware Options are either retrieved from NVRAM or @@ -1279,8 +1553,8 @@ isp_fibre_init(ispsoftc_t *isp) /* * If this is a 2100 < revision 5, we have to turn off FAIRNESS. */ - if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) { - fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS; + if (IS_2100(isp) && isp->isp_revision < 5) { + icbp->icb_fwoptions &= ~ICBOPT_FAIRNESS; } /* @@ -1289,33 +1563,29 @@ isp_fibre_init(ispsoftc_t *isp) * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0. */ if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) { - fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; + icbp->icb_fwoptions |= ICBOPT_FULL_LOGIN; } /* * Insist on Port Database Update Async notifications */ - fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; + icbp->icb_fwoptions |= ICBOPT_PDBCHANGE_AE; /* * Make sure that target role reflects into fwoptions. */ if (isp->isp_role & ISP_ROLE_TARGET) { - fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE; + icbp->icb_fwoptions |= ICBOPT_TGT_ENABLE; } else { - fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE; + icbp->icb_fwoptions &= ~ICBOPT_TGT_ENABLE; } if (isp->isp_role & ISP_ROLE_INITIATOR) { - fcp->isp_fwoptions &= ~ICBOPT_INI_DISABLE; + icbp->icb_fwoptions &= ~ICBOPT_INI_DISABLE; } else { - fcp->isp_fwoptions |= ICBOPT_INI_DISABLE; + icbp->icb_fwoptions |= ICBOPT_INI_DISABLE; } - /* - * Propagate all of this into the ICB structure. - */ - icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { @@ -1339,7 +1609,7 @@ isp_fibre_init(ispsoftc_t *isp) } icbp->icb_retry_delay = fcp->isp_retry_delay; icbp->icb_retry_count = fcp->isp_retry_count; - icbp->icb_hardaddr = loopid; + icbp->icb_hardaddr = fcp->isp_loopid; if (icbp->icb_hardaddr > 125) { /* * We end up with these Loop IDs for F-Port topologies @@ -1434,7 +1704,11 @@ isp_fibre_init(ispsoftc_t *isp) mbs.param[1] = 0xb; mbs.param[2] = 0; mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } } icbp->icb_logintime = ICB_LOGIN_TOV; icbp->icb_lunetimeout = ICB_LUN_ENABLE_TOV; @@ -1451,9 +1725,16 @@ isp_fibre_init(ispsoftc_t *isp) ((uint32_t) (nwwn & 0xffffffff)), ((uint32_t) (pwwn >> 32)), ((uint32_t) (pwwn & 0xffffffff))); + } else if (pwwn) { + icbp->icb_fwoptions &= ~ICBOPT_BOTH_WWNS; + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn); + isp_prt(isp, ISP_LOGDEBUG1, + "Setting ICB Port 0x%08x%08x", + ((uint32_t) (pwwn >> 32)), + ((uint32_t) (pwwn & 0xffffffff))); } else { - isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs"); - icbp->icb_fwoptions &= ~(ICBOPT_BOTH_WWNS|ICBOPT_FULL_LOGIN); + isp_prt(isp, ISP_LOGERR, "No valid WWNs to use"); + return; } icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); if (icbp->icb_rqstqlen < 1) { @@ -1488,18 +1769,20 @@ isp_fibre_init(ispsoftc_t *isp) mbs.param[3] = DMA_WD0(fcp->isp_scdma); mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); + mbs.logval = MBLOGALL; + mbs.timeout = 30 * 1000000; isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %p (%08x%08x)", fcp->isp_scratch, (uint32_t) ((uint64_t)fcp->isp_scdma >> 32), (uint32_t) fcp->isp_scdma); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp)); - isp_mboxcmd(isp, &mbs, MBLOGALL); + isp_mboxcmd(isp, &mbs); FC_SCRATCH_RELEASE(isp); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; } - isp->isp_reqidx = isp->isp_reqodx = 0; + isp->isp_reqidx = 0; + isp->isp_reqodx = 0; isp->isp_residx = 0; - isp->isp_sendmarker = 1; /* * Whatever happens, we're now committed to being here. @@ -1507,59 +1790,565 @@ isp_fibre_init(ispsoftc_t *isp) isp->isp_state = ISP_INITSTATE; } -/* - * Fibre Channel Support- get the port database for the id. - * - * Locks are held before coming here. Return 0 if success, - * else failure. - */ - -static int -isp_getmap(ispsoftc_t *isp, fcpos_map_t *map) +static void +isp_fibre_init_2400(ispsoftc_t *isp) { - fcparam *fcp = (fcparam *) isp->isp_param; + fcparam *fcp; + isp_icb_2400_t local, *icbp = &local; mbreg_t mbs; + uint64_t nwwn, pwwn; + + fcp = isp->isp_param; + + /* + * Turn on LIP F8 async event (1) + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS; + mbs.param[1] = 1; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + + /* + * XXX: This should be applied to icb- not fwoptions + */ + if (isp->isp_role & ISP_ROLE_TARGET) { + fcp->isp_fwoptions |= ICB2400_OPT1_TGT_ENABLE; + } else { + fcp->isp_fwoptions &= ~ICB2400_OPT1_TGT_ENABLE; + } + + if (isp->isp_role & ISP_ROLE_INITIATOR) { + fcp->isp_fwoptions &= ~ICB2400_OPT1_INI_DISABLE; + } else { + fcp->isp_fwoptions |= ICB2400_OPT1_INI_DISABLE; + } + + MEMZERO(icbp, sizeof (*icbp)); + icbp->icb_version = ICB_VERSION1; + icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; + if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || + icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) { + isp_prt(isp, ISP_LOGERR, + "bad frame length (%d) from NVRAM- using %d", + fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN); + icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN; + } + + icbp->icb_execthrottle = fcp->isp_execthrottle; + if (icbp->icb_execthrottle < 1) { + isp_prt(isp, ISP_LOGERR, + "bad execution throttle of %d- using 16", + fcp->isp_execthrottle); + icbp->icb_execthrottle = ICB_DFLT_THROTTLE; + } + + if (isp->isp_role & ISP_ROLE_TARGET) { + /* + * Get current resource count + */ + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_GET_RESOURCE_COUNT; + mbs.obits = 0x4cf; + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + icbp->icb_xchgcnt = mbs.param[3]; + } + + icbp->icb_fwoptions1 = fcp->isp_fwoptions; + + icbp->icb_hardaddr = fcp->isp_loopid; + if (icbp->icb_hardaddr > 125) { + /* + * We end up with these Loop IDs for F-Port topologies + */ + if (icbp->icb_hardaddr != 0xff && icbp->icb_hardaddr != 0x800) { + isp_prt(isp, ISP_LOGERR, + "bad hard address %u- resetting to zero", + icbp->icb_hardaddr); + icbp->icb_hardaddr = 0; + } + } + + if (isp->isp_confopts & ISP_CFG_OWNLOOPID) { + icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS; + } + + icbp->icb_fwoptions2 = fcp->isp_xfwoptions; + switch(isp->isp_confopts & ISP_CFG_PORT_PREF) { + case ISP_CFG_NPORT: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP; + break; + case ISP_CFG_NPORT_ONLY: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY; + break; + case ISP_CFG_LPORT_ONLY: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY; + break; + default: + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; + icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP; + break; + } + + switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) { + case ICB2400_OPT2_ZIO: + case ICB2400_OPT2_ZIO1: + icbp->icb_idelaytimer = 0; + break; + case 0: + break; + default: + isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", + icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK); + icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK; + break; + } + + icbp->icb_fwoptions3 = fcp->isp_zfwoptions; + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO; + if (isp->isp_confopts & ISP_CFG_ONEGB) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_ONEGB; + } else if (isp->isp_confopts & ISP_CFG_TWOGB) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_TWOGB; + } else if (isp->isp_confopts & ISP_CFG_FOURGB) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_FOURGB; + } else { + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO; + } + + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { + icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID; + } + icbp->icb_logintime = ICB_LOGIN_TOV; + + nwwn = ISP_NODEWWN(isp); + pwwn = ISP_PORTWWN(isp); + if (nwwn && pwwn) { + icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS; + MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn); + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn); + isp_prt(isp, ISP_LOGDEBUG1, + "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", + ((uint32_t) (nwwn >> 32)), + ((uint32_t) (nwwn & 0xffffffff)), + ((uint32_t) (pwwn >> 32)), + ((uint32_t) (pwwn & 0xffffffff))); + } else if (pwwn) { + icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS; + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn); + isp_prt(isp, ISP_LOGDEBUG1, + "Setting ICB Port 0x%08x%08x", + ((uint32_t) (pwwn >> 32)), + ((uint32_t) (pwwn & 0xffffffff))); + } else { + isp_prt(isp, ISP_LOGERR, "No valid WWNs to use"); + return; + } + icbp->icb_retry_count = fcp->isp_retry_count; + + icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); + if (icbp->icb_rqstqlen < 8) { + isp_prt(isp, ISP_LOGERR, "bad request queue length %d", + icbp->icb_rqstqlen); + return; + } + icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); + if (icbp->icb_rsltqlen < 8) { + isp_prt(isp, ISP_LOGERR, "bad result queue length %d", + icbp->icb_rsltqlen); + return; + } + icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma); + + icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); + +#ifdef ISP_TARGET_MODE + if (isp->isp_role & ISP_ROLE_TARGET) { + icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp); + if (icbp->icb_atioqlen < 8) { + isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", + icbp->icb_atioqlen); + return; + } + icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma); + icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma); + icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma); + icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma); + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init_2400: atioq %04x%04x%04x%04x", + DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma), + DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma)); + } +#endif + + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init_2400: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", + icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3); + + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init_2400: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", + DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma), + DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), + DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma), + DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma)); + + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "isp_fibre_init_2400", sizeof (*icbp), + icbp); + } + FC_SCRATCH_ACQUIRE(isp); + isp_put_icb_2400(isp, icbp, fcp->isp_scratch); + + + /* + * Init the firmware + */ MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP; + mbs.param[0] = MBOX_INIT_FIRMWARE; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); - FC_SCRATCH_ACQUIRE(isp); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (fcpos_map_t)); - isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - MEMCPY(map, fcp->isp_scratch, sizeof (fcpos_map_t)); - map->fwmap = mbs.param[1] != 0; - FC_SCRATCH_RELEASE(isp); - return (0); - } + mbs.logval = MBLOGALL; + mbs.timeout = 30 * 1000000; + isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", + DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), + DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma)); + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp)); + isp_mboxcmd(isp, &mbs); FC_SCRATCH_RELEASE(isp); - return (-1); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return; + } + isp->isp_reqidx = 0; + isp->isp_reqodx = 0; + isp->isp_residx = 0; + + /* + * Whatever happens, we're now committed to being here. + */ + isp->isp_state = ISP_INITSTATE; +} + +/* + * Fibre Channel Support- get the port database for the id. + */ +static void +isp_dump_portdb(ispsoftc_t *isp) +{ + fcparam *fcp = (fcparam *) isp->isp_param; + int i; + + for (i = 0; i < MAX_FC_TARG; i++) { + char mb[4]; + const char *dbs[8] = { + "NIL ", + "PROB", + "DEAD", + "CHGD", + "NEW ", + "PVLD", + "????", + "VLD " + }; + const char *roles[4] = { + " UNK", " TGT", " INI", "TINI" + }; + fcportdb_t *lp = &fcp->portdb[i]; + + if (lp->state == FC_PORTDB_STATE_NIL) { + continue; + } + if (lp->ini_map_idx) { + SNPRINTF(mb, sizeof (mb), "%3d", + ((int) lp->ini_map_idx) - 1); + } else { + SNPRINTF(mb, sizeof (mb), "---"); + } + isp_prt(isp, ISP_LOGALL, "%d: %s al%d tgt %s %s 0x%06x =>%s" + " 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x", i, + dbs[lp->state], lp->autologin, mb, + roles[lp->roles], lp->portid, + roles[lp->new_roles], lp->new_portid, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) (lp->node_wwn), + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) (lp->port_wwn)); + } } static void -isp_mark_getpdb_all(ispsoftc_t *isp) +isp_mark_portdb(ispsoftc_t *isp, int onprobation) { fcparam *fcp = (fcparam *) isp->isp_param; int i; + for (i = 0; i < MAX_FC_TARG; i++) { - fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0; + fcp->isp_ini_map[i] = 0; + if (onprobation == 0) { + MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); + } else { + switch (fcp->portdb[i].state) { + case FC_PORTDB_STATE_CHANGED: + case FC_PORTDB_STATE_PENDING_VALID: + case FC_PORTDB_STATE_VALID: + case FC_PORTDB_STATE_PROBATIONAL: + fcp->portdb[i].state = + FC_PORTDB_STATE_PROBATIONAL; + break; + case FC_PORTDB_STATE_NIL: + default: + MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); + fcp->portdb[i].state = + FC_PORTDB_STATE_NIL; + break; + } + } + } +} + +/* + * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards + */ +static void +isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) +{ + mbreg_t mbs; + uint8_t q[QENTRY_LEN]; + isp_plogx_t *plp = (isp_plogx_t *) q; + uint8_t *scp = FCPARAM(isp)->isp_scratch; + uint32_t sst, parm1; + int junk; + + MEMZERO(q, QENTRY_LEN); + plp->plogx_header.rqs_entry_count = 1; + plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN; + plp->plogx_handle = 0xffffffff; + plp->plogx_nphdl = handle; + plp->plogx_portlo = portid; + plp->plogx_rspsz_porthi = (portid >> 16) & 0xff; + if (log_ret) { + plp->plogx_flags = *log_ret; + } else { + log_ret = &junk; + } + + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp); + } + /* + * XXX: We're going to assume somebody has acquired SCRATCH for us + */ + isp_put_plogx(isp, plp, (isp_plogx_t *) scp); + + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64; + mbs.param[1] = QENTRY_LEN; + mbs.param[2] = DMA_WD1(FCPARAM(isp)->isp_scdma); + mbs.param[3] = DMA_WD0(FCPARAM(isp)->isp_scdma); + mbs.param[6] = DMA_WD3(FCPARAM(isp)->isp_scdma); + mbs.param[7] = DMA_WD2(FCPARAM(isp)->isp_scdma); + mbs.logval = MBLOGALL; + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + *log_ret = mbs.param[0]; + } + MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN); + scp += QENTRY_LEN; + isp_get_plogx(isp, (isp_plogx_t *) scp, plp); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, plp); + } + + if (plp->plogx_status == PLOGX_STATUS_OK) { + *log_ret = 0; + return; + } else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) { + isp_prt(isp, ISP_LOGWARN, "status 0x%x on port login IOCB", + plp->plogx_status); + *log_ret = -1; + return; + } + + sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16); + parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16); + + *log_ret = -1; + + switch (sst) { + case PLOGX_IOCBERR_NOLINK: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no link"); + break; + case PLOGX_IOCBERR_NOIOCB: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no IOCB buffer"); + break; + case PLOGX_IOCBERR_NOXGHG: + isp_prt(isp, ISP_LOGERR, + "PLOGX failed- no Exchange Control Block"); + break; + case PLOGX_IOCBERR_FAILED: + isp_prt(isp, ISP_LOGERR, + "PLOGX(0x%x) of Port 0x%06x failed: reason 0x%x (last LOGIN" + " state 0x%x)", *log_ret, portid, + parm1 & 0xff, (parm1 >> 8) & 0xff); + break; + case PLOGX_IOCBERR_NOFABRIC: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no fabric"); + break; + case PLOGX_IOCBERR_NOTREADY: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- f/w not ready"); + break; + case PLOGX_IOCBERR_NOLOGIN: + isp_prt(isp, ISP_LOGERR, + "PLOGX failed- not logged in (last LOGIN state 0x%x)", + parm1); + *log_ret = MBOX_NOT_LOGGED_IN; + break; + case PLOGX_IOCBERR_REJECT: + isp_prt(isp, ISP_LOGERR, "PLOGX failed: LS_RJT = 0x%x", parm1); + break; + case PLOGX_IOCBERR_NOPCB: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no PCB allocated"); + break; + case PLOGX_IOCBERR_EINVAL: + isp_prt(isp, ISP_LOGERR, + "PLOGX failed: invalid parameter at offset 0x%x", parm1); + break; + case PLOGX_IOCBERR_PORTUSED: + isp_prt(isp, ISP_LOGDEBUG0, + "portid 0x%x already logged in with N-port handle 0x%x", + portid, parm1); + *log_ret = MBOX_PORT_ID_USED | (handle << 16); + break; + case PLOGX_IOCBERR_HNDLUSED: + isp_prt(isp, ISP_LOGDEBUG0, + "N-port handle 0x%x already used for portid 0x%x", + handle, parm1); + *log_ret = MBOX_LOOP_ID_USED; + break; + case PLOGX_IOCBERR_NOHANDLE: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no handle allocated"); + break; + case PLOGX_IOCBERR_NOFLOGI: + isp_prt(isp, ISP_LOGERR, "PLOGX failed- no FLOGI_ACC"); + break; + default: + isp_prt(isp, ISP_LOGERR, "status %x from %s", plp->plogx_status, + (*log_ret)? "PLOGI" : "LOGO"); + *log_ret = -1; + break; } } static int -isp_getpdb(ispsoftc_t *isp, int id, isp_pdb_t *pdbp) +isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid) +{ + mbreg_t mbs; + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_FABRIC_LOGIN; + if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = handle; + mbs.ibits = (1 << 10); + } else { + mbs.param[1] = handle << 8; + } + mbs.param[2] = portid >> 16; + mbs.param[3] = portid; + + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); + + switch (mbs.param[0]) { + case MBOX_PORT_ID_USED: + isp_prt(isp, ISP_LOGDEBUG0, + "isp_port_login: portid 0x%06x already logged in as %u", + portid, mbs.param[1]); + return (MBOX_PORT_ID_USED | (mbs.param[1] << 16)); + break; + + case MBOX_LOOP_ID_USED: + isp_prt(isp, ISP_LOGDEBUG0, + "isp_port_login: handle %u in use for port id 0x%02xXXXX", + handle, mbs.param[1] & 0xff); + return (MBOX_LOOP_ID_USED); + + case MBOX_COMMAND_COMPLETE: + return (0); + + case MBOX_COMMAND_ERROR: + isp_prt(isp, ISP_LOGINFO, + "isp_port_login: error 0x%x in PLOGI to port 0x%06x", + mbs.param[1], portid); + return (MBOX_COMMAND_ERROR); + + case MBOX_ALL_IDS_USED: + isp_prt(isp, ISP_LOGINFO, + "isp_port_login: all IDs used for fabric login"); + return (MBOX_ALL_IDS_USED); + + default: + isp_prt(isp, ISP_LOGINFO, + "isp_port_login: error 0x%x on port login of 0x%06x@0x%0x", + mbs.param[0], portid, handle); + return (mbs.param[0]); + } +} + +static void +isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid) +{ + mbreg_t mbs; + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_FABRIC_LOGOUT; + if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = handle; + mbs.ibits = (1 << 10); + } else { + mbs.param[1] = handle << 8; + } + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); +} + +static int +isp_getpdb(ispsoftc_t *isp, uint16_t id, isp_pdb_t *pdb, int dolock) { fcparam *fcp = (fcparam *) isp->isp_param; mbreg_t mbs; + union { + isp_pdb_21xx_t fred; + isp_pdb_24xx_t bill; + } un; MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_PORT_DB; - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + mbs.ibits = 0x3ff; mbs.param[1] = id; - mbs.ibits |= (1 << 10); + } else if (FCPARAM(isp)->isp_2klogin) { + mbs.param[1] = id; + mbs.ibits = (1 << 10); } else { mbs.param[1] = id << 8; } @@ -1567,29 +2356,50 @@ isp_getpdb(ispsoftc_t *isp, int id, isp_pdb_t *pdbp) mbs.param[3] = DMA_WD0(fcp->isp_scdma); mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); - FC_SCRATCH_ACQUIRE(isp); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (isp_pdb_t)); - isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp); + mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR; + if (dolock) { + FC_SCRATCH_ACQUIRE(isp); + } + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (un)); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + if (dolock) { + FC_SCRATCH_RELEASE(isp); + } + return (-1); + } + if (IS_24XX(isp)) { + isp_get_pdb_24xx(isp, fcp->isp_scratch, &un.bill); + pdb->handle = un.bill.pdb_handle; + pdb->s3_role = un.bill.pdb_prli_svc3; + pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits); + MEMCPY(pdb->portname, un.bill.pdb_portname, 8); + MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8); + } else { + isp_get_pdb_21xx(isp, fcp->isp_scratch, &un.fred); + pdb->handle = un.fred.pdb_loopid; + pdb->s3_role = un.fred.pdb_prli_svc3; + pdb->portid = BITS2WORD(un.fred.pdb_portid_bits); + MEMCPY(pdb->portname, un.fred.pdb_portname, 8); + MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8); + } + if (dolock) { FC_SCRATCH_RELEASE(isp); - return (0); } - FC_SCRATCH_RELEASE(isp); - return (-1); + return (0); } static uint64_t isp_get_portname(ispsoftc_t *isp, int loopid, int nodename) { - uint64_t wwn = 0; + uint64_t wwn = (uint64_t) -1; mbreg_t mbs; MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_PORT_NAME; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin || IS_24XX(isp)) { mbs.param[1] = loopid; - mbs.ibits |= (1 << 10); + mbs.ibits = (1 << 10); if (nodename) { mbs.param[10] = 1; } @@ -1599,8 +2409,23 @@ isp_get_portname(ispsoftc_t *isp, int loopid, int nodename) mbs.param[1] |= 1; } } - isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR; + mbs.timeout = 30000; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return (wwn); + } + if (IS_24XX(isp)) { + wwn = + (((uint64_t)(mbs.param[2] >> 8)) << 56) | + (((uint64_t)(mbs.param[2] & 0xff)) << 48) | + (((uint64_t)(mbs.param[3] >> 8)) << 40) | + (((uint64_t)(mbs.param[3] & 0xff)) << 32) | + (((uint64_t)(mbs.param[6] >> 8)) << 24) | + (((uint64_t)(mbs.param[6] & 0xff)) << 16) | + (((uint64_t)(mbs.param[7] >> 8)) << 8) | + (((uint64_t)(mbs.param[7] & 0xff))); + } else { wwn = (((uint64_t)(mbs.param[2] & 0xff)) << 56) | (((uint64_t)(mbs.param[2] >> 8)) << 48) | @@ -1615,13 +2440,13 @@ isp_get_portname(ispsoftc_t *isp, int loopid, int nodename) } /* - * Make sure we have good FC link and know our Loop ID. + * Make sure we have good FC link. */ static int isp_fclink_test(ispsoftc_t *isp, int usdelay) { - static char *toponames[] = { + static const char *toponames[] = { "Private Loop", "FL Port", "N-Port to N-Port", @@ -1631,17 +2456,15 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay) mbreg_t mbs; int count, check_for_fabric; uint8_t lwfs; + int loopid; fcparam *fcp; - struct lportdb *lp; + fcportdb_t *lp; isp_pdb_t pdb; fcp = isp->isp_param; isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Entry"); - - /* - * XXX: Here is where we would start a 'loop dead' timeout - */ + isp_mark_portdb(isp, 1); /* * Wait up to N microseconds for F/W to go to a ready state. @@ -1710,50 +2533,39 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay) * If we haven't gone to 'ready' state, return. */ if (fcp->isp_fwstate != FW_READY) { + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fclink_test: not at FW_READY state"); return (-1); } /* - * Get our Loop ID (if possible). We really need to have it. + * Get our Loop ID and Port ID. */ MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_LOOP_ID; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return (-1); } - if (IS_2KLOGIN(isp)) { + + if (FCPARAM(isp)->isp_2klogin) { fcp->isp_loopid = mbs.param[1]; } else { fcp->isp_loopid = mbs.param[1] & 0xff; } - if (fcp->isp_loopid == 0xffff) { /* happens with 2k login f/w */ - fcp->isp_loopid = MAX_FC_TARG-1; - } else if (fcp->isp_loopid >= MAX_FC_TARG) { - isp_prt(isp, ISP_LOGWARN, "bad initiator loopid (0x%x)", fcp->isp_loopid); - fcp->isp_loopid = MAX_FC_TARG-1; - } - if (IS_2200(isp) || IS_23XX(isp)) { + + if (IS_2100(isp)) { + fcp->isp_topo = TOPO_NL_PORT; + } else { int topo = (int) mbs.param[6]; - if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) + if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) { topo = TOPO_PTP_STUB; + } fcp->isp_topo = topo; - } else { - fcp->isp_topo = TOPO_NL_PORT; } - /* - * Get the port id. - */ fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16); - /* - * Check to see if we're on a fabric by trying to see if we - * can talk to the fabric name server. This can be a bit - * tricky because if we're a 2100, we should check always - * (in case we're connected to a server doing aliasing). - */ - fcp->isp_onfabric = 0; - if (IS_2100(isp)) { /* * Don't bother with fabric if we are using really old @@ -1767,117 +2579,79 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay) } else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) { check_for_fabric = 1; - } else + } else { check_for_fabric = 0; + } - if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { - int loopid = FL_PORT_ID; + if (IS_24XX(isp)) { + loopid = NPH_FL_ID; + } else { + loopid = FL_ID; + } + + if (check_for_fabric && isp_getpdb(isp, loopid, &pdb, 1) == 0) { if (IS_2100(isp)) { fcp->isp_topo = TOPO_FL_PORT; } - - if (BITS2WORD(pdb.pdb_portid_bits) == 0) { + if (pdb.portid == 0) { /* * Crock. */ fcp->isp_topo = TOPO_NL_PORT; goto not_on_fabric; } - fcp->isp_portid = mbs.param[2] | ((int) mbs.param[3] << 16); /* * Save the Fabric controller's port database entry. */ - lp = &fcp->portdb[loopid]; - lp->node_wwn = - (((uint64_t)pdb.pdb_nodename[0]) << 56) | - (((uint64_t)pdb.pdb_nodename[1]) << 48) | - (((uint64_t)pdb.pdb_nodename[2]) << 40) | - (((uint64_t)pdb.pdb_nodename[3]) << 32) | - (((uint64_t)pdb.pdb_nodename[4]) << 24) | - (((uint64_t)pdb.pdb_nodename[5]) << 16) | - (((uint64_t)pdb.pdb_nodename[6]) << 8) | - (((uint64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((uint64_t)pdb.pdb_portname[0]) << 56) | - (((uint64_t)pdb.pdb_portname[1]) << 48) | - (((uint64_t)pdb.pdb_portname[2]) << 40) | - (((uint64_t)pdb.pdb_portname[3]) << 32) | - (((uint64_t)pdb.pdb_portname[4]) << 24) | - (((uint64_t)pdb.pdb_portname[5]) << 16) | - (((uint64_t)pdb.pdb_portname[6]) << 8) | - (((uint64_t)pdb.pdb_portname[7])); - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->portid = BITS2WORD(pdb.pdb_portid_bits); - lp->loopid = pdb.pdb_loopid; - lp->loggedin = lp->valid = 1; - fcp->isp_onfabric = 1; - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - isp_register_fc4_type(isp); + lp = &fcp->portdb[FL_ID]; + lp->state = FC_PORTDB_STATE_PENDING_VALID; + MAKE_WWN_FROM_NODE_NAME(lp->node_wwn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(lp->port_wwn, pdb.portname); + lp->roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + lp->portid = pdb.portid; + lp->handle = pdb.handle; + lp->new_portid = lp->portid; + lp->new_roles = lp->roles; + if (IS_24XX(isp)) { + (void) isp_register_fc4_type_24xx(isp); + } else { + (void) isp_register_fc4_type(isp); + } } else { not_on_fabric: - fcp->isp_onfabric = 0; - fcp->portdb[FL_PORT_ID].valid = 0; + fcp->portdb[FL_ID].state = FC_PORTDB_STATE_NIL; } fcp->isp_gbspeed = 1; - if (IS_23XX(isp)) { + if (IS_23XX(isp) || IS_24XX(isp)) { MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_SET_DATA_RATE; mbs.param[1] = MBGSD_GET_RATE; /* mbs.param[2] undefined if we're just getting rate */ - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - if (mbs.param[1] == MBGSD_TWOGB) { + if (mbs.param[1] == MBGSD_FOURGB) { + isp_prt(isp, ISP_LOGINFO, "4Gb link speed/s"); + fcp->isp_gbspeed = 4; + } if (mbs.param[1] == MBGSD_TWOGB) { isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s"); fcp->isp_gbspeed = 2; } } } - isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, - fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]); - /* - * Announce ourselves, too. This involves synthesizing an entry. + * Announce ourselves, too. */ - if (fcp->isp_iid_set == 0) { - fcp->isp_iid_set = 1; - fcp->isp_iid = fcp->isp_loopid; - lp = &fcp->portdb[fcp->isp_iid]; - } else { - lp = &fcp->portdb[fcp->isp_iid]; - if (fcp->isp_portid != lp->portid || - fcp->isp_loopid != lp->loopid || - fcp->isp_nodewwn != ISP_NODEWWN(isp) || - fcp->isp_portwwn != ISP_PORTWWN(isp)) { - lp->valid = 0; - count = fcp->isp_iid; - (void) isp_async(isp, ISPASYNC_PROMENADE, &count); - } - } - lp->loopid = fcp->isp_loopid; - lp->portid = fcp->isp_portid; - lp->node_wwn = ISP_NODEWWN(isp); - lp->port_wwn = ISP_PORTWWN(isp); - switch (isp->isp_role) { - case ISP_ROLE_NONE: - lp->roles = 0; - break; - case ISP_ROLE_TARGET: - lp->roles = SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT; - break; - case ISP_ROLE_INITIATOR: - lp->roles = SVC3_INI_ROLE >> SVC3_ROLE_SHIFT; - break; - case ISP_ROLE_BOTH: - lp->roles = (SVC3_INI_ROLE|SVC3_TGT_ROLE) >> SVC3_ROLE_SHIFT; - break; - } - lp->loggedin = lp->valid = 1; - count = fcp->isp_iid; - (void) isp_async(isp, ISPASYNC_PROMENADE, &count); + isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_portid, + fcp->isp_loopid, toponames[fcp->isp_topo]); + isp_prt(isp, ISP_LOGCONFIG, ourwwn, + (uint32_t) (ISP_NODEWWN(isp) >> 32), + (uint32_t) ISP_NODEWWN(isp), + (uint32_t) (ISP_PORTWWN(isp) >> 32), + (uint32_t) ISP_PORTWWN(isp)); isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Complete"); return (0); } @@ -1899,17 +2673,35 @@ isp2100_fw_statename(int state) } /* - * Synchronize our soft copy of the port database with what the f/w thinks - * (with a view toward possibly for a specific target....) + * Complete the synchronization of our Port Database. + * + * At this point, we've scanned the local loop (if any) and the fabric + * and performed fabric logins on all new devices. + * + * Our task here is to go through our port database and remove any entities + * that are still marked probational (issuing PLOGO for ones which we had + * PLOGI'd into) or are dead. + * + * Our task here is to also check policy to decide whether devices which + * have *changed* in some way should still be kept active. For example, + * if a device has just changed PortID, we can either elect to treat it + * as an old device or as a newly arrived device (and notify the outer + * layer appropriately). + * + * We also do initiator map target id assignment here for new initiator + * devices and refresh old ones ot make sure that they point to the corret + * entities. */ - static int isp_pdb_sync(ispsoftc_t *isp) { - struct lportdb *lp; fcparam *fcp = isp->isp_param; - isp_pdb_t pdb; - int loopid, base, lim; + fcportdb_t *lp; + uint16_t dbidx; + + if (fcp->isp_loopstate == LOOP_READY) { + return (0); + } /* * Make sure we're okay for doing this right now. @@ -1917,306 +2709,146 @@ isp_pdb_sync(ispsoftc_t *isp) if (fcp->isp_loopstate != LOOP_PDB_RCVD && fcp->isp_loopstate != LOOP_FSCAN_DONE && fcp->isp_loopstate != LOOP_LSCAN_DONE) { + isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d", + fcp->isp_loopstate); return (-1); } - if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT || + if (fcp->isp_topo == TOPO_FL_PORT || + fcp->isp_topo == TOPO_NL_PORT || fcp->isp_topo == TOPO_N_PORT) { if (fcp->isp_loopstate < LOOP_LSCAN_DONE) { if (isp_scan_loop(isp) != 0) { + isp_prt(isp, ISP_LOGWARN, + "isp_pdb_sync: isp_scan_loop failed"); return (-1); } } } - fcp->isp_loopstate = LOOP_SYNCING_PDB; - - /* - * If we get this far, we've settled our differences with the f/w - * (for local loop device) and we can say that the loop state is ready. - */ - - if (fcp->isp_topo == TOPO_NL_PORT) { - fcp->loop_seen_once = 1; - fcp->isp_loopstate = LOOP_READY; - return (0); - } - /* - * Find all Fabric Entities that didn't make it from one scan to the - * next and let the world know they went away. Scan the whole database. - */ - for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { - if (lp->was_fabric_dev && lp->fabric_dev == 0) { - loopid = lp - fcp->portdb; - lp->valid = 0; /* should already be set */ - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - MEMZERO((void *) lp, sizeof (*lp)); - continue; + if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { + if (fcp->isp_loopstate < LOOP_FSCAN_DONE) { + if (isp_scan_fabric(isp) != 0) { + isp_prt(isp, ISP_LOGWARN, + "isp_pdb_sync: isp_scan_fabric failed"); + return (-1); + } } - lp->was_fabric_dev = lp->fabric_dev; } - if (fcp->isp_topo == TOPO_FL_PORT) - base = FC_SNS_ID+1; - else - base = 0; - - if (fcp->isp_topo == TOPO_N_PORT) - lim = 1; - else - lim = MAX_FC_TARG; - - /* - * Now log in any fabric devices that the outer layer has - * left for us to see. This seems the most sane policy - * for the moment. - */ - for (lp = &fcp->portdb[base]; lp < &fcp->portdb[lim]; lp++) { - uint32_t portid; - mbreg_t mbs; + fcp->isp_loopstate = LOOP_SYNCING_PDB; - loopid = lp - fcp->portdb; - if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) { - continue; - } + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + lp = &fcp->portdb[dbidx]; - /* - * Anything here? - */ - if (lp->port_wwn == 0) { + if (lp->state == FC_PORTDB_STATE_NIL) { continue; } - /* - * Don't try to log into yourself. - */ - if ((portid = lp->portid) == fcp->isp_portid) { + if (lp->state == FC_PORTDB_STATE_VALID) { + if (dbidx != FL_ID) { + isp_prt(isp, + ISP_LOGERR, "portdb idx %d already valid", + dbidx); + } continue; } - - /* - * If we'd been logged in- see if we still are and we haven't - * changed. If so, no need to log ourselves out, etc.. - * - * Unfortunately, our charming Qlogic f/w has decided to - * return a valid port database entry for a fabric device - * that has, in fact, gone away. And it hangs trying to - * log it out. - */ - if (lp->loggedin && lp->force_logout == 0 && - isp_getpdb(isp, lp->loopid, &pdb) == 0) { - int nrole; - uint64_t nwwnn, nwwpn; - nwwnn = - (((uint64_t)pdb.pdb_nodename[0]) << 56) | - (((uint64_t)pdb.pdb_nodename[1]) << 48) | - (((uint64_t)pdb.pdb_nodename[2]) << 40) | - (((uint64_t)pdb.pdb_nodename[3]) << 32) | - (((uint64_t)pdb.pdb_nodename[4]) << 24) | - (((uint64_t)pdb.pdb_nodename[5]) << 16) | - (((uint64_t)pdb.pdb_nodename[6]) << 8) | - (((uint64_t)pdb.pdb_nodename[7])); - nwwpn = - (((uint64_t)pdb.pdb_portname[0]) << 56) | - (((uint64_t)pdb.pdb_portname[1]) << 48) | - (((uint64_t)pdb.pdb_portname[2]) << 40) | - (((uint64_t)pdb.pdb_portname[3]) << 32) | - (((uint64_t)pdb.pdb_portname[4]) << 24) | - (((uint64_t)pdb.pdb_portname[5]) << 16) | - (((uint64_t)pdb.pdb_portname[6]) << 8) | - (((uint64_t)pdb.pdb_portname[7])); - nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> - SVC3_ROLE_SHIFT; - if (pdb.pdb_loopid == lp->loopid && lp->portid == - (uint32_t) BITS2WORD(pdb.pdb_portid_bits) && - nwwnn == lp->node_wwn && nwwpn == lp->port_wwn && - lp->roles == nrole && lp->force_logout == 0) { - lp->loggedin = lp->valid = 1; - isp_prt(isp, ISP_LOGCONFIG, lretained, - (int) (lp - fcp->portdb), - (int) lp->loopid, lp->portid); - continue; + switch (lp->state) { + case FC_PORTDB_STATE_PROBATIONAL: + case FC_PORTDB_STATE_DEAD: + isp_async(isp, ISPASYNC_DEV_GONE, lp); + if (lp->ini_map_idx) { + fcp->isp_ini_map[lp->ini_map_idx-1] = 0; + lp->ini_map_idx = 0; } - } - - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); - } - - /* - * Force a logout if we were logged in. - */ - if (lp->loggedin) { - if (lp->force_logout || - isp_getpdb(isp, lp->loopid, &pdb) == 0) { - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGOUT; - if (IS_2KLOGIN(isp)) { - mbs.param[1] = lp->loopid; - mbs.ibits |= (1 << 10); + lp->state = FC_PORTDB_STATE_NIL; + if (lp->autologin == 0) { + if (IS_24XX(isp)) { + int action = + PLOGX_FLG_CMD_LOGO | + PLOGX_FLG_IMPLICIT | + PLOGX_FLG_FREE_NPHDL; + FC_SCRATCH_ACQUIRE(isp); + isp_plogx_24xx(isp, lp->handle, + lp->portid, &action); + FC_SCRATCH_RELEASE(isp); } else { - mbs.param[1] = lp->loopid << 8; + isp_port_logout(isp, lp->handle, + lp->portid); } - isp_mboxcmd(isp, &mbs, MBLOGNONE); - isp_prt(isp, ISP_LOGINFO, plogout, - (int) (lp - fcp->portdb), lp->loopid, - lp->portid); - } - lp->force_logout = lp->loggedin = 0; - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); - } - } - - /* - * And log in.... - */ - loopid = lp - fcp->portdb; - lp->loopid = FL_PORT_ID; - do { - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGIN; - if (IS_2KLOGIN(isp)) { - mbs.param[1] = loopid; - mbs.ibits |= (1 << 10); } else { - mbs.param[1] = loopid << 8; + lp->autologin = 0; } - mbs.param[2] = portid >> 16; - mbs.param[3] = portid & 0xffff; - isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED | - MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR)); - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); - } - switch (mbs.param[0]) { - case MBOX_LOOP_ID_USED: - /* - * Try the next available loop id. - */ - loopid++; - break; - case MBOX_PORT_ID_USED: - /* - * This port is already logged in. - * Snaffle the loop id it's using if it's - * nonzero, otherwise we're hosed. - */ - if (mbs.param[1] != 0) { - loopid = mbs.param[1]; - if (loopid >= MAX_FC_TARG) { - loopid = MAX_FC_TARG; - break; + lp->new_roles = 0; + lp->new_portid = 0; + break; + case FC_PORTDB_STATE_NEW: + /* + * If *we* have a new target dole and *it* has a target + * role, assign a new target id to it. + */ + lp->portid = lp->new_portid; + lp->roles = lp->new_roles; + lp->state = FC_PORTDB_STATE_VALID; + if ((isp->isp_role & ISP_ROLE_INITIATOR) && + (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) { + int i, t = dbidx; + for (i = 0; i < MAX_FC_TARG; i++) { + if (i < FL_ID || i > SNS_ID) { + if (fcp->isp_ini_map[t] == 0) { + break; + } } - isp_prt(isp, ISP_LOGINFO, retained, - loopid, (int) (lp - fcp->portdb), - lp->portid); + if (++t == MAX_FC_TARG) { + t = 0; + } + } + if (i < MAX_FC_TARG) { + fcp->isp_ini_map[t] = dbidx + 1; + lp->ini_map_idx = t + 1; } else { - loopid = MAX_FC_TARG; - break; + isp_prt(isp, ISP_LOGWARN, + "out of target ids"); } - /* FALLTHROUGH */ - case MBOX_COMMAND_COMPLETE: - lp->loggedin = 1; - lp->loopid = loopid; - break; - case MBOX_COMMAND_ERROR: - isp_prt(isp, ISP_LOGINFO, plogierr, - portid, mbs.param[1]); - /* FALLTHROUGH */ - case MBOX_ALL_IDS_USED: /* We're outta IDs */ - default: - loopid = MAX_FC_TARG; - break; } - } while (lp->loopid == FL_PORT_ID && loopid < MAX_FC_TARG); - - /* - * If we get here and we haven't set a Loop ID, - * we failed to log into this device. - */ - - if (lp->loopid == FL_PORT_ID) { - lp->loopid = 0; - continue; - } - - /* - * Make sure we can get the approriate port information. - */ - if (isp_getpdb(isp, lp->loopid, &pdb) != 0) { - isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid); - goto dump_em; - } - - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); - } - - if (pdb.pdb_loopid != lp->loopid) { - isp_prt(isp, ISP_LOGWARN, pdbmfail1, - lp->portid, pdb.pdb_loopid); - goto dump_em; - } - - if (lp->portid != (uint32_t) BITS2WORD(pdb.pdb_portid_bits)) { - isp_prt(isp, ISP_LOGWARN, pdbmfail2, - lp->portid, BITS2WORD(pdb.pdb_portid_bits)); - goto dump_em; - } - - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->node_wwn = - (((uint64_t)pdb.pdb_nodename[0]) << 56) | - (((uint64_t)pdb.pdb_nodename[1]) << 48) | - (((uint64_t)pdb.pdb_nodename[2]) << 40) | - (((uint64_t)pdb.pdb_nodename[3]) << 32) | - (((uint64_t)pdb.pdb_nodename[4]) << 24) | - (((uint64_t)pdb.pdb_nodename[5]) << 16) | - (((uint64_t)pdb.pdb_nodename[6]) << 8) | - (((uint64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((uint64_t)pdb.pdb_portname[0]) << 56) | - (((uint64_t)pdb.pdb_portname[1]) << 48) | - (((uint64_t)pdb.pdb_portname[2]) << 40) | - (((uint64_t)pdb.pdb_portname[3]) << 32) | - (((uint64_t)pdb.pdb_portname[4]) << 24) | - (((uint64_t)pdb.pdb_portname[5]) << 16) | - (((uint64_t)pdb.pdb_portname[6]) << 8) | - (((uint64_t)pdb.pdb_portname[7])); - /* - * Check to make sure this all makes sense. - */ - if (lp->node_wwn && lp->port_wwn) { - lp->valid = 1; - loopid = lp - fcp->portdb; - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - continue; - } -dump_em: - lp->valid = 0; - isp_prt(isp, ISP_LOGINFO, - ldumped, loopid, lp->loopid, lp->portid); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGOUT; - if (IS_2KLOGIN(isp)) { - mbs.param[1] = lp->loopid; - mbs.ibits |= (1 << 10); - } else { - mbs.param[1] = lp->loopid << 8; - } - isp_mboxcmd(isp, &mbs, MBLOGNONE); - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_SYNCING_PDB) { - return (-1); + isp_async(isp, ISPASYNC_DEV_ARRIVED, lp); + lp->new_roles = 0; + lp->new_portid = 0; + break; + case FC_PORTDB_STATE_CHANGED: + lp->portid = lp->new_portid; + lp->roles = lp->new_roles; + lp->state = FC_PORTDB_STATE_VALID; + if (lp->ini_map_idx) { + int t = lp->ini_map_idx - 1; + fcp->isp_ini_map[t] = dbidx + 1; + } + isp_async(isp, ISPASYNC_DEV_CHANGED, lp); + lp->new_roles = 0; + lp->new_portid = 0; + break; + case FC_PORTDB_STATE_PENDING_VALID: + lp->portid = lp->new_portid; + lp->roles = lp->new_roles; + lp->state = FC_PORTDB_STATE_VALID; + if (lp->ini_map_idx) { + int t = lp->ini_map_idx - 1; + fcp->isp_ini_map[t] = dbidx + 1; + } + isp_async(isp, ISPASYNC_DEV_STAYED, lp); + if (dbidx != FL_ID) { + lp->new_roles = 0; + lp->new_portid = 0; + } + break; + default: + isp_prt(isp, ISP_LOGERR, "eh? state %d for idx %d", + lp->state, dbidx); + isp_dump_portdb(isp); } } + /* * If we get here, we've for sure seen not only a valid loop * but know what is or isn't on it, so mark this for usage @@ -2227,807 +2859,912 @@ dump_em: return (0); } +/* + * Scan local loop for devices. + */ static int isp_scan_loop(ispsoftc_t *isp) { - struct lportdb *lp; + fcportdb_t *lp, tmp; fcparam *fcp = isp->isp_param; + int i; isp_pdb_t pdb; - int loopid, lim, hival; + uint16_t dbidx, lim = 0; + if (fcp->isp_fwstate < FW_READY || + fcp->isp_loopstate < LOOP_PDB_RCVD) { + return (-1); + } + + if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) { + return (0); + } + + /* + * Check our connection topology. + * + * If we're a public or private loop, we scan 0..125 as handle values. + * The firmware has (typically) peformed a PLOGI for us. + * + * If we're a N-port connection, we treat this is a short loop (0..1). + * + * If we're in target mode, we can all possible handles to see who + * might have logged into us. + */ switch (fcp->isp_topo) { case TOPO_NL_PORT: - hival = FL_PORT_ID; + case TOPO_FL_PORT: + lim = LOCAL_LOOP_LIM; break; case TOPO_N_PORT: - hival = 2; - break; - case TOPO_FL_PORT: - hival = FC_PORT_ID; + lim = 2; break; default: isp_prt(isp, ISP_LOGDEBUG0, "no loop topology to scan"); fcp->isp_loopstate = LOOP_LSCAN_DONE; return (0); } - fcp->isp_loopstate = LOOP_SCANNING_LOOP; - - isp_prt(isp, ISP_LOGDEBUG0, "scanning local loop 0..%d", hival); + fcp->isp_loopstate = LOOP_SCANNING_LOOP; + isp_prt(isp, ISP_LOGDEBUG0, "scanning loop 0..%d", lim-1); - /* - * make sure the temp port database is clean... - */ - MEMZERO((void *)fcp->tport, sizeof (fcp->tport)); /* - * Run through the local loop ports and get port database info - * for each loop ID. - * - * There's a somewhat unexplained situation where the f/w passes back - * the wrong database entity- if that happens, just restart (up to - * FL_PORT_ID times). + * Run through the list and get the port database info for each one. */ - for (lim = loopid = 0; loopid < hival; loopid++) { - lp = &fcp->tport[loopid]; - + for (dbidx = 0; dbidx < lim; dbidx++) { /* - * Don't even try for ourselves... + * But don't even try for ourselves... */ - if (loopid == fcp->isp_loopid) { + if (dbidx == fcp->isp_loopid) { continue; } + /* + * In older cards with older f/w GET_PORT_DATABASE has been + * known to hang. This trick gets around that problem. + */ if (IS_2100(isp) || IS_2200(isp)) { - lp->node_wwn = isp_get_portname(isp, loopid, 1); + uint64_t node_wwn = isp_get_portname(isp, dbidx, 1); if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { return (-1); } - if (lp->node_wwn == 0) { + if (node_wwn == 0) { continue; } } /* - * Get an entry.... + * Get the port database entity for this index. */ - if (isp_getpdb(isp, loopid, &pdb) != 0) { + if (isp_getpdb(isp, dbidx, &pdb, 1) != 0) { if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { + isp_mark_portdb(isp, 1); return (-1); } continue; } if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { + isp_mark_portdb(isp, 1); return (-1); } /* - * If the returned database element doesn't match what we - * asked for, restart the process entirely (up to a point...). + * On *very* old 2100 firmware we would end up sometimes + * with the firmware returning the port database entry + * for something else. We used to restart locally, but + * now we punt. */ - if (pdb.pdb_loopid != loopid) { - loopid = 0; - if (lim++ < hival) { - continue; - } + if (IS_2100(isp) && pdb.handle != dbidx) { isp_prt(isp, ISP_LOGWARN, "giving up on synchronizing the port database"); + isp_mark_portdb(isp, 1); return (-1); } /* * Save the pertinent info locally. */ - lp->node_wwn = - (((uint64_t)pdb.pdb_nodename[0]) << 56) | - (((uint64_t)pdb.pdb_nodename[1]) << 48) | - (((uint64_t)pdb.pdb_nodename[2]) << 40) | - (((uint64_t)pdb.pdb_nodename[3]) << 32) | - (((uint64_t)pdb.pdb_nodename[4]) << 24) | - (((uint64_t)pdb.pdb_nodename[5]) << 16) | - (((uint64_t)pdb.pdb_nodename[6]) << 8) | - (((uint64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((uint64_t)pdb.pdb_portname[0]) << 56) | - (((uint64_t)pdb.pdb_portname[1]) << 48) | - (((uint64_t)pdb.pdb_portname[2]) << 40) | - (((uint64_t)pdb.pdb_portname[3]) << 32) | - (((uint64_t)pdb.pdb_portname[4]) << 24) | - (((uint64_t)pdb.pdb_portname[5]) << 16) | - (((uint64_t)pdb.pdb_portname[6]) << 8) | - (((uint64_t)pdb.pdb_portname[7])); - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->portid = BITS2WORD(pdb.pdb_portid_bits); - lp->loopid = pdb.pdb_loopid; - } - - /* - * Mark all of the permanent local loop database entries as invalid - * (except our own entry). - */ - for (loopid = 0; loopid < hival; loopid++) { - if (loopid == fcp->isp_iid) { - fcp->portdb[loopid].valid = 1; - fcp->portdb[loopid].loopid = fcp->isp_loopid; - continue; - } - fcp->portdb[loopid].valid = 0; - } - - /* - * Now merge our local copy of the port database into our saved copy. - * Notify the outer layers of new devices arriving. - */ - for (loopid = 0; loopid < hival; loopid++) { - int i; - - /* - * If we don't have a non-zero Port WWN, we're not here. - */ - if (fcp->tport[loopid].port_wwn == 0) { - continue; - } + MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname); + tmp.roles = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + tmp.portid = pdb.portid; + tmp.handle = pdb.handle; /* - * Skip ourselves. + * Check to make sure it's still a valid entry. The 24XX seems + * to return a portid but not a WWPN/WWNN or role for devices + * which shift on a loop. */ - if (loopid == fcp->isp_iid) { + if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) { + isp_prt(isp, ISP_LOGWARN, + "bad pdb entry at loop %d", dbidx); + isp_dump_portdb(isp); continue; } /* - * For the purposes of deciding whether this is the - * 'same' device or not, we only search for an identical - * Port WWN. Node WWNs may or may not be the same as - * the Port WWN, and there may be multiple different - * Port WWNs with the same Node WWN. It would be chaos - * to have multiple identical Port WWNs, so we don't - * allow that. + * Now search the entire port database + * for the same Port and Node WWN. */ - - for (i = 0; i < hival; i++) { - int j; - if (fcp->portdb[i].port_wwn == 0) + for (i = 0; i < MAX_FC_TARG; i++) { + lp = &fcp->portdb[i]; + if (lp->state == FC_PORTDB_STATE_NIL) { + continue; + } + if (lp->node_wwn != tmp.node_wwn) { continue; - if (fcp->portdb[i].port_wwn != - fcp->tport[loopid].port_wwn) + } + if (lp->port_wwn != tmp.port_wwn) { continue; + } + /* - * We found this WWN elsewhere- it's changed - * loopids then. We don't change it's actual - * position in our cached port database- we - * just change the actual loop ID we'd use. + * Okay- we've found a non-nil entry that matches. + * Check to make sure it's probational. */ - if (fcp->portdb[i].loopid != loopid) { - isp_prt(isp, ISP_LOGINFO, portshift, i, - fcp->portdb[i].loopid, - fcp->portdb[i].portid, loopid, - fcp->tport[loopid].portid); + if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { + isp_prt(isp, ISP_LOGERR, + "portdb entry %d not probational (0x%x)", + i, lp->state); + isp_dump_portdb(isp); + isp_mark_portdb(isp, 1); + return (-1); } - fcp->portdb[i].portid = fcp->tport[loopid].portid; - fcp->portdb[i].loopid = loopid; - fcp->portdb[i].valid = 1; - fcp->portdb[i].roles = fcp->tport[loopid].roles; + lp->autologin = 1; /* - * Now make sure this Port WWN doesn't exist elsewhere - * in the port database. + * Check to make sure it's really the same + * device and update the initiator map before + * we mark it as pending valid. */ - for (j = i+1; j < hival; j++) { - if (fcp->portdb[i].port_wwn != - fcp->portdb[j].port_wwn) { - continue; - } - isp_prt(isp, ISP_LOGWARN, portdup, j, i); - /* - * Invalidate the 'old' *and* 'new' ones. - * This is really harsh and not quite right, - * but if this happens, we really don't know - * who is what at this point. - */ - fcp->portdb[i].valid = 0; - fcp->portdb[j].valid = 0; + if (lp->portid == tmp.portid && + lp->handle == tmp.handle && + lp->roles == tmp.roles) { + lp->new_portid = tmp.portid; + lp->new_roles = tmp.roles; + lp->state = FC_PORTDB_STATE_PENDING_VALID; + break; } + + /* + * We can wipe out the old handle value here because + * it's no longer valid. + */ + lp->handle = tmp.handle; + + /* + * Claim that this has changed and let somebody else + * decide what to do. + */ + lp->state = FC_PORTDB_STATE_CHANGED; + lp->new_portid = tmp.portid; + lp->new_roles = tmp.roles; break; } /* - * If we didn't traverse the entire port database, - * then we found (and remapped) an existing entry. - * No need to notify anyone- go for the next one. + * Did we find and update an old entry? */ - if (i < hival) { - isp_prt(isp, ISP_LOGINFO, retained, - fcp->portdb[i].loopid, i, fcp->portdb[i].portid); + if (i < MAX_FC_TARG) { continue; } /* - * We've not found this Port WWN anywhere. It's a new entry. - * See if we can leave it where it is (with target == loopid). + * Ah. A new device entry. Find an empty slot + * for it and save info for later disposition. */ - if (fcp->portdb[loopid].port_wwn != 0) { - for (lim = 0; lim < hival; lim++) { - if (fcp->portdb[lim].port_wwn == 0) - break; - } - /* "Cannot Happen" */ - if (lim == hival) { - isp_prt(isp, ISP_LOGWARN, "Remap Overflow"); - continue; + for (i = 0; i < MAX_FC_TARG; i++) { + if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) { + break; } - i = lim; - } else { - i = loopid; } - - /* - * NB: The actual loopid we use here is loopid- we may - * in fact be at a completely different index (target). - */ - fcp->portdb[i].loopid = loopid; - fcp->portdb[i].port_wwn = fcp->tport[loopid].port_wwn; - fcp->portdb[i].node_wwn = fcp->tport[loopid].node_wwn; - fcp->portdb[i].roles = fcp->tport[loopid].roles; - fcp->portdb[i].portid = fcp->tport[loopid].portid; - fcp->portdb[i].valid = 1; - - /* - * Tell the outside world we've arrived. - */ - (void) isp_async(isp, ISPASYNC_PROMENADE, &i); - } - - /* - * Now find all previously used targets that are now invalid and - * notify the outer layers that they're gone. - */ - for (lp = &fcp->portdb[0]; lp < &fcp->portdb[hival]; lp++) { - if (lp->valid || lp->port_wwn == 0) { + if (i == MAX_FC_TARG) { + isp_prt(isp, ISP_LOGERR, + "could not find slot for new entry"); continue; } + lp = &fcp->portdb[i]; - /* - * Tell the outside world we've gone - * away and erase our pdb entry. - * - */ - loopid = lp - fcp->portdb; - (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); - MEMZERO((void *) lp, sizeof (*lp)); + lp->autologin = 1; + lp->state = FC_PORTDB_STATE_NEW; + lp->portid = 0; + lp->roles = 0; + lp->new_portid = tmp.portid; + lp->new_roles = tmp.roles; + lp->handle = tmp.handle; + lp->port_wwn = tmp.port_wwn; + lp->node_wwn = tmp.node_wwn; } + fcp->isp_loopstate = LOOP_LSCAN_DONE; return (0); } +/* + * Scan the fabric for devices and add them to our port database. + * + * Use the GID_FT command to get all Port IDs for FC4 SCSI devices it knows. + * + * For 2100-23XX cards, we can use the SNS mailbox command to pass simple + * name server commands to the switch management server via the QLogic f/w. + * + * For the 24XX card, we have to use CT-Pass through run via the Execute IOCB + * mailbox command. + * + * The net result is to leave the list of Port IDs setting untranslated in + * offset IGPOFF of the FC scratch area, whereupon we'll canonicalize it to + * host order at OGPOFF. + */ + +/* + * Take less than half of our scratch area to store Port IDs + */ +#define GIDLEN ((ISP2100_SCRLEN >> 1) - 16 - SNS_GID_FT_REQ_SIZE) +#define NGENT ((GIDLEN - 16) >> 2) + +#define IGPOFF (2 * QENTRY_LEN) +#define OGPOFF (ISP2100_SCRLEN >> 1) +#define ZTXOFF (ISP2100_SCRLEN - (1 * QENTRY_LEN)) +#define CTXOFF (ISP2100_SCRLEN - (2 * QENTRY_LEN)) +#define XTXOFF (ISP2100_SCRLEN - (3 * QENTRY_LEN)) static int -isp_fabric_mbox_cmd(ispsoftc_t *isp, mbreg_t *mbp) +isp_gid_ft_sns(ispsoftc_t *isp) { - /* the caller sets up the mailbox */ - isp_mboxcmd(isp, mbp, MBLOGNONE); - if (mbp->param[0] != MBOX_COMMAND_COMPLETE) { - if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) { - FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - } - if (mbp->param[0] == MBOX_COMMAND_ERROR) { - char tbuf[16]; - char *m; - switch (mbp->param[1]) { - case 1: - m = "No Loop"; - break; - case 2: - m = "Failed to allocate IOCB buffer"; - break; - case 3: - m = "Failed to allocate XCB buffer"; - break; - case 4: - m = "timeout or transmit failed"; - break; - case 5: - m = "no fabric loop"; - break; - case 6: - m = "remote device not a target"; - break; - default: - SNPRINTF(tbuf, sizeof tbuf, "%x", - mbp->param[1]); - m = tbuf; - break; - } - isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m); - } - return (-1); - } + union { + sns_gid_ft_req_t _x; + uint8_t _y[SNS_GID_FT_REQ_SIZE]; + } un; + fcparam *fcp = FCPARAM(isp); + sns_gid_ft_req_t *rq = &un._x; + mbreg_t mbs; - if (FCPARAM(isp)->isp_fwstate != FW_READY || - FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) { - return (-1); + isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via SNS"); + + MEMZERO(rq, SNS_GID_FT_REQ_SIZE); + rq->snscb_rblen = GIDLEN >> 1; + rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + IGPOFF); + rq->snscb_sblen = 6; + rq->snscb_cmd = SNS_GID_FT; + rq->snscb_mword_div_2 = NGENT; + rq->snscb_fc4_type = FC4_SCSI; + + isp_put_gid_ft_request(isp, rq, fcp->isp_scratch); + MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE); + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_SEND_SNS; + mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1; + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); + mbs.logval = MBLOGALL; + mbs.timeout = 1000000; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + if (mbs.param[0] == MBOX_INVALID_COMMAND) { + return (1); + } else { + return (-1); + } } - return(0); + return (0); } -#ifdef ISP_USE_GA_NXT static int -isp_scan_fabric(ispsoftc_t *isp, int ftype) +isp_gid_ft_ct_passthru(ispsoftc_t *isp) { - fcparam *fcp = isp->isp_param; - uint32_t portid, first_portid, last_portid; - int hicap, last_port_same; - - if (fcp->isp_onfabric == 0) { - fcp->isp_loopstate = LOOP_FSCAN_DONE; - return (0); + mbreg_t mbs; + fcparam *fcp = FCPARAM(isp); + union { + isp_ct_pt_t plocal; + ct_hdr_t clocal; + uint8_t q[QENTRY_LEN]; + } un; + isp_ct_pt_t *pt; + ct_hdr_t *ct; + uint32_t *rp; + uint8_t *scp = fcp->isp_scratch; + + isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via CT"); + + if (!IS_24XX(isp)) { + return (1); } - isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GA_NXT)"); - - FC_SCRATCH_ACQUIRE(isp); - /* - * Since Port IDs are 24 bits, we can check against having seen - * anything yet with this value. + * Build a Passthrough IOCB in memory. */ - last_port_same = 0; - last_portid = 0xffffffff; /* not a port */ - first_portid = portid = fcp->isp_portid; - fcp->isp_loopstate = LOOP_SCANNING_FABRIC; - - for (hicap = 0; hicap < GA_NXT_MAX; hicap++) { - mbreg_t mbs; - sns_screq_t *rq; - sns_ga_nxt_rsp_t *rs0, *rs1; - struct lportdb lcl; - uint8_t sc[SNS_GA_NXT_RESP_SIZE]; - - rq = (sns_screq_t *)sc; - MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE); - rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1; - rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100); - rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100); - rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100); - rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100); - rq->snscb_sblen = 6; - rq->snscb_data[0] = SNS_GA_NXT; - rq->snscb_data[4] = portid & 0xffff; - rq->snscb_data[5] = (portid >> 16) & 0xff; - isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); - /* - * Leave 4 and 5 alone - */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } - FC_SCRATCH_RELEASE(isp); - return (-1); - } - MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE); - rs1 = (sns_ga_nxt_rsp_t *) sc; - rs0 = (sns_ga_nxt_rsp_t *) ((uint8_t *)fcp->isp_scratch+0x100); - isp_get_ga_nxt_response(isp, rs0, rs1); - if (rs1->snscb_cthdr.ct_response != FS_ACC) { - int level; - if (rs1->snscb_cthdr.ct_reason == 9 && - rs1->snscb_cthdr.ct_explanation == 7) - level = ISP_LOGDEBUG0; - else - level = ISP_LOGWARN; - isp_prt(isp, level, swrej, "GA_NXT", - rs1->snscb_cthdr.ct_reason, - rs1->snscb_cthdr.ct_explanation, portid); - FC_SCRATCH_RELEASE(isp); - fcp->isp_loopstate = LOOP_FSCAN_DONE; - return (0); - } - portid = - (((uint32_t) rs1->snscb_port_id[0]) << 16) | - (((uint32_t) rs1->snscb_port_id[1]) << 8) | - (((uint32_t) rs1->snscb_port_id[2])); + pt = &un.plocal; + MEMZERO(un.q, QENTRY_LEN); + pt->ctp_header.rqs_entry_count = 1; + pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; + pt->ctp_handle = 0xffffffff; + pt->ctp_nphdl = NPH_SNS_ID; + pt->ctp_cmd_cnt = 1; + pt->ctp_time = 30; + pt->ctp_rsp_cnt = 1; + pt->ctp_rsp_bcnt = GIDLEN; + pt->ctp_cmd_bcnt = sizeof (*ct) + sizeof (uint32_t); + pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_count = sizeof (*ct) + sizeof (uint32_t); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_count = GIDLEN; + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "ct IOCB", QENTRY_LEN, pt); + } + isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]); - /* - * XXX: We should check to make sure that this entry - * XXX: supports the type(s) we are interested in. - */ - /* - * Okay, we now have information about a fabric object. - * If it is the type we're interested in, tell the outer layers - * about it. The outer layer needs to know: Port ID, WWNN, - * WWPN, FC4 type, and port type. - * - * The lportdb structure is adequate for this. - */ - MEMZERO(&lcl, sizeof (lcl)); - lcl.port_type = rs1->snscb_port_type; - lcl.fc4_type = ftype; - lcl.portid = portid; - lcl.node_wwn = - (((uint64_t)rs1->snscb_nodename[0]) << 56) | - (((uint64_t)rs1->snscb_nodename[1]) << 48) | - (((uint64_t)rs1->snscb_nodename[2]) << 40) | - (((uint64_t)rs1->snscb_nodename[3]) << 32) | - (((uint64_t)rs1->snscb_nodename[4]) << 24) | - (((uint64_t)rs1->snscb_nodename[5]) << 16) | - (((uint64_t)rs1->snscb_nodename[6]) << 8) | - (((uint64_t)rs1->snscb_nodename[7])); - lcl.port_wwn = - (((uint64_t)rs1->snscb_portname[0]) << 56) | - (((uint64_t)rs1->snscb_portname[1]) << 48) | - (((uint64_t)rs1->snscb_portname[2]) << 40) | - (((uint64_t)rs1->snscb_portname[3]) << 32) | - (((uint64_t)rs1->snscb_portname[4]) << 24) | - (((uint64_t)rs1->snscb_portname[5]) << 16) | - (((uint64_t)rs1->snscb_portname[6]) << 8) | - (((uint64_t)rs1->snscb_portname[7])); - - /* - * Does this fabric object support the type we want? - * If not, skip it. - */ - if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) { - if (first_portid == portid) { - lcl.last_fabric_dev = 1; - } else { - lcl.last_fabric_dev = 0; - } - (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl); - } else { - isp_prt(isp, ISP_LOGDEBUG0, - "PortID 0x%x doesn't support FC4 type 0x%x", - portid, ftype); - } - if (first_portid == portid) { - fcp->isp_loopstate = LOOP_FSCAN_DONE; - FC_SCRATCH_RELEASE(isp); - return (0); - } - if (portid == last_portid) { - if (last_port_same++ > 20) { - isp_prt(isp, ISP_LOGWARN, - "tangled fabric database detected"); - break; - } - } else { - last_port_same = 0 ; - last_portid = portid; - } + /* + * Build the CT header and command in memory. + * + * Note that the CT header has to end up as Big Endian format in memory. + */ + ct = &un.clocal; + MEMZERO(ct, sizeof (*ct)); + ct->ct_revision = CT_REVISION; + ct->ct_fcs_type = CT_FC_TYPE_FC; + ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; + ct->ct_cmd_resp = SNS_GID_FT; + ct->ct_bcnt_resid = (GIDLEN - 16) >> 2; + + isp_put_ct_hdr(isp, ct, (ct_hdr_t *) &scp[XTXOFF]); + rp = (uint32_t *) &scp[XTXOFF+sizeof (*ct)]; + ISP_IOZPUT_32(isp, FC4_SCSI, rp); + MEMZERO(&scp[ZTXOFF], QENTRY_LEN); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64; + mbs.param[1] = QENTRY_LEN; + mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); + mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); + mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF); + mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF); + mbs.logval = MBLOGALL; + MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return (-1); } - FC_SCRATCH_RELEASE(isp); - if (hicap >= GA_NXT_MAX) { - isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX); + MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN); + pt = &un.plocal; + isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt); } - fcp->isp_loopstate = LOOP_FSCAN_DONE; + + if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) { + isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x", + pt->ctp_status); + return (-1); + } + MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN + 16); return (0); } -#else -#define GIDLEN ((ISP2100_SCRLEN >> 1) + 16) -#define NGENT ((GIDLEN - 16) >> 2) - -#define IGPOFF (ISP2100_SCRLEN - GIDLEN) -#define GXOFF (256) static int -isp_scan_fabric(ispsoftc_t *isp, int ftype) +isp_scan_fabric(ispsoftc_t *isp) { fcparam *fcp = FCPARAM(isp); - mbreg_t mbs; - int i; - sns_gid_ft_req_t *rq; + uint32_t portid; + uint16_t handle, oldhandle; + int portidx, portlim, r; sns_gid_ft_rsp_t *rs0, *rs1; - if (fcp->isp_onfabric == 0) { + isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric"); + if (fcp->isp_fwstate != FW_READY || + fcp->isp_loopstate < LOOP_LSCAN_DONE) { + return (-1); + } + if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) { + return (0); + } + if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) { fcp->isp_loopstate = LOOP_FSCAN_DONE; + isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done (no fabric)"); return (0); } - isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT)"); - FC_SCRATCH_ACQUIRE(isp); fcp->isp_loopstate = LOOP_SCANNING_FABRIC; - rq = (sns_gid_ft_req_t *)fcp->tport; - MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE); - rq->snscb_rblen = GIDLEN >> 1; - rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF); - rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF); - rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF); - rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF); - rq->snscb_sblen = 6; - rq->snscb_cmd = SNS_GID_FT; - rq->snscb_mword_div_2 = NGENT; - rq->snscb_fc4_type = ftype; - isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + if (IS_24XX(isp)) { + r = isp_gid_ft_ct_passthru(isp); + } else { + r = isp_gid_ft_sns(isp); + } - /* - * Leave 4 and 5 alone - */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } + if (r > 0) { + fcp->isp_loopstate = LOOP_FSCAN_DONE; FC_SCRATCH_RELEASE(isp); - return (-1); + return (0); + } else if (r < 0) { + fcp->isp_loopstate = LOOP_PDB_RCVD; /* try again */ + FC_SCRATCH_RELEASE(isp); + return (0); } if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { FC_SCRATCH_RELEASE(isp); return (-1); } + MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN); - rs1 = (sns_gid_ft_rsp_t *) fcp->tport; rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF); + rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF); isp_get_gid_ft_response(isp, rs0, rs1, NGENT); - if (rs1->snscb_cthdr.ct_response != FS_ACC) { + if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) { int level; if (rs1->snscb_cthdr.ct_reason == 9 && - rs1->snscb_cthdr.ct_explanation == 7) + rs1->snscb_cthdr.ct_explanation == 7) { level = ISP_LOGDEBUG0; - else + } else { level = ISP_LOGWARN; - isp_prt(isp, level, swrej, "GID_FT", - rs1->snscb_cthdr.ct_reason, - rs1->snscb_cthdr.ct_explanation, 0); + } + isp_prt(isp, level, "Fabric Nameserver rejected GID_FT " + "(Reason=0x%x Expl=0x%x)", rs1->snscb_cthdr.ct_reason, + rs1->snscb_cthdr.ct_explanation); FC_SCRATCH_RELEASE(isp); fcp->isp_loopstate = LOOP_FSCAN_DONE; return (0); } + /* - * Okay, we now have a list of Port IDs for this class of device. - * Go through the list and for each one get the WWPN/WWNN for it - * and tell the outer layers about it. The outer layer needs to - * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type. - * - * The lportdb structure is adequate for this. + * If we get this far, we certainly still have the fabric controller. */ - i = -1; - do { - sns_gxn_id_req_t grqbuf, *gq = &grqbuf; - sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf; - struct lportdb lcl; -#if 0 - sns_gff_id_rsp_t *fs0, ffsbuf, *fs1 = &ffsbuf; -#endif + fcp->portdb[FL_ID].state = FC_PORTDB_STATE_PENDING_VALID; - i++; - MEMZERO(&lcl, sizeof (lcl)); - lcl.fc4_type = ftype; - lcl.portid = - (((uint32_t) rs1->snscb_ports[i].portid[0]) << 16) | - (((uint32_t) rs1->snscb_ports[i].portid[1]) << 8) | - (((uint32_t) rs1->snscb_ports[i].portid[2])); - - MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t)); - gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1; - gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF); - gq->snscb_sblen = 6; - gq->snscb_cmd = SNS_GPN_ID; - gq->snscb_portid = lcl.portid; - isp_put_gxn_id_request(isp, gq, - (sns_gxn_id_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); - /* - * Leave 4 and 5 alone - */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; + /* + * Prime the handle we will start using. + */ + oldhandle = 0xffff; + + /* + * Okay, we now have a list of Port IDs for all FC4 SCSI devices + * that the Fabric Name server knows about. Go through the list + * and remove duplicate port ids. + */ + + portlim = 0; + portidx = 0; + for (portidx = 0; portidx < NGENT-1; portidx++) { + if (rs1->snscb_ports[portidx].control & 0x80) { + break; + } + } + + /* + * If we're not at the last entry, our list wasn't big enough. + */ + if ((rs1->snscb_ports[portidx].control & 0x80) == 0) { + isp_prt(isp, ISP_LOGWARN, + "fabric too big for scratch area: increase ISP2100_SCRLEN"); + } + portlim = portidx + 1; + isp_prt(isp, ISP_LOGDEBUG0, "got %d ports back from name server", + portlim); + + for (portidx = 0; portidx < portlim; portidx++) { + int npidx; + + portid = + ((rs1->snscb_ports[portidx].portid[0]) << 16) | + ((rs1->snscb_ports[portidx].portid[1]) << 8) | + ((rs1->snscb_ports[portidx].portid[2])); + + for (npidx = portidx + 1; npidx < portlim; npidx++) { + uint32_t new_portid = + ((rs1->snscb_ports[npidx].portid[0]) << 16) | + ((rs1->snscb_ports[npidx].portid[1]) << 8) | + ((rs1->snscb_ports[npidx].portid[2])); + if (new_portid == portid) { + break; } - FC_SCRATCH_RELEASE(isp); - return (-1); } - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); + + if (npidx < portlim) { + rs1->snscb_ports[npidx].portid[0] = 0; + rs1->snscb_ports[npidx].portid[1] = 0; + rs1->snscb_ports[npidx].portid[2] = 0; + isp_prt(isp, ISP_LOGDEBUG0, + "removing duplicate PortID 0x%x entry from list", + portid); } - MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE); - gs0 = (sns_gxn_id_rsp_t *) ((uint8_t *)fcp->isp_scratch+GXOFF); - isp_get_gxn_id_response(isp, gs0, gs1); - if (gs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID", - gs1->snscb_cthdr.ct_reason, - gs1->snscb_cthdr.ct_explanation, lcl.portid); - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); - } + } + + /* + * Okay, we now have a list of Port IDs for all FC4 SCSI devices + * that the Fabric Name server knows about. + * + * For each entry on this list go through our port database looking + * for probational entries- if we find one, then an old entry is + * is maybe still this one. We get some information to find out. + * + * Otherwise, it's a new fabric device, and we log into it + * (unconditionally). After searching the entire database + * again to make sure that we never ever ever ever have more + * than one entry that has the same PortID or the same + * WWNN/WWPN duple, we enter the device into our database. + */ + + for (portidx = 0; portidx < portlim; portidx++) { + fcportdb_t *lp; + isp_pdb_t pdb; + uint64_t wwnn, wwpn; + int dbidx, r, nr; + + portid = + ((rs1->snscb_ports[portidx].portid[0]) << 16) | + ((rs1->snscb_ports[portidx].portid[1]) << 8) | + ((rs1->snscb_ports[portidx].portid[2])); + + if (portid == 0) { + isp_prt(isp, ISP_LOGDEBUG0, + "skipping null PortID at idx %d", portidx); continue; } - lcl.port_wwn = - (((uint64_t)gs1->snscb_wwn[0]) << 56) | - (((uint64_t)gs1->snscb_wwn[1]) << 48) | - (((uint64_t)gs1->snscb_wwn[2]) << 40) | - (((uint64_t)gs1->snscb_wwn[3]) << 32) | - (((uint64_t)gs1->snscb_wwn[4]) << 24) | - (((uint64_t)gs1->snscb_wwn[5]) << 16) | - (((uint64_t)gs1->snscb_wwn[6]) << 8) | - (((uint64_t)gs1->snscb_wwn[7])); - - MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t)); - gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1; - gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF); - gq->snscb_sblen = 6; - gq->snscb_cmd = SNS_GNN_ID; - gq->snscb_portid = lcl.portid; - isp_put_gxn_id_request(isp, gq, - (sns_gxn_id_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + /* - * Leave 4 and 5 alone + * Skip ourselves... */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; - } - FC_SCRATCH_RELEASE(isp); - return (-1); + if (portid == fcp->isp_portid) { + isp_prt(isp, ISP_LOGDEBUG0, + "skip ourselves @ PortID 0x%06x", portid); + continue; } - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); + isp_prt(isp, ISP_LOGDEBUG0, "Fabric Port 0x%06x", portid); + + /* + * We now search our Port Database for any + * probational entries with this PortID. + */ + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + lp = &fcp->portdb[dbidx]; + + if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { + continue; + } + if (lp->portid == portid) { + break; + } } - MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE); - gs0 = (sns_gxn_id_rsp_t *) ((uint8_t *)fcp->isp_scratch+GXOFF); - isp_get_gxn_id_response(isp, gs0, gs1); - if (gs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID", - gs1->snscb_cthdr.ct_reason, - gs1->snscb_cthdr.ct_explanation, lcl.portid); + + /* + * We found a probational entry with this Port ID. + */ + if (dbidx < MAX_FC_TARG) { + int handle_changed = 0; + + lp = &fcp->portdb[dbidx]; + + /* + * See if we're still logged into it. + * + * If we aren't, mark it as a dead device and + * leave the new portid in the database entry + * for somebody further along to decide what to + * do (policy choice). + * + * If we are, check to see if it's the same + * device still (it should be). If for some + * reason it isn't, mark it as a changed device + * and leave the new portid and role in the + * database entry for somebody further along to + * decide what to do (policy choice). + * + */ + + r = isp_getpdb(isp, lp->handle, &pdb, 0); if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { FC_SCRATCH_RELEASE(isp); + isp_mark_portdb(isp, 1); return (-1); } + if (r != 0) { + lp->new_portid = portid; + lp->state = FC_PORTDB_STATE_DEAD; + continue; + } + + + /* + * Check to make sure that handle, portid, WWPN and + * WWNN agree. If they don't, then the association + * between this PortID and the stated handle has been + * broken by the firmware. + */ + MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + if (pdb.handle != lp->handle || + pdb.portid != portid || + wwpn != lp->port_wwn || + wwnn != lp->node_wwn) { + isp_prt(isp, ISP_LOGDEBUG0, fconf, dbidx, + pdb.handle, pdb.portid, + (uint32_t) (wwnn >> 32), (uint32_t) wwnn, + (uint32_t) (wwpn >> 32), (uint32_t) wwpn, + lp->handle, portid, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + /* + * Try to re-login to this device using a + * new handle. If that fails, mark it dead. + * + * isp_login_device will check for handle and + * portid consistency after re-login. + * + */ + if (isp_login_device(isp, portid, &pdb, + &oldhandle)) { + lp->new_portid = portid; + lp->state = FC_PORTDB_STATE_DEAD; + if (fcp->isp_loopstate != + LOOP_SCANNING_FABRIC) { + FC_SCRATCH_RELEASE(isp); + isp_mark_portdb(isp, 1); + return (-1); + } + continue; + } + MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + if (wwpn != lp->port_wwn || + wwnn != lp->node_wwn) { + isp_prt(isp, ISP_LOGWARN, "changed WWN" + " after relogin"); + lp->new_portid = portid; + lp->state = FC_PORTDB_STATE_DEAD; + continue; + } + + lp->handle = pdb.handle; + handle_changed++; + } + + nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + + /* + * Check to see whether the portid and roles have + * stayed the same. If they have stayed the same, + * we believe that this is the same device and it + * hasn't become disconnected and reconnected, so + * mark it as pending valid. + * + * If they aren't the same, mark the device as a + * changed device and save the new port id and role + * and let somebody else decide. + */ + + lp->new_portid = portid; + lp->new_roles = nr; + if (pdb.portid != lp->portid || nr != lp->roles || + handle_changed) { + lp->state = FC_PORTDB_STATE_CHANGED; + } else { + lp->state = FC_PORTDB_STATE_PENDING_VALID; + } continue; } - lcl.node_wwn = - (((uint64_t)gs1->snscb_wwn[0]) << 56) | - (((uint64_t)gs1->snscb_wwn[1]) << 48) | - (((uint64_t)gs1->snscb_wwn[2]) << 40) | - (((uint64_t)gs1->snscb_wwn[3]) << 32) | - (((uint64_t)gs1->snscb_wwn[4]) << 24) | - (((uint64_t)gs1->snscb_wwn[5]) << 16) | - (((uint64_t)gs1->snscb_wwn[6]) << 8) | - (((uint64_t)gs1->snscb_wwn[7])); /* - * The QLogic f/w is bouncing this with a parameter error. - */ -#if 0 - /* - * Try and get FC4 Features (FC-GS-3 only). - * We can use the sns_gxn_id_req_t for this request. + * Ah- a new entry. Search the database again for all non-NIL + * entries to make sure we never ever make a database entry + * with the same port id. */ - MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t)); - gq->snscb_rblen = SNS_GFF_ID_RESP_SIZE >> 1; - gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF); - gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF); - gq->snscb_sblen = 6; - gq->snscb_cmd = SNS_GFF_ID; - gq->snscb_portid = lcl.portid; - isp_put_gxn_id_request(isp, gq, - (sns_gxn_id_req_t *) fcp->isp_scratch); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_SEND_SNS; - mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + if (dbidx >= FL_ID && dbidx <= SNS_ID) { + continue; + } + if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) { + continue; + } + if (fcp->portdb[dbidx].portid == portid) { + break; + } + } + + if (dbidx != MAX_FC_TARG) { + isp_prt(isp, ISP_LOGWARN, + "PortID 0x%06x already at %d handle %d state %d", + portid, dbidx, fcp->portdb[dbidx].handle, + fcp->portdb[dbidx].state); + continue; + } + /* - * Leave 4 and 5 alone + * Find an empty database entry for it. */ - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (isp_fabric_mbox_cmd(isp, &mbs)) { - if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { - fcp->isp_loopstate = LOOP_PDB_RCVD; + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + if (dbidx >= FL_ID && dbidx <= SNS_ID) { + continue; + } + if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) { + break; } - FC_SCRATCH_RELEASE(isp); - return (-1); } - if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { - FC_SCRATCH_RELEASE(isp); - return (-1); + + if (dbidx == MAX_FC_TARG) { + isp_prt(isp, ISP_LOGERR, + "port database too small to login fabric device" + "- increase MAX_FC_TARG"); + continue; } - MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GFF_ID_RESP_SIZE); - fs0 = (sns_gff_id_rsp_t *) ((uint8_t *)fcp->isp_scratch+GXOFF); - isp_get_gff_id_response(isp, fs0, fs1); - if (fs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, /* ISP_LOGDEBUG0 */ ISP_LOGWARN, - swrej, "GFF_ID", - fs1->snscb_cthdr.ct_reason, - fs1->snscb_cthdr.ct_explanation, lcl.portid); + + /* + * Try to see if we are logged into this device, + * and maybe log into it. + * + * isp_login_device will check for handle and + * portid consistency after login. + */ + if (isp_login_device(isp, portid, &pdb, &oldhandle)) { if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { FC_SCRATCH_RELEASE(isp); + isp_mark_portdb(isp, 1); return (-1); } - } else { - int index = (ftype >> 3); - int bshft = (ftype & 0x7) * 4; - int fc4_fval = - (fs1->snscb_fc4_features[index] >> bshft) & 0xf; - if (fc4_fval & 0x1) { - lcl.roles |= - (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT); + continue; + } + + handle = pdb.handle; + MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + nr = (pdb.s3_role & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + + /* + * And go through the database *one* more time to make sure + * that we do not make more than one entry that has the same + * WWNN/WWPN duple + */ + lp = &fcp->portdb[dbidx]; + + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) { + continue; } - if (fc4_fval & 0x2) { - lcl.roles |= - (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); + if (dbidx >= FL_ID && dbidx <= SNS_ID) { + continue; + } + if (fcp->portdb[dbidx].node_wwn == wwnn && + fcp->portdb[dbidx].port_wwn == wwpn) { + break; } } -#endif + if (dbidx != MAX_FC_TARG) { + isp_prt(isp, ISP_LOGWARN, + "PortID 0x%x 0x%08x%08x/0x%08x%08x %ld already at " + "idx %d", portid, + (uint32_t) (wwnn >> 32), (uint32_t) wwnn, + (uint32_t) (wwpn >> 32), (uint32_t) wwpn, + (long) (lp - fcp->portdb), dbidx); + continue; + } + + lp->handle = handle; + lp->ini_map_idx = 0; + lp->node_wwn = wwnn; + lp->port_wwn = wwpn; + lp->new_portid = portid; + lp->new_roles = nr; + lp->state = FC_PORTDB_STATE_NEW; + } + + + FC_SCRATCH_RELEASE(isp); + if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) { + isp_mark_portdb(isp, 1); + return (-1); + } + fcp->isp_loopstate = LOOP_FSCAN_DONE; + isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done"); + return (0); +} + +/* + * Find an unused handle and try and use to login to a port. + */ +static int +isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp) +{ + int lim, i, r, logval; + uint16_t handle; + + if (IS_24XX(isp)) { + lim = NPH_MAX_24XX; + } else { + lim = NPH_MAX; + } + + handle = isp_nxt_handle(isp, *ohp); + for (i = 0; i < lim; i++) { /* - * If we really want to know what kind of port type this is, - * we have to run another CT command. Otherwise, we'll leave - * it as undefined. - * - lcl.port_type = 0; + * See if we're still logged into something with + * this handle and that something agrees with this + * port id. */ - if (rs1->snscb_ports[i].control & 0x80) { - lcl.last_fabric_dev = 1; + r = isp_getpdb(isp, handle, p, 0); + if (r == 0 && p->portid != portid) { + if (IS_24XX(isp)) { + logval = + PLOGX_FLG_CMD_LOGO | + PLOGX_FLG_IMPLICIT; + isp_plogx_24xx(isp, handle, portid, &logval); + } else { + isp_port_logout(isp, handle, portid); + } + } else if (r == 0) { + break; + } + if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { + return (-1); + } + /* + * Now try and log into the device + */ + if (IS_24XX(isp)) { + logval = PLOGX_FLG_CMD_PLOGI; + isp_plogx_24xx(isp, handle, portid, &logval); } else { - lcl.last_fabric_dev = 0; + logval = isp_port_login(isp, handle, portid); + } + if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { + return (-1); } - (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl); + if (logval == 0) { + *ohp = handle; + break; + } else if ((logval & 0xffff) == MBOX_PORT_ID_USED) { + handle = logval >> 16; + break; + } else if (logval != MBOX_LOOP_ID_USED) { + i = lim; + break; + } else { + *ohp = handle; + handle = isp_nxt_handle(isp, *ohp); + } + } - } while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1); + if (i == lim) { + isp_prt(isp, ISP_LOGINFO, "PLOGI 0x%06x failed", portid); + return (-1); + } /* - * If we're not at the last entry, our list isn't big enough. + * If we successfully logged into it, get the PDB for it + * so we can crosscheck that it is still what we think it + * is and that we also have the role it plays */ - if ((rs1->snscb_ports[i].control & 0x80) == 0) { - isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area"); + r = isp_getpdb(isp, handle, p, 0); + if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { + return (-1); + } + if (r != 0) { + isp_prt(isp, ISP_LOGERR, "new device 0x%06x@0x%x disappeared", + portid, handle); + return (-1); } - FC_SCRATCH_RELEASE(isp); - fcp->isp_loopstate = LOOP_FSCAN_DONE; + if (p->handle != handle || p->portid != portid) { + isp_prt(isp, ISP_LOGERR, + "new device 0x%06x@0x%x changed (0x%06x@0x%0x)", + portid, handle, p->portid, p->handle); + return (-1); + } return (0); } -#endif -static void +static int isp_register_fc4_type(ispsoftc_t *isp) { fcparam *fcp = isp->isp_param; @@ -3046,9 +3783,6 @@ isp_register_fc4_type(ispsoftc_t *isp) reqp->snscb_data[4] = fcp->isp_portid & 0xffff; reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff; reqp->snscb_data[6] = (1 << FC4_SCSI); -#if 0 - reqp->snscb_data[6] |= (1 << FC4_IP); /* ISO/IEC 8802-2 LLC/SNAP */ -#endif FC_SCRATCH_ACQUIRE(isp); isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch); MEMZERO(&mbs, sizeof (mbs)); @@ -3056,16 +3790,149 @@ isp_register_fc4_type(ispsoftc_t *isp) mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); - /* - * Leave 4 and 5 alone - */ mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); + mbs.logval = MBLOGALL; + mbs.timeout = 1000000; MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_RFT_ID_REQ_SIZE); - isp_mboxcmd(isp, &mbs, MBLOGALL); + isp_mboxcmd(isp, &mbs); FC_SCRATCH_RELEASE(isp); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded"); + return (0); + } else { + return (-1); + } +} + +static int +isp_register_fc4_type_24xx(ispsoftc_t *isp) +{ + mbreg_t mbs; + fcparam *fcp = FCPARAM(isp); + union { + isp_ct_pt_t plocal; + rft_id_t clocal; + uint8_t q[QENTRY_LEN]; + } un; + isp_ct_pt_t *pt; + ct_hdr_t *ct; + rft_id_t *rp; + uint8_t *scp = fcp->isp_scratch; + + FC_SCRATCH_ACQUIRE(isp); + /* + * Build a Passthrough IOCB in memory. + */ + MEMZERO(un.q, QENTRY_LEN); + pt = &un.plocal; + pt->ctp_header.rqs_entry_count = 1; + pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; + pt->ctp_handle = 0xffffffff; + pt->ctp_nphdl = NPH_SNS_ID; + pt->ctp_cmd_cnt = 1; + pt->ctp_time = 1; + pt->ctp_rsp_cnt = 1; + pt->ctp_rsp_bcnt = sizeof (ct_hdr_t); + pt->ctp_cmd_bcnt = sizeof (rft_id_t); + pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); + pt->ctp_dataseg[0].ds_count = sizeof (rft_id_t); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t); + isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]); + + /* + * Build the CT header and command in memory. + * + * Note that the CT header has to end up as Big Endian format in memory. + */ + MEMZERO(&un.clocal, sizeof (un.clocal)); + ct = &un.clocal.rftid_hdr; + ct->ct_revision = CT_REVISION; + ct->ct_fcs_type = CT_FC_TYPE_FC; + ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS; + ct->ct_cmd_resp = SNS_RFT_ID; + ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2; + rp = &un.clocal; + rp->rftid_portid[0] = fcp->isp_portid >> 16; + rp->rftid_portid[1] = fcp->isp_portid >> 8; + rp->rftid_portid[2] = fcp->isp_portid; + rp->rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f); + isp_put_rft_id(isp, rp, (rft_id_t *) &scp[XTXOFF]); + + MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t)); + + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64; + mbs.param[1] = QENTRY_LEN; + mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); + mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); + mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF); + mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF); + mbs.logval = MBLOGALL; + MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + FC_SCRATCH_RELEASE(isp); + return (-1); + } + MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN); + pt = &un.plocal; + isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt); + } + if (pt->ctp_status) { + FC_SCRATCH_RELEASE(isp); + isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x", + pt->ctp_status); + return (-1); + } + + isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct); + FC_SCRATCH_RELEASE(isp); + + if (ct->ct_cmd_resp == LS_RJT) { + isp_prt(isp, ISP_LOGWARN, "Register FC4 Type rejected"); + return (-1); + } else if (ct->ct_cmd_resp == LS_ACC) { + isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 Type accepted"); + return(0); + } else { + isp_prt(isp, ISP_LOGWARN, + "Register FC4 Type: %x", ct->ct_cmd_resp); + return (-1); + } +} + +static uint16_t +isp_nxt_handle(ispsoftc_t *isp, uint16_t handle) +{ + if (handle == 0xffff) { + if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) { + handle = 0; + } else { + handle = SNS_ID+1; + } + } else { + handle += 1; + if (handle >= FL_ID && handle <= SNS_ID) { + handle = SNS_ID+1; + } else if (IS_24XX(isp)) { + if (handle == 0xffff) { + handle = 0; + } + } else { + if (handle == MAX_FC_TARG) { + handle = 0; + } + } + } + if (handle == FCPARAM(isp)->isp_loopid) { + return (isp_nxt_handle(isp, handle)); + } else { + return (handle); } } @@ -3077,9 +3944,12 @@ int isp_start(XS_T *xs) { ispsoftc_t *isp; - uint16_t nxti, optr, handle; + uint32_t nxti, optr, handle, isr; + uint16_t sema, mbox; uint8_t local[QENTRY_LEN]; ispreq_t *reqp, *qep; + void *cdbp; + uint16_t *tptr; int target, i; XS_INITERR(xs); @@ -3119,198 +3989,42 @@ isp_start(XS_T *xs) } /* - * Check to see whether we have good firmware state still or - * need to refresh our port database for this target. + * Translate the target to device handle as appropriate, checking + * for correct device state as well. */ target = XS_TGT(xs); if (IS_FC(isp)) { fcparam *fcp = isp->isp_param; - struct lportdb *lp; -#ifdef HANDLE_LOOPSTATE_IN_OUTER_LAYERS + if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) { return (CMD_RQLATER); } - /* - * If we're not on a Fabric, we can't have a target - * above FL_PORT_ID-1. - * - * If we're on a fabric and *not* connected as an F-port, - * we can't have a target less than FC_SNS_ID+1. This - * keeps us from having to sort out the difference between - * local public loop devices and those which we might get - * from a switch's database. - */ - if (fcp->isp_onfabric == 0) { - if (target >= FL_PORT_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - } else { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - /* - * We used to exclude having local loop ports - * at the same time that we have fabric ports. - * That is, we used to exclude having ports - * at < FL_PORT_ID if we're FL-port. - * - * That's wrong. The only thing that could be - * dicey is if the switch you're connected to - * has these local loop ports appear on the - * fabric and we somehow attach them twice. - */ - } -#else - /* - * Check for f/w being in ready state. If the f/w - * isn't in ready state, then we don't know our - * loop ID and the f/w hasn't completed logging - * into all targets on the loop. If this is the - * case, then bounce the command. We pretend this is - * a SELECTION TIMEOUT error if we've never gone to - * FW_READY state at all- in this case we may not - * be hooked to a loop at all and we shouldn't hang - * the machine for this. Otherwise, defer this command - * until later. - */ - if (fcp->isp_fwstate != FW_READY) { - /* - * Give ourselves at most a 250ms delay. - */ - if (isp_fclink_test(isp, 250000)) { - XS_SETERR(xs, HBA_SELTIMEOUT); - if (fcp->loop_seen_once) { - return (CMD_RQLATER); - } else { - return (CMD_COMPLETE); - } - } - } - - /* - * If we're not on a Fabric, we can't have a target - * above FL_PORT_ID-1. - * - * If we're on a fabric and *not* connected as an F-port, - * we can't have a target less than FC_SNS_ID+1. This - * keeps us from having to sort out the difference between - * local public loop devices and those which we might get - * from a switch's database. - */ - if (fcp->isp_onfabric == 0) { - if (target >= FL_PORT_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - } else { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - if (fcp->isp_topo != TOPO_F_PORT && - target < FL_PORT_ID) { - XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); - } - } - - /* - * If our loop state is such that we haven't yet received - * a "Port Database Changed" notification (after a LIP or - * a Loop Reset or firmware initialization), then defer - * sending commands for a little while, but only if we've - * seen a valid loop at one point (otherwise we can get - * stuck at initialization time). - */ - if (fcp->isp_loopstate < LOOP_PDB_RCVD) { - XS_SETERR(xs, HBA_SELTIMEOUT); - if (fcp->loop_seen_once) { - return (CMD_RQLATER); - } else { - return (CMD_COMPLETE); - } - } - - /* - * If we're in the middle of loop or fabric scanning - * or merging the port databases, retry this command later. - */ - if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC || - fcp->isp_loopstate == LOOP_SCANNING_LOOP || - fcp->isp_loopstate == LOOP_SYNCING_PDB) { - return (CMD_RQLATER); - } - - /* - * If our loop state is now such that we've just now - * received a Port Database Change notification, then - * we have to go off and (re)scan the fabric. We back - * out and try again later if this doesn't work. - */ - if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) { - if (isp_scan_fabric(isp, FC4_SCSI)) { - return (CMD_RQLATER); - } - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate < LOOP_FSCAN_DONE) { - return (CMD_RQLATER); - } - } - - /* - * If our loop state is now such that we've just now - * received a Port Database Change notification, then - * we have to go off and (re)synchronize our port - * database. - */ - if (fcp->isp_loopstate < LOOP_READY) { - if (isp_pdb_sync(isp)) { - return (CMD_RQLATER); - } - if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate != LOOP_READY) { - return (CMD_RQLATER); - } - } - - /* - * XXX: Here's were we would cancel any loop_dead flag - * XXX: also cancel in dead_loop timeout that's running - */ -#endif - - /* - * Now check whether we should even think about pursuing this. - */ - lp = &fcp->portdb[target]; - if (lp->valid == 0) { + if (XS_TGT(xs) >= MAX_FC_TARG) { XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } - if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) { - isp_prt(isp, ISP_LOGDEBUG2, - "Target %d does not have target service", target); + + i = fcp->isp_ini_map[XS_TGT(xs)]; + isp_prt(isp, ISP_LOGDEBUG1, "XS_TGT(xs)=%d- handle value %d", + XS_TGT(xs), i); + if (i < 1 || i >= MAX_FC_TARG) { XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } - /* - * Now turn target into what the actual Loop ID is. - */ - target = lp->loopid; + target = fcp->portdb[i - 1].handle; } /* - * Next check to see if any HBA or Device - * parameters need to be updated. + * Next check to see if any HBA or Device parameters need to be updated. */ if (isp->isp_update != 0) { isp_update(isp); } + start_again: + if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) { isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow"); XS_SETERR(xs, HBA_BOTCH); @@ -3324,34 +4038,40 @@ isp_start(XS_T *xs) */ reqp = (ispreq_t *) local; if (isp->isp_sendmarker) { - uint8_t n = (IS_DUALBUS(isp)? 2: 1); - /* - * Check ports to send markers for... - */ - for (i = 0; i < n; i++) { - if ((isp->isp_sendmarker & (1 << i)) == 0) { - continue; - } - MEMZERO((void *) reqp, QENTRY_LEN); - reqp->req_header.rqs_entry_count = 1; - reqp->req_header.rqs_entry_type = RQSTYPE_MARKER; - reqp->req_modifier = SYNC_ALL; - reqp->req_target = i << 7; /* insert bus number */ - isp_put_request(isp, reqp, qep); + if (IS_24XX(isp)) { + isp_marker_24xx_t *m = (isp_marker_24xx_t *) qep; + MEMZERO(m, QENTRY_LEN); + m->mrk_header.rqs_entry_count = 1; + m->mrk_header.rqs_entry_type = RQSTYPE_MARKER; + m->mrk_modifier = SYNC_ALL; + isp_put_marker_24xx(isp, m, (isp_marker_24xx_t *)qep); ISP_ADD_REQUEST(isp, nxti); - isp->isp_sendmarker &= ~(1 << i); - if (isp_getrqentry(isp, &nxti, &optr, (void *) &qep)) { - isp_prt(isp, ISP_LOGDEBUG0, - "Request Queue Overflow+"); - XS_SETERR(xs, HBA_BOTCH); - return (CMD_EAGAIN); + isp->isp_sendmarker = 0; + goto start_again; + } else { + for (i = 0; i < (IS_DUALBUS(isp)? 2: 1); i++) { + isp_marker_t *m = (isp_marker_t *) qep; + if ((isp->isp_sendmarker & (1 << i)) == 0) { + continue; + } + MEMZERO(m, QENTRY_LEN); + m->mrk_header.rqs_entry_count = 1; + m->mrk_header.rqs_entry_type = RQSTYPE_MARKER; + m->mrk_target = (i << 7); /* bus # */ + m->mrk_modifier = SYNC_ALL; + isp_put_marker(isp, m, (isp_marker_t *) qep); + ISP_ADD_REQUEST(isp, nxti); + isp->isp_sendmarker &= ~(1 << i); + goto start_again; } } } MEMZERO((void *)reqp, QENTRY_LEN); reqp->req_header.rqs_entry_count = 1; - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS; + } else if (IS_FC(isp)) { reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS; } else { if (XS_CDBLEN(xs) > 12) @@ -3361,7 +4081,26 @@ isp_start(XS_T *xs) } /* reqp->req_header.rqs_flags = 0; */ /* reqp->req_header.rqs_seqno = 0; */ - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + int ttype; + if (XS_TAG_P(xs)) { + ttype = XS_TAG_TYPE(xs); + } else { + if (XS_CDBP(xs)[0] == 0x3) { + ttype = REQFLAG_HTAG; + } else { + ttype = REQFLAG_STAG; + } + } + if (ttype == REQFLAG_OTAG) { + ttype = FCP_CMND_TASK_ATTR_ORDERED; + } else if (ttype == REQFLAG_HTAG) { + ttype = FCP_CMND_TASK_ATTR_HEAD; + } else { + ttype = FCP_CMND_TASK_ATTR_SIMPLE; + } + ((ispreqt7_t *)reqp)->req_task_attribute = ttype; + } else if (IS_FC(isp)) { /* * See comment in isp_intr */ @@ -3392,25 +4131,47 @@ isp_start(XS_T *xs) reqp->req_flags = XS_TAG_TYPE(xs); } } + cdbp = reqp->req_cdb; + tptr = &reqp->req_time; + if (IS_SCSI(isp)) { reqp->req_target = target | (XS_CHANNEL(xs) << 7); reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); - } else if (IS_2KLOGIN(isp)) { + } else if (IS_24XX(isp)) { + fcportdb_t *lp; + + i = FCPARAM(isp)->isp_ini_map[XS_TGT(xs)] - 1; + lp = &FCPARAM(isp)->portdb[i]; + + ((ispreqt7_t *)reqp)->req_nphdl = target; + ((ispreqt7_t *)reqp)->req_tidlo = lp->portid; + ((ispreqt7_t *)reqp)->req_tidhi = lp->portid >> 16; + if (XS_LUN(xs) > 256) { + ((ispreqt7_t *)reqp)->req_lun[0] = XS_LUN(xs) >> 8; + ((ispreqt7_t *)reqp)->req_lun[0] |= 0x40; + } + ((ispreqt7_t *)reqp)->req_lun[1] = XS_LUN(xs); + cdbp = ((ispreqt7_t *)reqp)->req_cdb; + tptr = &((ispreqt7_t *)reqp)->req_time; + } else if (FCPARAM(isp)->isp_2klogin) { ((ispreqt2e_t *)reqp)->req_target = target; ((ispreqt2e_t *)reqp)->req_scclun = XS_LUN(xs); - } else if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + } else if (FCPARAM(isp)->isp_sccfw) { ((ispreqt2_t *)reqp)->req_target = target; ((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs); } else { ((ispreqt2_t *)reqp)->req_target = target; ((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs); } - MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); + MEMCPY(cdbp, XS_CDBP(xs), XS_CDBLEN(xs)); - reqp->req_time = XS_TIME(xs) / 1000; - if (reqp->req_time == 0 && XS_TIME(xs)) { - reqp->req_time = 1; + *tptr = XS_TIME(xs) / 1000; + if (*tptr == 0 && XS_TIME(xs)) { + *tptr = 1; + } + if (IS_24XX(isp) && *tptr > 0x1999) { + *tptr = 0x1999; } if (isp_save_xs(isp, xs, &handle)) { @@ -3418,6 +4179,7 @@ isp_start(XS_T *xs) XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } + /* Whew. Thankfully the same for type 7 requests */ reqp->req_handle = handle; /* @@ -3440,6 +4202,11 @@ isp_start(XS_T *xs) (long) XS_XFRLEN(xs)); ISP_ADD_REQUEST(isp, nxti); isp->isp_nactive++; + if (IS_23XX(isp) || IS_24XX(isp)) { + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + } + } return (CMD_QUEUED); } @@ -3454,7 +4221,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) XS_T *xs; mbreg_t mbs; int bus, tgt; - uint16_t handle; + uint32_t handle; MEMZERO(&mbs, sizeof (mbs)); @@ -3467,10 +4234,14 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) /* * Issue a bus reset. */ - mbs.param[0] = MBOX_BUS_RESET; - if (IS_SCSI(isp)) { - mbs.param[1] = - ((sdparam *) isp->isp_param)->isp_bus_reset_delay; + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGWARN, "RESET BUS NOT IMPLETENTED"); + break; + } else if (IS_FC(isp)) { + mbs.param[1] = 10; + bus = 0; + } else { + mbs.param[1] = SDPARAM(isp)->isp_bus_reset_delay; if (mbs.param[1] < 2) { mbs.param[1] = 2; } @@ -3478,12 +4249,11 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) if (IS_DUALBUS(isp)) { mbs.param[2] = bus; } - } else { - mbs.param[1] = 10; - bus = 0; } + mbs.param[0] = MBOX_BUS_RESET; isp->isp_sendmarker |= (1 << bus); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -3493,20 +4263,25 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) case ISPCTL_RESET_DEV: tgt = (*((int *) arg)) & 0xffff; - bus = (*((int *) arg)) >> 16; - mbs.param[0] = MBOX_ABORT_TARGET; - if (IS_SCSI(isp)) { - mbs.param[1] = (tgt << 8) | (bus << 15); - } else { - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGWARN, "RESET DEV NOT IMPLETENTED"); + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { mbs.param[1] = tgt; - mbs.ibits |= (1 << 10); + mbs.ibits = (1 << 10); } else { mbs.param[1] = (tgt << 8); } + bus = 0; + } else { + bus = (*((int *) arg)) >> 16; + mbs.param[1] = (bus << 15) | (tgt << 8); } + mbs.param[0] = MBOX_ABORT_TARGET; mbs.param[2] = 3; /* 'delay', in seconds */ - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -3518,17 +4293,19 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) case ISPCTL_ABORT_CMD: xs = (XS_T *) arg; tgt = XS_TGT(xs); + handle = isp_find_handle(isp, xs); if (handle == 0) { isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort"); break; } - bus = XS_CHANNEL(xs); - mbs.param[0] = MBOX_ABORT; - if (IS_FC(isp)) { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGWARN, "ABORT CMD NOT IMPLETENTED"); + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_sccfw) { + if (FCPARAM(isp)->isp_2klogin) { mbs.param[1] = tgt; } else { mbs.param[1] = tgt << 8; @@ -3538,19 +4315,17 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) mbs.param[1] = tgt << 8 | XS_LUN(xs); } } else { - mbs.param[1] = - (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs); + bus = XS_CHANNEL(xs); + mbs.param[1] = (bus << 15) | (tgt << 8) | XS_LUN(xs); } + mbs.param[0] = MBOX_ABORT; mbs.param[2] = handle; - isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_ERROR); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - return (0); + mbs.logval = MBLOGALL & ~MBOX_COMMAND_ERROR; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + break; } - /* - * XXX: Look for command in the REQUEST QUEUE. That is, - * XXX: It hasen't been picked up by firmware yet. - */ - break; + return (0); case ISPCTL_UPDATE_PARAMS: @@ -3571,8 +4346,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) case ISPCTL_SCAN_FABRIC: if (IS_FC(isp)) { - int ftype = (arg)? *((int *) arg) : FC4_SCSI; - return (isp_scan_fabric(isp, ftype)); + return (isp_scan_fabric(isp)); } break; @@ -3592,37 +4366,41 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) case ISPCTL_SEND_LIP: - if (IS_FC(isp)) { + if (IS_FC(isp) && !IS_24XX(isp)) { mbs.param[0] = MBOX_INIT_LIP; - if (IS_2KLOGIN(isp)) { - mbs.ibits |= (1 << 10); + if (FCPARAM(isp)->isp_2klogin) { + mbs.ibits = (1 << 10); } - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { return (0); } } break; - case ISPCTL_GET_POSMAP: - - if (IS_FC(isp) && arg) { - return (isp_getmap(isp, arg)); - } - break; - - case ISPCTL_GET_PDB: if (IS_FC(isp) && arg) { int id = *((int *)arg); isp_pdb_t *pdb = arg; - return (isp_getpdb(isp, id, pdb)); + return (isp_getpdb(isp, id, pdb, 1)); } break; + case ISPCTL_GET_PORTNAME: + { + uint64_t *wwnp = arg; + int loopid = *wwnp; + *wwnp = isp_get_portname(isp, loopid, 0); + if (*wwnp == (uint64_t) -1) { + break; + } else { + return (0); + } + } case ISPCTL_RUN_MBOXCMD: - isp_mboxcmd(isp, arg, MBLOGALL); + isp_mboxcmd(isp, arg); return(0); #ifdef ISP_TARGET_MODE @@ -3638,7 +4416,8 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) mbs.param[0] = MBOX_ENABLE_TARGET_MODE; mbs.param[1] = param & 0xffff; mbs.param[2] = param >> 16; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } @@ -3662,17 +4441,18 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) * of completions on a request queue at any one time. */ #ifndef MAX_REQUESTQ_COMPLETIONS -#define MAX_REQUESTQ_COMPLETIONS 64 +#define MAX_REQUESTQ_COMPLETIONS 32 #endif void -isp_intr(ispsoftc_t *isp, uint16_t isr, uint16_t sema, uint16_t mbox) +isp_intr(ispsoftc_t *isp, uint32_t isr, uint16_t sema, uint16_t mbox) { XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs; - uint16_t iptr, optr, junk; + uint32_t iptr, optr, junk; int i, nlooked = 0, ndone = 0; again: + optr = isp->isp_residx; /* * Is this a mailbox related interrupt? * The mailbox semaphore will be nonzero if so. @@ -3698,16 +4478,14 @@ again: MBOX_NOTIFY_COMPLETE(isp); } else { isp_prt(isp, ISP_LOGWARN, - "Mbox Command Async (0x%x) with no waiters", - mbox); + "mailbox cmd (0x%x) with no waiters", mbox); } } else if (isp_parse_async(isp, mbox) < 0) { return; } if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) || isp->isp_state != ISP_RUNSTATE) { - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); + goto out; return; } } @@ -3716,32 +4494,72 @@ again: * We can't be getting this now. */ if (isp->isp_state != ISP_RUNSTATE) { - isp_prt(isp, ISP_LOGWARN, + isp_prt(isp, ISP_LOGINFO, "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema); /* * Thank you very much! *Burrrp*! */ - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, - READ_RESPONSE_QUEUE_IN_POINTER(isp)); + ISP_WRITE(isp, isp->isp_respoutrp, + ISP_READ(isp, isp->isp_respinrp)); + if (IS_24XX(isp)) { + ISP_DISABLE_INTS(isp); + } + goto out; + } - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); - return; +#ifdef ISP_TARGET_MODE + /* + * Check for ATIO Queue entries. + */ + if (isp->isp_rspbsy == 0 && (isp->isp_role & ISP_ROLE_TARGET) && + IS_24XX(isp)) { + iptr = ISP_READ(isp, isp->isp_atioinrp); + optr = ISP_READ(isp, isp->isp_atiooutrp); + + isp->isp_rspbsy = 1; + while (optr != iptr) { + uint8_t qe[QENTRY_LEN]; + isphdr_t *hp; + uint32_t oop; + void *addr; + + oop = optr; + MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN); + addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop); + isp_get_hdr(isp, addr, (isphdr_t *)qe); + hp = (isphdr_t *)qe; + switch (hp->rqs_entry_type) { + case RQSTYPE_NOTIFY: + case RQSTYPE_ATIO: + (void) isp_target_notify(isp, addr, &oop); + break; + default: + isp_print_qentry(isp, "?ATIOQ entry?", + oop, addr); + break; + } + optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp)); + ISP_WRITE(isp, isp->isp_atiooutrp, optr); + } + isp->isp_rspbsy = 0; } +#endif /* * Get the current Response Queue Out Pointer. * - * If we're a 2300, we can ask what hardware what it thinks. + * If we're a 2300 or 2400, we can ask what hardware what it thinks. */ - if (IS_23XX(isp)) { + if (IS_23XX(isp) || IS_24XX(isp)) { optr = ISP_READ(isp, isp->isp_respoutrp); /* * Debug: to be taken out eventually */ if (isp->isp_residx != optr) { - isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x", + isp_prt(isp, ISP_LOGINFO, + "isp_intr: hard optr=%x, soft optr %x", optr, isp->isp_residx); + isp->isp_residx = optr; } } else { optr = isp->isp_residx; @@ -3756,19 +4574,18 @@ again: if (IS_2100(isp) || (IS_2300(isp) && isp->isp_revision < 2)) { i = 0; do { - iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); - junk = READ_RESPONSE_QUEUE_IN_POINTER(isp); + iptr = ISP_READ(isp, isp->isp_respinrp); + junk = ISP_READ(isp, isp->isp_respinrp); } while (junk != iptr && ++i < 1000); if (iptr != junk) { - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); isp_prt(isp, ISP_LOGWARN, "Response Queue Out Pointer Unstable (%x, %x)", iptr, junk); - return; + goto out; } } else { - iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); + iptr = ISP_READ(isp, isp->isp_respinrp); } isp->isp_resodx = iptr; @@ -3782,15 +4599,17 @@ again: * make sure the old interrupt went away (to avoid 'ringing' * effects), but that didn't stop this from occurring. */ - if (IS_23XX(isp)) { + if (IS_24XX(isp)) { + junk = 0; + } else if (IS_23XX(isp)) { USEC_DELAY(100); - iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); + iptr = ISP_READ(isp, isp->isp_respinrp); junk = ISP_READ(isp, BIU_R2HSTSLO); } else { junk = ISP_READ(isp, BIU_ISR); } if (optr == iptr) { - if (IS_23XX(isp)) { + if (IS_23XX(isp) || IS_24XX(isp)) { ; } else { sema = ISP_READ(isp, BIU_SEMA); @@ -3806,43 +4625,73 @@ again: } } isp->isp_resodx = iptr; - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); + if (isp->isp_rspbsy) { - return; + goto out; } isp->isp_rspbsy = 1; - while (optr != iptr) { - ispstatusreq_t local, *sp = &local; + uint8_t qe[QENTRY_LEN]; + ispstatusreq_t *sp = (ispstatusreq_t *) qe; isphdr_t *hp; - int type; + int buddaboom, etype, scsi_status, completion_status; + int req_status_flags, req_state_flags; + long resid; uint16_t oop; - int buddaboom = 0; hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr); oop = optr; optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp)); nlooked++; read_again: + buddaboom = req_status_flags = req_state_flags = 0; + resid = 0L; + /* * Synchronize our view of this response queue entry. */ MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN); - - type = isp_get_response_type(isp, hp); - - if (type == RQSTYPE_RESPONSE) { + isp_get_hdr(isp, hp, &sp->req_header); + etype = sp->req_header.rqs_entry_type; + + if (IS_24XX(isp) && etype == RQSTYPE_T7RQS) { + isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe; + isp_get_24xx_response(isp, + (isp24xx_statusreq_t *)hp, sp2); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, + "Response Queue Entry", QENTRY_LEN, sp2); + } + scsi_status = sp2->req_scsi_status; + completion_status = sp2->req_completion_status; + req_state_flags = 0; + resid = sp2->req_resid; + } else if (etype == RQSTYPE_RESPONSE) { isp_get_response(isp, (ispstatusreq_t *) hp, sp); - } else if (type == RQSTYPE_RIO2) { - isp_rio2_t rio; - isp_get_rio2(isp, (isp_rio2_t *) hp, &rio); - for (i = 0; i < rio.req_header.rqs_seqno; i++) { - isp_fastpost_complete(isp, rio.req_handles[i]); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, + "Response Queue Entry", QENTRY_LEN, sp); + } + scsi_status = sp->req_scsi_status; + completion_status = sp->req_completion_status; + req_status_flags = sp->req_status_flags; + req_state_flags = sp->req_state_flags; + resid = sp->req_resid; + } else if (etype == RQSTYPE_RIO2) { + isp_rio2_t *rio = (isp_rio2_t *)qe; + isp_get_rio2(isp, (isp_rio2_t *) hp, rio); + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, + "Response Queue Entry", QENTRY_LEN, rio); + } + for (i = 0; i < rio->req_header.rqs_seqno; i++) { + isp_fastpost_complete(isp, rio->req_handles[i]); + } + if (isp->isp_fpcchiwater < rio->req_header.rqs_seqno) { + isp->isp_fpcchiwater = + rio->req_header.rqs_seqno; } - if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno) - isp->isp_fpcchiwater = rio.req_header.rqs_seqno; MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } else { @@ -3851,10 +4700,12 @@ again: * may have updated the response queue pointers for * us, so we reload our goal index. */ - int i = isp_handle_other_response(isp, type, hp, &optr); - if (i < 0) { + int r; + r = isp_handle_other_response(isp, etype, hp, &optr); + if (r < 0) { goto read_again; - } else if (i > 0) { + } + if (r > 0) { iptr = isp->isp_resodx; MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; @@ -3865,34 +4716,33 @@ again: * we don't know how to deal with the rest of the * response. */ - isp_get_response(isp, (ispstatusreq_t *) hp, sp); /* * It really has to be a bounced request just copied * from the request queue to the response queue. If * not, something bad has happened. */ - if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) { + if (etype != RQSTYPE_REQUEST) { isp_prt(isp, ISP_LOGERR, notresp, - sp->req_header.rqs_entry_type, oop, optr, - nlooked); - if (isp->isp_dblev & ISP_LOGDEBUG0) { - isp_print_bytes(isp, "Queue Entry", - QENTRY_LEN, sp); - } + etype, oop, optr, nlooked); + isp_print_bytes(isp, + "Reqeonse Queue Entry", QENTRY_LEN, sp); MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } buddaboom = 1; + scsi_status = sp->req_scsi_status; + completion_status = sp->req_completion_status; + req_status_flags = sp->req_status_flags; + req_state_flags = sp->req_state_flags; + resid = sp->req_resid; } - if (sp->req_header.rqs_flags & 0xf) { -#define _RQS_OFLAGS \ - ~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET) + if (sp->req_header.rqs_flags & RQSFLAG_MASK) { if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) { isp_prt(isp, ISP_LOGWARN, "continuation segment"); - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + ISP_WRITE(isp, isp->isp_respoutrp, optr); continue; } if (sp->req_header.rqs_flags & RQSFLAG_FULL) { @@ -3903,53 +4753,47 @@ again: */ } if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) { - isp_prt(isp, ISP_LOGERR, "bad header flag"); + isp_print_bytes(isp, "bad header flag", + QENTRY_LEN, sp); buddaboom++; } if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) { - isp_prt(isp, ISP_LOGERR, "bad request packet"); + isp_print_bytes(isp, "bad request packet", + QENTRY_LEN, sp); buddaboom++; } - if (sp->req_header.rqs_flags & _RQS_OFLAGS) { - isp_prt(isp, ISP_LOGERR, - "unknown flags (0x%x) in response", - sp->req_header.rqs_flags); - buddaboom++; - } -#undef _RQS_OFLAGS } + if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) { - MEMZERO(hp, QENTRY_LEN); /* PERF */ isp_prt(isp, ISP_LOGERR, - "bad request handle %d (type 0x%x, flags 0x%x)", - sp->req_handle, sp->req_header.rqs_entry_type, - sp->req_header.rqs_flags); - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + "bad request handle %d (type 0x%x)", + sp->req_handle, etype); + MEMZERO(hp, QENTRY_LEN); /* PERF */ + ISP_WRITE(isp, isp->isp_respoutrp, optr); continue; } xs = isp_find_xs(isp, sp->req_handle); if (xs == NULL) { - uint8_t ts = sp->req_completion_status & 0xff; - MEMZERO(hp, QENTRY_LEN); /* PERF */ + uint8_t ts = completion_status & 0xff; /* * Only whine if this isn't the expected fallout of * aborting the command. */ - if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) { + if (etype != RQSTYPE_RESPONSE) { isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", - sp->req_handle, - sp->req_header.rqs_entry_type); + sp->req_handle, etype); } else if (ts != RQCS_ABORTED) { isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts); } - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + MEMZERO(hp, QENTRY_LEN); /* PERF */ + ISP_WRITE(isp, isp->isp_respoutrp, optr); continue; } isp_destroy_handle(isp, sp->req_handle); - if (sp->req_status_flags & RQSTF_BUS_RESET) { + if (req_status_flags & RQSTF_BUS_RESET) { XS_SETERR(xs, HBA_BUSRESET); isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); } @@ -3957,31 +4801,37 @@ again: XS_SETERR(xs, HBA_BOTCH); } - if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) { + if (IS_FC(isp) && (scsi_status & RQCS_SV) != 0) { /* * Fibre Channel F/W doesn't say we got status * if there's Sense Data instead. I guess they * think it goes w/o saying. */ - sp->req_state_flags |= RQSF_GOT_STATUS; + req_state_flags |= RQSF_GOT_STATUS; } - if (sp->req_state_flags & RQSF_GOT_STATUS) { - *XS_STSP(xs) = sp->req_scsi_status & 0xff; + if (req_state_flags & RQSF_GOT_STATUS) { + *XS_STSP(xs) = scsi_status & 0xff; } - switch (sp->req_header.rqs_entry_type) { + switch (etype) { case RQSTYPE_RESPONSE: + /* XXX won't work for 24xx */ XS_SET_STATE_STAT(isp, xs, sp); - isp_parse_status(isp, sp, xs); + if (IS_24XX(isp)) { + isp_parse_status_24xx(isp, + (isp24xx_statusreq_t *)sp, xs, &resid); + } else { + isp_parse_status(isp, (void *)sp, xs, &resid); + } if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && (*XS_STSP(xs) == SCSI_BUSY)) { XS_SETERR(xs, HBA_TGTBSY); } if (IS_SCSI(isp)) { - XS_RESID(xs) = sp->req_resid; - if ((sp->req_state_flags & RQSF_GOT_STATUS) && + XS_RESID(xs) = resid; + if ((req_state_flags & RQSF_GOT_STATUS) && (*XS_STSP(xs) == SCSI_CHECK) && - (sp->req_state_flags & RQSF_GOT_SENSE)) { + (req_state_flags & RQSF_GOT_SENSE)) { XS_SAVE_SENSE(xs, sp); } /* @@ -3989,7 +4839,7 @@ again: * this target. Mark state such that we'll go * look up that which has changed later. */ - if (sp->req_status_flags & RQSTF_NEGOTIATION) { + if (req_status_flags & RQSTF_NEGOTIATION) { int t = XS_TGT(xs); sdparam *sdp = isp->isp_param; sdp += XS_CHANNEL(xs); @@ -3998,27 +4848,30 @@ again: (1 << XS_CHANNEL(xs)); } } else { - if (sp->req_status_flags & RQSF_XFER_COMPLETE) { + if (req_status_flags & RQSF_XFER_COMPLETE) { XS_RESID(xs) = 0; - } else if (sp->req_scsi_status & RQCS_RESID) { - XS_RESID(xs) = sp->req_resid; + } else if (scsi_status & RQCS_RESID) { + XS_RESID(xs) = resid; } else { XS_RESID(xs) = 0; } - if ((sp->req_state_flags & RQSF_GOT_STATUS) && + if ((req_state_flags & RQSF_GOT_STATUS) && (*XS_STSP(xs) == SCSI_CHECK) && - (sp->req_scsi_status & RQCS_SV)) { + (scsi_status & RQCS_SV)) { XS_SAVE_SENSE(xs, sp); /* solely for the benefit of debug */ - sp->req_state_flags |= RQSF_GOT_SENSE; + req_state_flags |= RQSF_GOT_SENSE; } } isp_prt(isp, ISP_LOGDEBUG2, "asked for %ld got raw resid %ld settled for %ld", - (long) XS_XFRLEN(xs), (long) sp->req_resid, - (long) XS_RESID(xs)); + (long) XS_XFRLEN(xs), resid, (long) XS_RESID(xs)); break; case RQSTYPE_REQUEST: + case RQSTYPE_A64: + case RQSTYPE_T2RQS: + case RQSTYPE_T3RQS: + case RQSTYPE_T7RQS: if (sp->req_header.rqs_flags & RQSFLAG_FULL) { /* * Force Queue Full status. @@ -4029,16 +4882,19 @@ again: /* * ???? */ + XS_SETERR(xs, HBA_BOTCH); isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Entry bounced back"); - XS_SETERR(xs, HBA_BOTCH); + if ((isp->isp_dblev & ISP_LOGDEBUG1) == 0) { + isp_print_bytes(isp, "Bounced Request", + QENTRY_LEN, qe); + } } XS_RESID(xs) = XS_XFRLEN(xs); break; default: - isp_prt(isp, ISP_LOGWARN, - "unhandled response queue type 0x%x", - sp->req_header.rqs_entry_type); + isp_print_bytes(isp, "Unhandled Response Type", + QENTRY_LEN, qe); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BOTCH); } @@ -4056,7 +4912,7 @@ again: ((isp->isp_dblev & ISP_LOGDEBUG1) && ((!XS_NOERR(xs)) || (*XS_STSP(xs) != SCSI_GOOD)))) { char skey; - if (sp->req_state_flags & RQSF_GOT_SENSE) { + if (req_state_flags & RQSF_GOT_SENSE) { skey = XS_SNSKEY(xs) & 0xf; if (skey < 10) skey += '0'; @@ -4087,13 +4943,23 @@ again: * ISP's notion of what we've seen so far. */ if (nlooked) { - WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + ISP_WRITE(isp, isp->isp_respoutrp, optr); /* * While we're at it, read the requst queue out pointer. */ - isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp); - if (isp->isp_rscchiwater < ndone) + isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp); + if (isp->isp_rscchiwater < ndone) { isp->isp_rscchiwater = ndone; + } + } + +out: + + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU_SEMA, 0); } isp->isp_residx = optr; @@ -4128,8 +4994,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) case ASYNC_BUS_RESET: isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif isp_async(isp, ISPASYNC_BUS_RESET, &bus); break; @@ -4179,7 +5046,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) * We don't need to be chatty about this- just unlatch things * and move on. */ - mbox = READ_REQUEST_QUEUE_OUT_POINTER(isp); + mbox = ISP_READ(isp, isp->isp_rqstoutrp); break; case ASYNC_TIMEOUT_RESET: @@ -4187,8 +5054,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) "timeout initiated SCSI bus reset of bus %d", bus); isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; @@ -4196,8 +5064,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus); isp->isp_sendmarker |= (1 << bus); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif break; @@ -4300,16 +5169,18 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) #endif break; } + case ASYNC_LIP_ERROR: case ASYNC_LIP_F8: case ASYNC_LIP_OCCURRED: FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp->isp_sendmarker = 1; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_LIP, NULL); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif /* * We've had problems with data corruption occuring on @@ -4340,7 +5211,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_LOOP_UP, NULL); #ifdef ISP_TARGET_MODE if (isp_target_async(isp, bus, mbox)) { @@ -4353,7 +5224,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_NIL; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_LOOP_DOWN, NULL); #ifdef ISP_TARGET_MODE if (isp_target_async(isp, bus, mbox)) { @@ -4366,7 +5237,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_NIL; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_LOOP_RESET, NULL); #ifdef ISP_TARGET_MODE if (isp_target_async(isp, bus, mbox)) { @@ -4378,39 +5249,37 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) case ASYNC_PDB_CHANGED: isp->isp_sendmarker = 1; FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB); break; case ASYNC_CHANGE_NOTIFY: - /* - * Not correct, but it will force us to rescan the loop. - */ - FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - isp_mark_getpdb_all(isp); + if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) { + FCPARAM(isp)->isp_loopstate = LOOP_LSCAN_DONE; + } else { + FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; + } + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS); break; case ASYNC_PTPMODE: - if (FCPARAM(isp)->isp_onfabric) - FCPARAM(isp)->isp_topo = TOPO_F_PORT; - else - FCPARAM(isp)->isp_topo = TOPO_N_PORT; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp->isp_sendmarker = 1; FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER); #ifdef ISP_TARGET_MODE - if (isp_target_async(isp, bus, mbox)) + if (isp_target_async(isp, bus, mbox)) { rval = -1; + } #endif isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode"); break; case ASYNC_CONNMODE: mbox = ISP_READ(isp, OUTMAILBOX1); - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); switch (mbox) { case ISP_CONN_LOOP: isp_prt(isp, ISP_LOGINFO, @@ -4449,6 +5318,15 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; break; + case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */ + if (IS_24XX(isp)) { + isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent"); + break; + } else if (IS_2200(isp)) { + isp_prt(isp, ISP_LOGTDEBUG0, "QFULL sent"); + break; + } + /* FALLTHROUGH */ default: isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox); break; @@ -4469,8 +5347,9 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp_prt(isp, ISP_LOGDEBUG3, "fast post completion of %u", handles[i]); } - if (isp->isp_fpcchiwater < nh) + if (isp->isp_fpcchiwater < nh) { isp->isp_fpcchiwater = nh; + } } else { isp->isp_intoasync++; } @@ -4485,11 +5364,14 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) static int isp_handle_other_response(ispsoftc_t *isp, int type, - isphdr_t *hp, uint16_t *optrp) + isphdr_t *hp, uint32_t *optrp) { switch (type) { case RQSTYPE_STATUS_CONT: - isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response"); + isp_prt(isp, ISP_LOGDEBUG0, "Ignored Continuation Response"); + return (1); + case RQSTYPE_MARKER: + isp_prt(isp, ISP_LOGDEBUG0, "Marker Response"); return (1); case RQSTYPE_ATIO: case RQSTYPE_CTIO: @@ -4501,6 +5383,9 @@ isp_handle_other_response(ispsoftc_t *isp, int type, case RQSTYPE_ATIO2: case RQSTYPE_CTIO2: case RQSTYPE_CTIO3: + case RQSTYPE_CTIO7: + case RQSTYPE_ABTS_RCVD: + case RQSTYPE_ABTS_RSP: isp->isp_rsltccmplt++; /* count as a response completion */ #ifdef ISP_TARGET_MODE if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) { @@ -4534,7 +5419,7 @@ isp_handle_other_response(ispsoftc_t *isp, int type, } static void -isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) +isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp) { switch (sp->req_completion_status & 0xff) { case RQCS_COMPLETE: @@ -4550,6 +5435,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_SELTIMEOUT); + *rp = XS_XFRLEN(xs); } return; } @@ -4562,6 +5448,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) case RQCS_DMA_ERROR: isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + *rp = XS_XFRLEN(xs); break; case RQCS_TRANSPORT_ERROR: @@ -4617,6 +5504,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) isp_prt(isp, ISP_LOGERR, "%s", buf); isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), buf); + *rp = XS_XFRLEN(xs); break; } case RQCS_RESET_OCCURRED: @@ -4627,6 +5515,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_BUSRESET); } + *rp = XS_XFRLEN(xs); return; case RQCS_ABORTED: @@ -4642,15 +5531,8 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); /* - * Check to see if we logged out the device. + * XXX: Check to see if we logged out of the device. */ - if (IS_FC(isp)) { - if ((sp->req_completion_status & RQSTF_LOGOUT) && - FCPARAM(isp)->portdb[XS_TGT(xs)].valid && - FCPARAM(isp)->portdb[XS_TGT(xs)].fabric_dev) { - FCPARAM(isp)->portdb[XS_TGT(xs)].relogin = 1; - } - } if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_CMDTIMEOUT); } @@ -4857,28 +5739,36 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) * No such port on the loop. Moral equivalent of SELTIMEO */ case RQCS_PORT_LOGGED_OUT: + { + char *reason; + uint8_t sts = sp->req_completion_status & 0xff; + /* * It was there (maybe)- treat as a selection timeout. */ - if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE) - isp_prt(isp, ISP_LOGINFO, - "port unavailable for target %d", XS_TGT(xs)); - else - isp_prt(isp, ISP_LOGINFO, - "port logout for target %d", XS_TGT(xs)); + if (sts == RQCS_PORT_UNAVAILABLE) { + reason = "unavailable"; + } else { + reason = "logout"; + } + + isp_prt(isp, ISP_LOGINFO, "port %s for target %d", + reason, XS_TGT(xs)); + /* * If we're on a local loop, force a LIP (which is overkill) * to force a re-login of this unit. If we're on fabric, - * then we'll have to relogin as a matter of course. + * then we'll have to log in again as a matter of course. */ if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT || FCPARAM(isp)->isp_topo == TOPO_FL_PORT) { mbreg_t mbs; MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_INIT_LIP; - if (IS_2KLOGIN(isp)) { - mbs.ibits |= (1 << 10); + if (FCPARAM(isp)->isp_2klogin) { + mbs.ibits = (1 << 10); } + mbs.logval = MBLOGALL; isp_mboxcmd_qnw(isp, &mbs, 1); } @@ -4887,13 +5777,13 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) */ isp->isp_sendmarker = 1; FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 1); isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_SELTIMEOUT); } return; - + } case RQCS_PORT_CHANGED: isp_prt(isp, ISP_LOGWARN, "port changed for target %d", XS_TGT(xs)); @@ -4921,6 +5811,176 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs) } static void +isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, + XS_T *xs, long *rp) +{ + switch (sp->req_completion_status) { + case RQCS_COMPLETE: + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_NOERROR); + } + return; + + case RQCS_DMA_ERROR: + isp_prt(isp, ISP_LOGERR, "DMA error for command on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + break; + + case RQCS_TRANSPORT_ERROR: + isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + break; + + case RQCS_RESET_OCCURRED: + isp_prt(isp, ISP_LOGWARN, + "bus reset destroyed command for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BUSRESET); + } + return; + + case RQCS_ABORTED: + isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + isp->isp_sendmarker |= (1 << XS_CHANNEL(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } + return; + + case RQCS_TIMEOUT: + isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_CMDTIMEOUT); + } + return; + + case RQCS_DATA_OVERRUN: + XS_RESID(xs) = sp->req_resid; + isp_prt(isp, ISP_LOGERR, "data overrun for command on %d.%d.%d", + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_DATAOVR); + } + return; + + case RQCS_24XX_DRE: /* data reassembly error */ + isp_prt(isp, ISP_LOGERR, "data reassembly error for target %d", + XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } + *rp = XS_XFRLEN(xs); + return; + + case RQCS_24XX_TABORT: /* aborted by target */ + isp_prt(isp, ISP_LOGERR, "target %d sent ABTS", + XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_ABORTED); + } + return; + + case RQCS_DATA_UNDERRUN: + + XS_RESID(xs) = sp->req_resid; + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_NOERROR); + } + return; + + case RQCS_PORT_UNAVAILABLE: + /* + * No such port on the loop. Moral equivalent of SELTIMEO + */ + case RQCS_PORT_LOGGED_OUT: + { + char *reason; + uint8_t sts = sp->req_completion_status & 0xff; + + /* + * It was there (maybe)- treat as a selection timeout. + */ + if (sts == RQCS_PORT_UNAVAILABLE) { + reason = "unavailable"; + } else { + reason = "logout"; + } + + isp_prt(isp, ISP_LOGINFO, "port %s for target %d", + reason, XS_TGT(xs)); + + /* + * If we're on a local loop, force a LIP (which is overkill) + * to force a re-login of this unit. If we're on fabric, + * then we'll have to log in again as a matter of course. + */ + if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT || + FCPARAM(isp)->isp_topo == TOPO_FL_PORT) { + mbreg_t mbs; + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_INIT_LIP; + if (FCPARAM(isp)->isp_2klogin) { + mbs.ibits = (1 << 10); + } + mbs.logval = MBLOGALL; + isp_mboxcmd_qnw(isp, &mbs, 1); + } + + /* + * Probably overkill. + */ + isp->isp_sendmarker = 1; + FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; + isp_mark_portdb(isp, 1); + isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } + return; + } + case RQCS_PORT_CHANGED: + isp_prt(isp, ISP_LOGWARN, + "port changed for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + } + return; + + + case RQCS_24XX_ENOMEM: /* f/w resource unavailable */ + isp_prt(isp, ISP_LOGWARN, + "f/w resource unavailable for target %d", XS_TGT(xs)); + if (XS_NOERR(xs)) { + *XS_STSP(xs) = SCSI_BUSY; + XS_SETERR(xs, HBA_TGTBSY); + } + return; + + case RQCS_24XX_TMO: /* task management overrun */ + isp_prt(isp, ISP_LOGWARN, + "command for target %d overlapped task management", + XS_TGT(xs)); + if (XS_NOERR(xs)) { + *XS_STSP(xs) = SCSI_BUSY; + XS_SETERR(xs, HBA_TGTBSY); + } + return; + + default: + isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x", + sp->req_completion_status); + break; + } + if (XS_NOERR(xs)) { + XS_SETERR(xs, HBA_BOTCH); + } +} + +static void isp_fastpost_complete(ispsoftc_t *isp, uint16_t fph) { XS_T *xs; @@ -4977,8 +6037,12 @@ isp_mbox_continue(ispsoftc_t *isp) /* * Clear the previous interrupt. */ - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU_SEMA, 0); + } /* * Continue with next word. @@ -4996,7 +6060,7 @@ isp_mbox_continue(ispsoftc_t *isp) break; case MBOX_WRITE_RAM_WORD_EXTENDED: offset = isp->isp_mbxwrk1; - offset |= ((uint32_t) isp->isp_mbxwrk8 << 16); + offset |= isp->isp_mbxwrk8 << 16; mbs.param[2] = *ptr++;; mbs.param[1] = offset; @@ -5006,7 +6070,7 @@ isp_mbox_continue(ispsoftc_t *isp) break; case MBOX_READ_RAM_WORD_EXTENDED: offset = isp->isp_mbxwrk1; - offset |= ((uint32_t) isp->isp_mbxwrk8 << 16); + offset |= isp->isp_mbxwrk8 << 16; *ptr++ = isp->isp_mboxtmp[2]; mbs.param[1] = offset; @@ -5018,11 +6082,11 @@ isp_mbox_continue(ispsoftc_t *isp) isp->isp_mbxworkp = ptr; isp->isp_mbxwrk0--; mbs.param[0] = isp->isp_lastmbxcmd; + mbs.logval = MBLOGALL; isp_mboxcmd_qnw(isp, &mbs, 0); return (0); } - #define HIWRD(x) ((x) >> 16) #define LOWRD(x) ((x) & 0xffff) #define ISPOPMAP(a, b) (((a) << 16) | (b)) @@ -5111,7 +6175,7 @@ static const uint32_t mbpscsi[] = { ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */ ISPOPMAP(0xdf, 0xff), /* 0x52: INITIALIZE REQUEST QUEUE A64 */ ISPOPMAP(0xef, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */ - ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ + ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUCUTE COMMAND IOCB A64 */ ISPOPMAP(0x07, 0x01), /* 0x55: ENABLE TARGET MODE */ ISPOPMAP(0x03, 0x0f), /* 0x56: GET TARGET STATUS */ ISPOPMAP(0x00, 0x00), /* 0x57: */ @@ -5123,7 +6187,6 @@ static const uint32_t mbpscsi[] = { ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */ }; -#ifndef ISP_STRIPPED static char *scsi_mbcmd_names[] = { "NO-OP", "LOAD RAM", @@ -5220,23 +6283,22 @@ static char *scsi_mbcmd_names[] = { "SET HOST DATA", "GET NOST DATA", }; -#endif static const uint32_t mbpfc[] = { ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ - ISPOPMAP(0x07, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ + ISPOPMAP(0x0f, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ ISPOPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */ ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ - ISPOPMAP(0x03, 0x05), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ ISPOPMAP(0x01, 0x4f), /* 0x08: MBOX_ABOUT_FIRMWARE */ ISPOPMAP(0xdf, 0x01), /* 0x09: LOAD RAM */ ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ - ISPOPMAP(0x00, 0x00), /* 0x0b: */ + ISPOPMAP(0x1ff, 0x01), /* 0x0b: MBOX_LOAD_RISC_RAM */ ISPOPMAP(0x00, 0x00), /* 0x0c: */ - ISPOPMAP(0x10f, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED) */ + ISPOPMAP(0x10f, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */ ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ ISPOPMAP(0x10f, 0x05), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */ ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ @@ -5289,8 +6351,8 @@ static const uint32_t mbpfc[] = { ISPOPMAP(0x00, 0x00), /* 0x3f: */ ISPOPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ ISPOPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ - ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNTS */ - ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */ + ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNT */ + ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_OFFLINE_MODE */ ISPOPMAP(0x00, 0x00), /* 0x44: */ ISPOPMAP(0x00, 0x00), /* 0x45: */ ISPOPMAP(0x00, 0x00), /* 0x46: */ @@ -5319,7 +6381,7 @@ static const uint32_t mbpfc[] = { ISPOPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */ ISPOPMAP(0x00, 0x00), /* 0x5e: */ ISPOPMAP(0x00, 0x00), /* 0x5f: */ - ISPOPMAP(0xcd, 0x31), /* 0x60: MBOX_INIT_FIRMWARE */ + ISPOPMAP(0xcd, 0x01), /* 0x60: MBOX_INIT_FIRMWARE */ ISPOPMAP(0x00, 0x00), /* 0x61: */ ISPOPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ ISPOPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ @@ -5360,7 +6422,6 @@ static const uint32_t mbpfc[] = { * is that we won't overflow. */ -#ifndef ISP_STRIPPED static char *fc_mbcmd_names[] = { "NO-OP", "LOAD RAM", @@ -5428,7 +6489,7 @@ static char *fc_mbcmd_names[] = { NULL, "LOOP PORT BYPASS", "LOOP PORT ENABLE", - "GET RESOURCE COUNTS", + "GET RESOURCE COUNT", "REQUEST NON PARTICIPATING MODE", NULL, NULL, @@ -5490,7 +6551,6 @@ static char *fc_mbcmd_names[] = { "SEND LFA", "Lun RESET" }; -#endif static void isp_mboxcmd_qnw(ispsoftc_t *isp, mbreg_t *mbp, int nodelay) @@ -5521,19 +6581,23 @@ isp_mboxcmd_qnw(ispsoftc_t *isp, mbreg_t *mbp, int nodelay) isp->isp_obits = obits; isp->isp_mboxbsy = 1; } - ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + } /* * Oddly enough, if we're not delaying for an answer, * delay a bit to give the f/w a chance to pick up the * command. */ if (nodelay) { - USEC_DELAY(100); + USEC_DELAY(1000); } } static void -isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask) +isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp) { char *cname, *xname, tname[16], mname[16]; unsigned int lim, ibits, obits, box, opcode; @@ -5571,11 +6635,14 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask) /* * Get exclusive usage of mailbox registers. */ - MBOX_ACQUIRE(isp); + if (MBOX_ACQUIRE(isp)) { + mbp->param[0] = MBOX_REGS_BUSY; + goto out; + } for (box = 0; box < MAX_MAILBOX(isp); box++) { if (ibits & (1 << box)) { - isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%x", box, + isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%04x", box, mbp->param[box]); ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } @@ -5593,20 +6660,23 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask) /* * Set Host Interrupt condition so that RISC will pick up mailbox regs. */ - ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + } /* * While we haven't finished the command, spin our wheels here. */ - MBOX_WAIT_COMPLETE(isp); + MBOX_WAIT_COMPLETE(isp, mbp); /* * Did the command time out? */ - if (isp->isp_mboxbsy) { - isp->isp_mboxbsy = 0; + if (mbp->param[0] == MBOX_TIMEOUT) { MBOX_RELEASE(isp); - return; + goto out; } /* @@ -5615,21 +6685,18 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask) for (box = 0; box < MAX_MAILBOX(isp); box++) { if (obits & (1 << box)) { mbp->param[box] = isp->isp_mboxtmp[box]; - isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%x", box, + isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%04x", box, mbp->param[box]); } } MBOX_RELEASE(isp); - - if (logmask == 0 || opcode == MBOX_EXEC_FIRMWARE) { + out: + isp->isp_mboxbsy = 0; + if (mbp->logval == 0 || opcode == MBOX_EXEC_FIRMWARE) { return; } -#ifdef ISP_STRIPPED - cname = NULL; -#else cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode]; -#endif if (cname == NULL) { cname = tname; SNPRINTF(tname, sizeof tname, "opcode %x", opcode); @@ -5643,46 +6710,49 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask) case MBOX_COMMAND_COMPLETE: break; case MBOX_INVALID_COMMAND: - if (logmask & MBLOGMASK(MBOX_COMMAND_COMPLETE)) { + if (mbp->logval & MBLOGMASK(MBOX_COMMAND_COMPLETE)) { xname = "INVALID COMMAND"; } break; case MBOX_HOST_INTERFACE_ERROR: - if (logmask & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) { + if (mbp->logval & MBLOGMASK(MBOX_HOST_INTERFACE_ERROR)) { xname = "HOST INTERFACE ERROR"; } break; case MBOX_TEST_FAILED: - if (logmask & MBLOGMASK(MBOX_TEST_FAILED)) { + if (mbp->logval & MBLOGMASK(MBOX_TEST_FAILED)) { xname = "TEST FAILED"; } break; case MBOX_COMMAND_ERROR: - if (logmask & MBLOGMASK(MBOX_COMMAND_ERROR)) { + if (mbp->logval & MBLOGMASK(MBOX_COMMAND_ERROR)) { xname = "COMMAND ERROR"; } break; case MBOX_COMMAND_PARAM_ERROR: - if (logmask & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) { + if (mbp->logval & MBLOGMASK(MBOX_COMMAND_PARAM_ERROR)) { xname = "COMMAND PARAMETER ERROR"; } break; case MBOX_LOOP_ID_USED: - if (logmask & MBLOGMASK(MBOX_LOOP_ID_USED)) { + if (mbp->logval & MBLOGMASK(MBOX_LOOP_ID_USED)) { xname = "LOOP ID ALREADY IN USE"; } break; case MBOX_PORT_ID_USED: - if (logmask & MBLOGMASK(MBOX_PORT_ID_USED)) { + if (mbp->logval & MBLOGMASK(MBOX_PORT_ID_USED)) { xname = "PORT ID ALREADY IN USE"; } break; case MBOX_ALL_IDS_USED: - if (logmask & MBLOGMASK(MBOX_ALL_IDS_USED)) { + if (mbp->logval & MBLOGMASK(MBOX_ALL_IDS_USED)) { xname = "ALL LOOP IDS IN USE"; } break; - case 0: /* special case */ + case MBOX_REGS_BUSY: + xname = "REGISTERS BUSY"; + break; + case MBOX_TIMEOUT: xname = "TIMEOUT"; break; default: @@ -5705,7 +6775,9 @@ isp_fw_state(ispsoftc_t *isp) MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_FW_STATE; - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + mbs.timeout = 100000; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { fcp->isp_fwstate = mbs.param[1]; } @@ -5767,17 +6839,16 @@ isp_update_bus(ispsoftc_t *isp, int bus) */ if (sdp->isp_devparam[tgt].dev_refresh) { mbs.param[0] = MBOX_GET_TARGET_PARAMS; - sdp->isp_devparam[tgt].dev_refresh = 0; get = 1; } else if (sdp->isp_devparam[tgt].dev_update) { mbs.param[0] = MBOX_SET_TARGET_PARAMS; + /* * Make sure goal_flags has "Renegotiate on Error" * on and "Freeze Queue on Error" off. */ sdp->isp_devparam[tgt].goal_flags |= DPARM_RENEG; sdp->isp_devparam[tgt].goal_flags &= ~DPARM_QFRZ; - mbs.param[2] = sdp->isp_devparam[tgt].goal_flags; /* @@ -5811,26 +6882,31 @@ isp_update_bus(ispsoftc_t *isp, int bus) "bus %d set tgt %d flags 0x%x off 0x%x period 0x%x", bus, tgt, mbs.param[2], mbs.param[3] >> 8, mbs.param[3] & 0xff); - sdp->isp_devparam[tgt].dev_update = 0; - sdp->isp_devparam[tgt].dev_refresh = 1; get = 0; } else { continue; } mbs.param[1] = (bus << 15) | (tgt << 8); - isp_mboxcmd(isp, &mbs, MBLOGALL); + mbs.logval = MBLOGALL; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + continue; + } if (get == 0) { isp->isp_sendmarker |= (1 << bus); - continue; + sdp->isp_devparam[tgt].dev_update = 0; + sdp->isp_devparam[tgt].dev_refresh = 1; + } else { + sdp->isp_devparam[tgt].dev_refresh = 0; + flags = mbs.param[2]; + period = mbs.param[3] & 0xff; + offset = mbs.param[3] >> 8; + sdp->isp_devparam[tgt].actv_flags = flags; + sdp->isp_devparam[tgt].actv_period = period; + sdp->isp_devparam[tgt].actv_offset = offset; + get = (bus << 16) | tgt; + (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get); } - flags = mbs.param[2]; - period = mbs.param[3] & 0xff; - offset = mbs.param[3] >> 8; - sdp->isp_devparam[tgt].actv_flags = flags; - sdp->isp_devparam[tgt].actv_period = period; - sdp->isp_devparam[tgt].actv_offset = offset; - get = (bus << 16) | tgt; - (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get); } for (tgt = 0; tgt < MAX_TARGETS; tgt++) { @@ -5921,7 +6997,7 @@ isp_setdfltparm(ispsoftc_t *isp, int channel) ISP_NODEWWN(isp) = fcp->isp_nodewwn; if (fcp->isp_nodewwn == 0) { isp_prt(isp, ISP_LOGCONFIG, - "bad WWNN- using default\n"); + "bad WWNN- using default"); ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp); } } @@ -5938,7 +7014,7 @@ isp_setdfltparm(ispsoftc_t *isp, int channel) ISP_PORTWWN(isp) = fcp->isp_portwwn; if (fcp->isp_portwwn == 0) { isp_prt(isp, ISP_LOGCONFIG, - "bad WWPN- using default\n"); + "bad WWPN- using default"); ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp); } } @@ -6005,7 +7081,8 @@ isp_setdfltparm(ispsoftc_t *isp, int channel) MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_GET_ACT_NEG_STATE; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + mbs.logval = MBLOGNONE; + isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { sdp->isp_req_ack_active_neg = 1; sdp->isp_data_line_active_neg = 1; @@ -6082,18 +7159,16 @@ isp_setdfltparm(ispsoftc_t *isp, int channel) * Re-initialize the ISP and complete all orphaned commands * with a 'botched' notice. The reset/init routines should * not disturb an already active list of commands. - * - * Locks held prior to coming here. */ void isp_reinit(ispsoftc_t *isp) { XS_T *xs; - int i; + uint32_t tmp; if (IS_FC(isp)) { - isp_mark_getpdb_all(isp); + isp_mark_portdb(isp, 0); } isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { @@ -6106,17 +7181,36 @@ isp_reinit(ispsoftc_t *isp) if (isp->isp_state != ISP_RUNSTATE) { isp_prt(isp, ISP_LOGERR, "isp_reinit cannot restart card"); + ISP_DISABLE_INTS(isp); } - } + } else { + ISP_DISABLE_INTS(isp); + if (IS_FC(isp)) { + /* + * If we're in ISP_ROLE_NONE, turn off the lasers. + */ + if (!IS_24XX(isp)) { + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); + ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); + ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + } + } + } isp->isp_nactive = 0; - for (i = 0; i < isp->isp_maxcmds; i++) { - uint16_t handle; - xs = isp->isp_xflist[i]; + for (tmp = 0; tmp < isp->isp_maxcmds; tmp++) { + uint32_t handle; + + xs = isp->isp_xflist[tmp]; if (xs == NULL) { continue; } - handle = isp_index_handle(i); + handle = isp_find_handle(isp, xs); + if (handle == 0) { + continue; + } isp_destroy_handle(isp, handle); if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, handle); @@ -6127,6 +7221,9 @@ isp_reinit(ispsoftc_t *isp) XS_SETERR(xs, HBA_BUSRESET); isp_done(xs); } +#ifdef ISP_TARGET_MODE + MEMZERO(isp->isp_tgtlist, isp->isp_maxcmds * sizeof (void **)); +#endif } /* @@ -6144,7 +7241,9 @@ isp_read_nvram(ispsoftc_t *isp) #define nvram_data _n._x #define nvram_words _n._s - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + return (isp_read_nvram_2400(isp)); + } else if (IS_FC(isp)) { amt = ISP2100_NVRAM_SIZE; minversion = 1; } else if (IS_ULTRA2(isp)) { @@ -6155,13 +7254,10 @@ isp_read_nvram(ispsoftc_t *isp) minversion = 2; } - /* - * Just read the first two words first to see if we have a valid - * NVRAM to continue reading the rest with. - */ - for (i = 0; i < 2; i++) { + for (i = 0; i < amt>>1; i++) { isp_rdnvram_word(isp, i, &nvram_words[i]); } + if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || nvram_data[2] != 'P') { if (isp->isp_bustype != ISP_BT_SBUS) { @@ -6172,9 +7268,7 @@ isp_read_nvram(ispsoftc_t *isp) retval = -1; goto out; } - for (i = 2; i < amt>>1; i++) { - isp_rdnvram_word(isp, i, &nvram_words[i]); - } + for (csum = 0, i = 0; i < amt; i++) { csum += nvram_data[i]; } @@ -6183,6 +7277,7 @@ isp_read_nvram(ispsoftc_t *isp) retval = -1; goto out; } + if (ISP_NVRAM_VERSION(nvram_data) < minversion) { isp_prt(isp, ISP_LOGWARN, "version %d NVRAM not understood", ISP_NVRAM_VERSION(nvram_data)); @@ -6211,6 +7306,43 @@ out: #undef nvram_words } +static int +isp_read_nvram_2400(ispsoftc_t *isp) +{ + uint8_t *nvram_data = FCPARAM(isp)->isp_scratch; + int retval = 0; + uint32_t addr, csum, lwrds, *dptr; + + if (isp->isp_port) { + addr = ISP2400_NVRAM_PORT1_ADDR; + } else { + addr = ISP2400_NVRAM_PORT0_ADDR; + } + + dptr = (uint32_t *) nvram_data; + for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { + isp_rd_2400_nvram(isp, addr++, dptr++); + } + if (nvram_data[0] != 'I' || nvram_data[1] != 'S' || + nvram_data[2] != 'P') { + isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header"); + retval = -1; + goto out; + } + dptr = (uint32_t *) nvram_data; + for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) { + csum += dptr[lwrds]; + } + if (csum != 0) { + isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum"); + retval = -1; + goto out; + } + isp_parse_nvram_2400(isp, nvram_data); +out: + return (retval); +} + static void isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp) { @@ -6283,6 +7415,29 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp) } static void +isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp) +{ + int loops = 0; + const uint32_t base = 0x7ffe0000; + uint32_t tmp; + + ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr); + for (loops = 0; loops < 5000; loops++) { + USEC_DELAY(10); + tmp = ISP_READ(isp, BIU2400_FLASH_ADDR); + if ((tmp & (1 << 31)) != 0) { + break; + } + } + if (tmp & (1 << 31)) { + tmp = ISP_READ(isp, BIU2400_FLASH_DATA); + *rp = tmp; + } else { + *rp = 0xffffffff; + } +} + +static void isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data) { sdparam *sdp = (sdparam *) isp->isp_param; @@ -6592,9 +7747,41 @@ isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data) } static void +isp_fix_nvram_wwns(ispsoftc_t *isp) +{ + fcparam *fcp = FCPARAM(isp); + + /* + * Make sure we have both Node and Port as non-zero values. + */ + if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) { + fcp->isp_portwwn = fcp->isp_nodewwn; + } else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) { + fcp->isp_nodewwn = fcp->isp_portwwn; + } + + /* + * Make the Node and Port values sane if they're NAA == 2. + * This means to clear bits 48..56 for the Node WWN and + * make sure that there's some non-zero value in 48..56 + * for the Port WWN. + */ + if (fcp->isp_nodewwn && fcp->isp_portwwn) { + if ((fcp->isp_nodewwn & (((uint64_t) 0xfff) << 48)) != 0 && + (fcp->isp_nodewwn >> 60) == 2) { + fcp->isp_nodewwn &= ~((uint64_t) 0xfff << 48); + } + if ((fcp->isp_portwwn & (((uint64_t) 0xfff) << 48)) == 0 && + (fcp->isp_portwwn >> 60) == 2) { + fcp->isp_portwwn |= ((uint64_t) 1 << 56); + } + } +} + +static void isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data) { - fcparam *fcp = (fcparam *) isp->isp_param; + fcparam *fcp = FCPARAM(isp); uint64_t wwn; /* @@ -6632,47 +7819,21 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data) } fcp->isp_nodewwn = wwn; - /* - * Make sure we have both Node and Port as non-zero values. - */ - if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) { - fcp->isp_portwwn = fcp->isp_nodewwn; - } else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) { - fcp->isp_nodewwn = fcp->isp_portwwn; - } + isp_fix_nvram_wwns(isp); - /* - * Make the Node and Port values sane if they're NAA == 2. - * This means to clear bits 48..56 for the Node WWN and - * make sure that there's some non-zero value in 48..56 - * for the Port WWN. - */ - if (fcp->isp_nodewwn && fcp->isp_portwwn) { - if ((fcp->isp_nodewwn & (((uint64_t) 0xfff) << 48)) != 0 && - (fcp->isp_nodewwn >> 60) == 2) { - fcp->isp_nodewwn &= ~((uint64_t) 0xfff << 48); - } - if ((fcp->isp_portwwn & (((uint64_t) 0xfff) << 48)) == 0 && - (fcp->isp_portwwn >> 60) == 2) { - fcp->isp_portwwn |= ((uint64_t) 1 << 56); - } + fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { + fcp->isp_maxfrmlen = ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data); } - - fcp->isp_maxalloc = - ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); - if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) - fcp->isp_maxfrmlen = - ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data); - fcp->isp_retry_delay = - ISP2100_NVRAM_RETRY_DELAY(nvram_data); - fcp->isp_retry_count = - ISP2100_NVRAM_RETRY_COUNT(nvram_data); - if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) - fcp->isp_loopid = - ISP2100_NVRAM_HARDLOOPID(nvram_data); - if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) + fcp->isp_retry_delay = ISP2100_NVRAM_RETRY_DELAY(nvram_data); + fcp->isp_retry_count = ISP2100_NVRAM_RETRY_COUNT(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { + fcp->isp_loopid = ISP2100_NVRAM_HARDLOOPID(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) { fcp->isp_execthrottle = ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data); + } fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data); isp_prt(isp, ISP_LOGDEBUG0, "NVRAM 0x%08x%08x 0x%08x%08x maxalloc %d maxframelen %d", @@ -6693,6 +7854,64 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data) ISP2100_XFW_OPTIONS(nvram_data), ISP2100_ZFW_OPTIONS(nvram_data)); } +static void +isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data) +{ + fcparam *fcp = FCPARAM(isp); + uint64_t wwn; + + isp_prt(isp, ISP_LOGDEBUG0, + "NVRAM 0x%08x%08x 0x%08x%08x exchg_cnt %d maxframelen %d", + (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32), + (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)), + (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32), + (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)), + ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data), + ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data)); + isp_prt(isp, ISP_LOGDEBUG0, + "NVRAM execthr %d loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", + ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data), + ISP2400_NVRAM_HARDLOOPID(nvram_data), + ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data), + ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data), + ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data)); + + wwn = ISP2400_NVRAM_PORT_NAME(nvram_data); + if (wwn) { + if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { + wwn = 0; + } + } + fcp->isp_portwwn = wwn; + + wwn = ISP2400_NVRAM_NODE_NAME(nvram_data); + if (wwn) { + if ((wwn >> 60) != 2 && (wwn >> 60) != 5) { + wwn = 0; + } + } + fcp->isp_nodewwn = wwn; + + isp_fix_nvram_wwns(isp); + + if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) { + fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) { + fcp->isp_maxfrmlen = ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) { + fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data); + } + if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) { + fcp->isp_execthrottle = + ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data); + } + fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data); + fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data); + fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data); +} + #ifdef ISP_FW_CRASH_DUMP static void isp2200_fw_dump(ispsoftc_t *); static void isp2300_fw_dump(ispsoftc_t *); @@ -6823,7 +8042,7 @@ isp2200_fw_dump(ispsoftc_t *isp) break; } } - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); mbs.param[0] = MBOX_READ_RAM_WORD; mbs.param[1] = 0x1000; isp->isp_mbxworkp = (void *) ptr; @@ -6966,7 +8185,7 @@ isp2300_fw_dump(ispsoftc_t *isp) isp_prt(isp, ISP_LOGERR, "Board Would Not Reset"); return; } - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); MEMZERO(&mbs, sizeof (mbs)); mbs.param[0] = MBOX_READ_RAM_WORD; mbs.param[1] = 0x800; @@ -7008,5 +8227,8 @@ isp_fw_dump(ispsoftc_t *isp) isp2200_fw_dump(isp); else if (IS_23XX(isp)) isp2300_fw_dump(isp); + else if (IS_24XX(isp)) + isp_prt(isp, ISP_LOGERR, "24XX dump method undefined"); + } #endif diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 5e1d8ce..2750969 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$"); MODULE_VERSION(isp, 1); MODULE_DEPEND(isp, cam, 1, 1, 1); int isp_announced = 0; +int isp_fabric_hysteresis = 5; +int isp_loop_down_limit = 300; /* default loop down limit */ +int isp_quickboot_time = 5; /* don't wait more than N secs for loop up */ static d_ioctl_t ispioctl; static void isp_intr_enable(void *); @@ -242,7 +245,7 @@ isp_attach(ispsoftc_t *isp) if (isp->isp_role != ISP_ROLE_NONE) { isp->isp_state = ISP_RUNSTATE; - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); } if (isplist == NULL) { isplist = isp; @@ -387,7 +390,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td) case ISP_FC_GETDINFO: { struct isp_fc_device *ifc = (struct isp_fc_device *) addr; - struct lportdb *lp; + fcportdb_t *lp; if (IS_SCSI(isp)) { break; @@ -398,9 +401,9 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td) } ISP_LOCK(isp); lp = &FCPARAM(isp)->portdb[ifc->loopid]; - if (lp->valid) { + if (lp->state == FC_PORTDB_STATE_VALID) { ifc->role = lp->roles; - ifc->loopid = lp->loopid; + ifc->loopid = lp->handle; ifc->portid = lp->portid; ifc->node_wwn = lp->node_wwn; ifc->port_wwn = lp->port_wwn; @@ -566,7 +569,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td) memset(&mbs, 0, sizeof (mbs)); needmarker = retval = 0; loopid = fct->loopid; - if (IS_2KLOGIN(isp) == 0) { + if (FCPARAM(isp)->isp_2klogin == 0) { loopid <<= 8; } switch (fct->action) { @@ -657,10 +660,7 @@ isp_intr_enable(void *arg) { ispsoftc_t *isp = arg; if (isp->isp_role != ISP_ROLE_NONE) { - ENABLE_INTS(isp); -#if 0 - isp->isp_osinfo.intsok = 1; -#endif + ISP_ENABLE_INTS(isp); } /* Release our hook so that the boot can continue. */ config_intrhook_disestablish(&isp->isp_osinfo.ehook); @@ -911,7 +911,7 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb) /* * This is as a good a place as any to check f/w capabilities. */ - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) == 0) { + if (FCPARAM(isp)->isp_tmode == 0) { isp_prt(isp, ISP_LOGERR, "firmware does not support target mode"); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; @@ -921,9 +921,8 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb) * XXX: We *could* handle non-SCCLUN f/w, but we'd have to * XXX: dorks with our already fragile enable/disable code. */ - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { - isp_prt(isp, ISP_LOGERR, - "firmware not SCCLUN capable"); + if (FCPARAM(isp)->isp_sccfw == 0) { + isp_prt(isp, ISP_LOGERR, "firmware not SCCLUN capable"); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; return (-1); } @@ -1280,8 +1279,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) { void *qe; struct ccb_scsiio *cso = &ccb->csio; - uint16_t *hp, save_handle; - uint16_t nxti, optr; + uint32_t nxti, optr, handle; uint8_t local[QENTRY_LEN]; @@ -1303,11 +1301,11 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { ((ct2e_entry_t *)cto)->ct_iid = cso->init_id; } else { cto->ct_iid = cso->init_id; - if (!(FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)) { + if (FCPARAM(isp)->isp_sccfw == 0) { cto->ct_lun = ccb->ccb_h.target_lun; } } @@ -1386,7 +1384,6 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) atp->state = ATPD_STATE_CTIO; } cto->ct_timeout = 10; - hp = &cto->ct_syshandle; } else { ct_entry_t *cto = (ct_entry_t *) local; @@ -1422,10 +1419,9 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) } ccb->ccb_h.flags &= ~CAM_SEND_SENSE; cto->ct_timeout = 10; - hp = &cto->ct_syshandle; } - if (isp_save_xs_tgt(isp, ccb, hp)) { + if (isp_save_xs_tgt(isp, ccb, &handle)) { xpt_print_path(ccb->ccb_h.path); printf("No XFLIST pointers for isp_target_start_ctio\n"); XS_SETERR(ccb, CAM_REQUEUE_REQ); @@ -1442,7 +1438,13 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) * format. */ - save_handle = *hp; + if (IS_FC(isp)) { + ct2_entry_t *cto = (ct2_entry_t *) local; + cto->ct_syshandle = handle; + } else { + ct_entry_t *cto = (ct_entry_t *) local; + cto->ct_syshandle = handle; + } switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) { case CMD_QUEUED: @@ -1457,7 +1459,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) default: break; } - isp_destroy_tgt_handle(isp, save_handle); + isp_destroy_tgt_handle(isp, handle); out: ISPLOCK_2_CAMLOCK(isp); @@ -1478,7 +1480,7 @@ isp_target_putback_atio(union ccb *ccb) { ispsoftc_t *isp; struct ccb_scsiio *cso; - uint16_t nxti, optr; + uint32_t nxti, optr; void *qe; isp = XS_ISP(ccb); @@ -1496,7 +1498,7 @@ isp_target_putback_atio(union ccb *ccb) MEMZERO(at, sizeof (at2_entry_t)); at->at_header.rqs_entry_type = RQSTYPE_ATIO2; at->at_header.rqs_entry_count = 1; - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) { + if (FCPARAM(isp)->isp_sccfw) { at->at_scclun = (uint16_t) ccb->ccb_h.target_lun; } else { at->at_lun = (uint8_t) ccb->ccb_h.target_lun; @@ -1685,7 +1687,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) return (0); } - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) { + if (FCPARAM(isp)->isp_sccfw) { lun = aep->at_scclun; } else { lun = aep->at_lun; @@ -1731,8 +1733,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) lun, tptr->atio_count); if (tptr == &isp->isp_osinfo.tsdflt[0]) { - atiop->ccb_h.target_id = - ((fcparam *)isp->isp_param)->isp_loopid; + atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid; atiop->ccb_h.target_lun = lun; } /* @@ -2004,7 +2005,8 @@ static void isp_poll(struct cam_sim *sim) { ispsoftc_t *isp = cam_sim_softc(sim); - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; ISP_LOCK(isp); if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { @@ -2020,7 +2022,6 @@ isp_watchdog(void *arg) XS_T *xs = arg; ispsoftc_t *isp = XS_ISP(xs); uint32_t handle; - int iok; /* * We've decided this command is dead. Make sure we're not trying @@ -2028,11 +2029,10 @@ isp_watchdog(void *arg) * and seeing whether it's still alive. */ ISP_LOCK(isp); - iok = isp->isp_osinfo.intsok; - isp->isp_osinfo.intsok = 0; handle = isp_find_handle(isp, xs); if (handle) { - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; if (XS_CMD_DONE_P(xs)) { isp_prt(isp, ISP_LOGDEBUG1, @@ -2077,28 +2077,14 @@ isp_watchdog(void *arg) XS_CMD_C_WDOG(xs); isp_done(xs); } else { - uint16_t nxti, optr; - ispreq_t local, *mp= &local, *qe; - XS_CMD_C_WDOG(xs); xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz); - if (isp_getrqentry(isp, &nxti, &optr, (void **) &qe)) { - ISP_UNLOCK(isp); - return; - } XS_CMD_S_GRACE(xs); - MEMZERO((void *) mp, sizeof (*mp)); - mp->req_header.rqs_entry_count = 1; - mp->req_header.rqs_entry_type = RQSTYPE_MARKER; - mp->req_modifier = SYNC_ALL; - mp->req_target = XS_CHANNEL(xs) << 7; - isp_put_request(isp, mp, qe); - ISP_ADD_REQUEST(isp, nxti); + isp->isp_sendmarker |= 1 << XS_CHANNEL(xs); } } else { isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command"); } - isp->isp_osinfo.intsok = iok; ISP_UNLOCK(isp); } @@ -2106,13 +2092,13 @@ static void isp_kthread(void *arg) { ispsoftc_t *isp = arg; + int slp; #if __FreeBSD_version < 500000 int s; s = splcam(); - isp->isp_osinfo.intsok = 1; #else #ifdef ISP_SMPLOCK mtx_lock(&isp->isp_lock); @@ -2125,32 +2111,63 @@ isp_kthread(void *arg) * gotten good fibre channel state. */ for (;;) { - int wasfrozen; + int wasfrozen, lb; isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state"); - while (isp_fc_runstate(isp, 2 * 1000000) != 0) { - isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state ungood"); - if (FCPARAM(isp)->isp_fwstate != FW_READY || - FCPARAM(isp)->isp_loopstate < LOOP_PDB_RCVD) { - if (FCPARAM(isp)->loop_seen_once == 0 || - isp->isp_osinfo.ktmature == 0) { - break; - } + lb = isp_fc_runstate(isp, 250000); + if (lb) { + unsigned int inc = 1; + + if (lb < 0) { + isp_prt(isp, ISP_LOGDEBUG0, + "kthread: FC loop not up (down count %d)", + isp->isp_osinfo.loop_down_time); + } else { + isp_prt(isp, ISP_LOGDEBUG0, + "kthread: FC got to %d (down count %d)", + lb, isp->isp_osinfo.loop_down_time); } -#ifdef ISP_SMPLOCK - msleep(isp_kthread, &isp->isp_lock, - PRIBIO, "isp_fcthrd", hz); -#else - (void) tsleep(isp_kthread, PRIBIO, "isp_fcthrd", hz); -#endif + + + /* + * If we've never seen loop up and we've waited longer + * than quickboot time, give up and go to sleep until + * loop comes up. Otherwise, increment the loop down + * time and figure out how long to sleep to the next + * check. + */ + if (FCPARAM(isp)->loop_seen_once == 0 && + isp->isp_osinfo.loop_down_time >= + isp_quickboot_time) { + isp->isp_osinfo.loop_down_time = 0xffff; + slp = 0; + } else if (isp->isp_osinfo.loop_down_time > 30) { + inc = 30; + slp = 30 * hz; + } else if (isp->isp_osinfo.loop_down_time > 1) { + slp = hz; + } else { + slp = 1; + } + + inc += isp->isp_osinfo.loop_down_time; + if (inc < 0xffff) { + isp->isp_osinfo.loop_down_time = inc; + } else { + isp->isp_osinfo.loop_down_time = 0xfffe; + } + } else { + isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state OK"); + isp->isp_osinfo.loop_down_time = 0; + slp = 0; } /* - * Even if we didn't get good loop state we may be - * unfreezing the SIMQ so that we can kill off - * commands (if we've never seen loop before, for example). + * If we'd frozen the simq, unfreeze it now so that CAM + * can start sending us commands. If the FC state isn't + * okay yet, they'll hit that in isp_start which will + * freeze the queue again. */ - isp->isp_osinfo.ktmature = 1; wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { @@ -2159,16 +2176,26 @@ isp_kthread(void *arg) xpt_release_simq(isp->isp_sim, 1); CAMLOCK_2_ISPLOCK(isp); } - isp_prt(isp, ISP_LOGDEBUG0, "kthread: waiting until called"); #if __FreeBSD_version < 500000 - tsleep(&isp->isp_osinfo.kproc, PRIBIO, "isp_fc_worker", 0); + tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp); #else #ifdef ISP_SMPLOCK - cv_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock); + cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock, slp); #else - (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "fc_cv", 0); + (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf", slp); #endif #endif + /* + * If slp is zero, we're waking up for the first time after + * things have been okay. In this case, we set a deferral state + * for all commands and delay hysteresis seconds before starting + * the FC state evaluation. This gives the loop/fabric a chance + * to settle. + */ + if (slp == 0 && isp->isp_osinfo.hysteresis) { + (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT", + (isp->isp_osinfo.hysteresis * hz)); + } } } @@ -2260,8 +2287,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb) * This can only happen for Fibre Channel */ KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only")); - if (FCPARAM(isp)->loop_seen_once == 0 && - isp->isp_osinfo.ktmature) { + /* + * If we've exceeded the loop down limit start + * failing commands. + */ + if (isp->isp_osinfo.loop_down_time > + isp->isp_osinfo.loop_down_limit) { ISPLOCK_2_CAMLOCK(isp); XS_SETERR(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); @@ -2303,25 +2334,22 @@ isp_action(struct cam_sim *sim, union ccb *ccb) #ifdef ISP_TARGET_MODE case XPT_EN_LUN: /* Enable LUN as a target */ { - int seq, iok, i; + int seq, i; CAMLOCK_2_ISPLOCK(isp); - iok = isp->isp_osinfo.intsok; - isp->isp_osinfo.intsok = 0; seq = isp_en_lun(isp, ccb); if (seq < 0) { - isp->isp_osinfo.intsok = iok; ISPLOCK_2_CAMLOCK(isp); xpt_done(ccb); break; } for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) { - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { isp_intr(isp, isr, sema, mbox); } DELAY(1000); } - isp->isp_osinfo.intsok = iok; ISPLOCK_2_CAMLOCK(isp); break; } @@ -2519,7 +2547,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) else fc->bitrate = 100000; if (tgt > 0 && tgt < MAX_FC_TARG) { - struct lportdb *lp = &fcp->portdb[tgt]; + fcportdb_t *lp = &fcp->portdb[tgt]; fc->wwnn = lp->node_wwn; fc->wwpn = lp->port_wwn; fc->port = lp->portid; @@ -2767,6 +2795,19 @@ int isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) { int bus, rv = 0; + static const char *roles[4] = { + "(none)", "Target", "Initiator", "Target/Initiator" + }; + static const char prom[] = + "PortID 0x%06x handle 0x%x role %s %s\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + static const char prom2[] = + "PortID 0x%06x handle 0x%x role %s %s tgt %u\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + target_id_t tgt; + fcportdb_t *lp; + struct cam_path *tmppath; + switch (cmd) { case ISPASYNC_NEW_TGT_PARAMS: { @@ -2775,7 +2816,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) int flags, tgt; sdparam *sdp = isp->isp_param; struct ccb_trans_settings cts; - struct cam_path *tmppath; memset(&cts, 0, sizeof (struct ccb_trans_settings)); @@ -2876,59 +2916,127 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) */ isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; - case ISPASYNC_PROMENADE: - { - const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x " - "(role %s) %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x"; - static const char *roles[4] = { - "(none)", "Target", "Initiator", "Target/Initiator" - }; - fcparam *fcp = isp->isp_param; - int tgt = *((int *) arg); + case ISPASYNC_DEV_ARRIVED: + lp = arg; + + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "arrived at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); #if __FreeBSD_version >= 500000 - int is_tgt_mask = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); - struct cam_path *tmppath; + ISPLOCK_2_CAMLOCK(isp); + if (xpt_create_path(&tmppath, NULL, + cam_sim_path(isp->isp_sim), tgt, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + CAMLOCK_2_ISPLOCK(isp); + break; + } + xpt_async(AC_FOUND_DEVICE, tmppath, NULL); + xpt_free_path(tmppath); + CAMLOCK_2_ISPLOCK(isp); #endif - struct lportdb *lp = &fcp->portdb[tgt]; - - isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid, - roles[lp->roles & 0x3], - (lp->valid)? "Arrived" : "Departed", - (uint32_t) (lp->port_wwn >> 32), - (uint32_t) (lp->port_wwn & 0xffffffffLL), - (uint32_t) (lp->node_wwn >> 32), - (uint32_t) (lp->node_wwn & 0xffffffffLL)); - - ISPLOCK_2_CAMLOCK(isp); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "arrived", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } + break; + case ISPASYNC_DEV_CHANGED: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "changed at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "changed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } + break; + case ISPASYNC_DEV_STAYED: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "stayed at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "stayed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } + break; + case ISPASYNC_DEV_GONE: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "departed from", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); #if __FreeBSD_version >= 500000 - if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), - (target_id_t)tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - CAMLOCK_2_ISPLOCK(isp); - break; - } - /* - * Policy: only announce targets. - */ - if (lp->roles & is_tgt_mask) { - if (lp->valid) { - xpt_async(AC_FOUND_DEVICE, tmppath, NULL); - } else { - xpt_async(AC_LOST_DEVICE, tmppath, NULL); + ISPLOCK_2_CAMLOCK(isp); + if (xpt_create_path(&tmppath, NULL, + cam_sim_path(isp->isp_sim), tgt, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + CAMLOCK_2_ISPLOCK(isp); + break; } - } - xpt_free_path(tmppath); + xpt_async(AC_LOST_DEVICE, tmppath, NULL); + xpt_free_path(tmppath); + CAMLOCK_2_ISPLOCK(isp); #endif - CAMLOCK_2_ISPLOCK(isp); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "departed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } break; - } case ISPASYNC_CHANGE_NOTIFY: + { + char *msg; if (arg == ISPASYNC_CHANGE_PDB) { - isp_prt(isp, ISP_LOGINFO, - "Port Database Changed"); + msg = "Port Database Changed"; } else if (arg == ISPASYNC_CHANGE_SNS) { - isp_prt(isp, ISP_LOGINFO, - "Name Server Database Changed"); + msg = "Name Server Database Changed"; + } else { + msg = "Other Change Notify"; } + isp_prt(isp, ISP_LOGINFO, msg); + isp_freeze_loopdown(isp, msg); #if __FreeBSD_version < 500000 wakeup(&isp->isp_osinfo.kproc); #else @@ -2939,117 +3047,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) #endif #endif break; - case ISPASYNC_FABRIC_DEV: - { - int target, base, lim; - fcparam *fcp = isp->isp_param; - struct lportdb *lp = NULL; - struct lportdb *clp = (struct lportdb *) arg; - char *pt; - - switch (clp->port_type) { - case 1: - pt = " N_Port"; - break; - case 2: - pt = " NL_Port"; - break; - case 3: - pt = "F/NL_Port"; - break; - case 0x7f: - pt = " Nx_Port"; - break; - case 0x81: - pt = " F_port"; - break; - case 0x82: - pt = " FL_Port"; - break; - case 0x84: - pt = " E_port"; - break; - default: - pt = " "; - break; - } - - isp_prt(isp, ISP_LOGINFO, - "%s Fabric Device @ PortID 0x%x", pt, clp->portid); - - /* - * If we don't have an initiator role we bail. - * - * We just use ISPASYNC_FABRIC_DEV for announcement purposes. - */ - - if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { - break; - } - - /* - * Is this entry for us? If so, we bail. - */ - - if (fcp->isp_portid == clp->portid) { - break; - } - - /* - * Else, the default policy is to find room for it in - * our local port database. Later, when we execute - * the call to isp_pdb_sync either this newly arrived - * or already logged in device will be (re)announced. - */ - - if (fcp->isp_topo == TOPO_FL_PORT) - base = FC_SNS_ID+1; - else - base = 0; - - if (fcp->isp_topo == TOPO_N_PORT) - lim = 1; - else - lim = MAX_FC_TARG; - - /* - * Is it already in our list? - */ - for (target = base; target < lim; target++) { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - continue; - } - lp = &fcp->portdb[target]; - if (lp->port_wwn == clp->port_wwn && - lp->node_wwn == clp->node_wwn) { - lp->fabric_dev = 1; - break; - } - } - if (target < lim) { - break; - } - for (target = base; target < lim; target++) { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - continue; - } - lp = &fcp->portdb[target]; - if (lp->port_wwn == 0) { - break; - } - } - if (target == lim) { - isp_prt(isp, ISP_LOGWARN, - "out of space for fabric devices"); - break; - } - lp->port_type = clp->port_type; - lp->fc4_type = clp->fc4_type; - lp->node_wwn = clp->node_wwn; - lp->port_wwn = clp->port_wwn; - lp->portid = clp->portid; - lp->fabric_dev = 1; - break; } #ifdef ISP_TARGET_MODE case ISPASYNC_TARGET_NOTIFY: @@ -3136,8 +3133,12 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) void isp_uninit(ispsoftc_t *isp) { - ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); - DISABLE_INTS(isp); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); + } + ISP_DISABLE_INTS(isp); } void diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 6b80137..2a96d5d 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -149,13 +149,16 @@ struct isposinfo { struct cam_sim *sim2; struct cam_path *path2; struct intr_config_hook ehook; - uint8_t + uint16_t loop_down_time; + uint16_t loop_down_limit; + uint32_t : 5, + simqfrozen : 3, + hysteresis : 8, + : 4, disabled : 1, fcbsy : 1, - ktmature : 1, - mboxwaiting : 1, - intsok : 1, - simqfrozen : 3; + mboxcmd_done : 1, + mboxbsy : 1; #if __FreeBSD_version >= 500000 struct firmware * fw; struct mtx lock; @@ -211,18 +214,13 @@ struct isposinfo { * Required Macros/Defines */ -#define ISP2100_SCRLEN 0x800 +#define ISP2100_SCRLEN 0x1000 #define MEMZERO(a, b) memset(a, 0, b) #define MEMCPY memcpy #define SNPRINTF snprintf #define USEC_DELAY DELAY -#define USEC_SLEEP(isp, x) \ - if (isp->isp_osinfo.intsok) \ - ISP_UNLOCK(isp); \ - DELAY(x); \ - if (isp->isp_osinfo.intsok) \ - ISP_LOCK(isp) +#define USEC_SLEEP(isp, x) DELAY(x) #define NANOTIME_T struct timespec #define GET_NANOTIME nanotime @@ -247,15 +245,10 @@ default: \ break; \ } -#define MBOX_ACQUIRE(isp) +#define MBOX_ACQUIRE isp_mbox_acquire #define MBOX_WAIT_COMPLETE isp_mbox_wait_complete -#define MBOX_NOTIFY_COMPLETE(isp) \ - if (isp->isp_osinfo.mboxwaiting) { \ - isp->isp_osinfo.mboxwaiting = 0; \ - wakeup(&isp->isp_mbxworkp); \ - } \ - isp->isp_mboxbsy = 0 -#define MBOX_RELEASE(isp) +#define MBOX_NOTIFY_COMPLETE(isp) isp->isp_osinfo.mboxcmd_done = 1 +#define MBOX_RELEASE isp_mbox_release #define FC_SCRATCH_ACQUIRE(isp) \ if (isp->isp_osinfo.fcbsy) { \ @@ -361,7 +354,8 @@ default: \ #define ISP_IOXGET_32(isp, s, d) \ d = (isp->isp_bustype == ISP_BT_SBUS)? \ *((uint32_t *)s) : bswap32(*((uint32_t *)s)) -#else + +#else /* ISP_SBUS_SUPPORTED */ #define ISP_IOXPUT_8(isp, s, d) *(d) = s #define ISP_IOXPUT_16(isp, s, d) *(d) = bswap16(s) #define ISP_IOXPUT_32(isp, s, d) *(d) = bswap32(s) @@ -370,6 +364,15 @@ default: \ #define ISP_IOXGET_32(isp, s, d) d = bswap32(*((uint32_t *)s)) #endif #define ISP_SWIZZLE_NVRAM_WORD(isp, rp) *rp = bswap16(*rp) + +#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)s)) +#define ISP_IOZGET_16(isp, s, d) d = (*((uint16_t *)s)) +#define ISP_IOZGET_32(isp, s, d) d = (*((uint32_t *)s)) +#define ISP_IOZPUT_8(isp, s, d) *(d) = s +#define ISP_IOZPUT_16(isp, s, d) *(d) = s +#define ISP_IOZPUT_32(isp, s, d) *(d) = s + + #else #define ISP_IOXPUT_8(isp, s, d) *(d) = s #define ISP_IOXPUT_16(isp, s, d) *(d) = s @@ -378,6 +381,15 @@ default: \ #define ISP_IOXGET_16(isp, s, d) d = *(s) #define ISP_IOXGET_32(isp, s, d) d = *(s) #define ISP_SWIZZLE_NVRAM_WORD(isp, rp) + +#define ISP_IOZPUT_8(isp, s, d) *(d) = s +#define ISP_IOZPUT_16(isp, s, d) *(d) = bswap16(s) +#define ISP_IOZPUT_32(isp, s, d) *(d) = bswap32(s) + +#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)(s))) +#define ISP_IOZGET_16(isp, s, d) d = bswap16(*((uint16_t *)(s))) +#define ISP_IOZGET_32(isp, s, d) d = bswap32(*((uint32_t *)(s))) + #endif /* @@ -417,6 +429,9 @@ extern void isp_uninit(ispsoftc_t *); * driver global data */ extern int isp_announced; +extern int isp_fabric_hysteresis; +extern int isp_loop_down_limit; +extern int isp_quickboot_time; /* * Platform private flags @@ -444,49 +459,61 @@ extern int isp_announced; * Platform specific inline functions */ -static __inline void isp_mbox_wait_complete(ispsoftc_t *); +static __inline int isp_mbox_acquire(ispsoftc_t *); +static __inline void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *); +static __inline void isp_mbox_release(ispsoftc_t *); + +static __inline int +isp_mbox_acquire(ispsoftc_t *isp) +{ + if (isp->isp_osinfo.mboxbsy) { + return (1); + } else { + isp->isp_osinfo.mboxcmd_done = 0; + isp->isp_osinfo.mboxbsy = 1; + return (0); + } +} + static __inline void -isp_mbox_wait_complete(ispsoftc_t *isp) +isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp) { - if (isp->isp_osinfo.intsok) { - int lim = ((isp->isp_mbxwrk0)? 120 : 20) * hz; - isp->isp_osinfo.mboxwaiting = 1; -#ifdef ISP_SMPLOCK - (void) msleep(&isp->isp_mbxworkp, - &isp->isp_lock, PRIBIO, "isp_mboxwaiting", lim); -#else - (void) tsleep(&isp->isp_mbxworkp, - PRIBIO, "isp_mboxwaiting", lim); -#endif - if (isp->isp_mboxbsy != 0) { - isp_prt(isp, ISP_LOGWARN, - "Interrupting Mailbox Command (0x%x) Timeout", - isp->isp_lastmbxcmd); - isp->isp_mboxbsy = 0; + int lim = mbp->timeout; + int j; + + if (lim == 0) { + lim = MBCMD_DEFAULT_TIMEOUT; + } + if (isp->isp_mbxwrk0) { + lim *= isp->isp_mbxwrk0; + } + for (j = 0; j < lim; j += 100) { + uint32_t isr; + uint16_t sema, mbox; + if (isp->isp_osinfo.mboxcmd_done) { + break; } - isp->isp_osinfo.mboxwaiting = 0; - } else { - int lim = ((isp->isp_mbxwrk0)? 240 : 60) * 10000; - int j; - for (j = 0; j < lim; j++) { - uint16_t isr, sema, mbox; - if (isp->isp_mboxbsy == 0) { + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + if (isp->isp_osinfo.mboxcmd_done) { break; } - if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { - isp_intr(isp, isr, sema, mbox); - if (isp->isp_mboxbsy == 0) { - break; - } - } - USEC_DELAY(500); - } - if (isp->isp_mboxbsy != 0) { - isp_prt(isp, ISP_LOGWARN, - "Polled Mailbox Command (0x%x) Timeout", - isp->isp_lastmbxcmd); } + USEC_DELAY(100); } + if (isp->isp_osinfo.mboxcmd_done == 0) { + isp_prt(isp, ISP_LOGWARN, + "Polled Mailbox Command (0x%x) Timeout", + isp->isp_lastmbxcmd); + mbp->param[0] = MBOX_TIMEOUT; + isp->isp_osinfo.mboxcmd_done = 1; + } +} + +static __inline void +isp_mbox_release(ispsoftc_t *isp) +{ + isp->isp_osinfo.mboxbsy = 0; } static __inline uint64_t nanotime_sub(struct timespec *, struct timespec *); diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index 298197f..072d726 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -46,11 +46,11 @@ __FBSDID("$FreeBSD$"); #endif int -isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint16_t *handlep) +isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep) { - int i, j; + uint16_t i, j; - for (j = isp->isp_lasthdls, i = 0; i < (int) isp->isp_maxcmds; i++) { + for (j = isp->isp_lasthdls, i = 0; i < isp->isp_maxcmds; i++) { if (isp->isp_xflist[j] == NULL) { break; } @@ -63,63 +63,58 @@ isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint16_t *handlep) } isp->isp_xflist[j] = xs; *handlep = j+1; - if (++j == isp->isp_maxcmds) + if (++j == isp->isp_maxcmds) { j = 0; - isp->isp_lasthdls = (uint16_t)j; + } + isp->isp_lasthdls = (uint32_t)j; return (0); } XS_T * -isp_find_xs(ispsoftc_t *isp, uint16_t handle) +isp_find_xs(ispsoftc_t *isp, uint32_t handle) { - if (handle < 1 || handle > (uint16_t) isp->isp_maxcmds) { + if (handle < 1 || handle > (uint32_t) isp->isp_maxcmds) { return (NULL); } else { return (isp->isp_xflist[handle - 1]); } } -uint16_t +uint32_t isp_find_handle(ispsoftc_t *isp, XS_T *xs) { - int i; + uint16_t i; if (xs != NULL) { for (i = 0; i < isp->isp_maxcmds; i++) { if (isp->isp_xflist[i] == xs) { - return ((uint16_t) i+1); + return ((uint32_t) (i+1)); } } } return (0); } -int -isp_handle_index(uint16_t handle) -{ - return (handle-1); -} - -uint16_t -isp_index_handle(int index) +uint32_t +isp_handle_index(uint32_t handle) { - return (index+1); + return (handle - 1); } void -isp_destroy_handle(ispsoftc_t *isp, uint16_t handle) +isp_destroy_handle(ispsoftc_t *isp, uint32_t handle) { - if (handle > 0 && handle <= (uint16_t) isp->isp_maxcmds) { + if (handle > 0 && handle <= (uint32_t) isp->isp_maxcmds) { isp->isp_xflist[handle - 1] = NULL; } } int -isp_getrqentry(ispsoftc_t *isp, uint16_t *iptrp, - uint16_t *optrp, void **resultp) +isp_getrqentry(ispsoftc_t *isp, uint32_t *iptrp, + uint32_t *optrp, void **resultp) { - volatile uint16_t iptr, optr; + volatile uint32_t iptr, optr; - optr = isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp); + optr = isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp); iptr = isp->isp_reqidx; *resultp = ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN(isp)); @@ -185,10 +180,6 @@ isp_print_bytes(ispsoftc_t *isp, char *msg, int amt, void *arg) * action because things may have changed while we were doing this. * Any failure or change of state causes us to return a nonzero value. * - * We honor HBA roles in that if we're not in Initiator mode, we don't - * attempt to sync up the database (that's for somebody else to do, - * if ever). - * * We assume we enter here with any locks held. */ @@ -198,34 +189,72 @@ isp_fc_runstate(ispsoftc_t *isp, int tval) fcparam *fcp; int *tptr; - if (IS_SCSI(isp)) + if (isp->isp_role == ISP_ROLE_NONE) { return (0); - - tptr = &tval; - if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) { - return (-1); } fcp = FCPARAM(isp); - if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) - return (-1); - if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) { - return (-1); - } - if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) { - return (-1); + tptr = &tval; + if (fcp->isp_fwstate < FW_READY || + fcp->isp_loopstate < LOOP_PDB_RCVD) { + if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) { + isp_prt(isp, ISP_LOGINFO, + "isp_fc_runstate: linktest failed"); + return (-1); + } + if (fcp->isp_fwstate != FW_READY || + fcp->isp_loopstate < LOOP_PDB_RCVD) { + isp_prt(isp, ISP_LOGINFO, + "isp_fc_runstate: f/w not ready"); + return (-1); + } } if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { return (0); } + if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) { + isp_prt(isp, ISP_LOGINFO, + "isp_fc_runstate: scan loop fails"); + return (LOOP_PDB_RCVD); + } + if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) { + isp_prt(isp, ISP_LOGINFO, + "isp_fc_runstate: scan fabric fails"); + return (LOOP_LSCAN_DONE); + } if (isp_control(isp, ISPCTL_PDB_SYNC, NULL) != 0) { - return (-1); + isp_prt(isp, ISP_LOGINFO, "isp_fc_runstate: pdb_sync fails"); + return (LOOP_FSCAN_DONE); } if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) { + isp_prt(isp, ISP_LOGINFO, + "isp_fc_runstate: f/w not ready again"); return (-1); } return (0); } +void +isp_shutdown(ispsoftc_t *isp) +{ + if (IS_FC(isp)) { + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_ICR, 0); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); + } else { + ISP_WRITE(isp, BIU_ICR, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); + ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); + ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + } + } else { + ISP_WRITE(isp, BIU_ICR, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + } +} + /* * Functions to move stuff to a form that the QLogic RISC engine understands * and functions to move stuff back to a form the processor understands. @@ -240,11 +269,12 @@ isp_fc_runstate(ispsoftc_t *isp, int tval) #define ISP_IS_SBUS(isp) \ (ISP_SBUS_SUPPORTED && (isp)->isp_bustype == ISP_BT_SBUS) +#define ASIZE(x) (sizeof (x) / sizeof (x[0])) /* * Swizzle/Copy Functions */ void -isp_copy_out_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst) +isp_put_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst) { if (ISP_IS_SBUS(isp)) { ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type, @@ -268,7 +298,7 @@ isp_copy_out_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst) } void -isp_copy_in_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst) +isp_get_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst) { if (ISP_IS_SBUS(isp)) { ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type, @@ -307,7 +337,7 @@ void isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst) { int i; - isp_copy_out_hdr(isp, &rqsrc->req_header, &rqdst->req_header); + isp_put_hdr(isp, &rqsrc->req_header, &rqdst->req_header); ISP_IOXPUT_32(isp, rqsrc->req_handle, &rqdst->req_handle); if (ISP_IS_SBUS(isp)) { ISP_IOXPUT_8(isp, rqsrc->req_lun_trn, &rqdst->req_target); @@ -320,7 +350,7 @@ isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst) ISP_IOXPUT_16(isp, rqsrc->req_flags, &rqdst->req_flags); ISP_IOXPUT_16(isp, rqsrc->req_time, &rqdst->req_time); ISP_IOXPUT_16(isp, rqsrc->req_seg_count, &rqdst->req_seg_count); - for (i = 0; i < 12; i++) { + for (i = 0; i < ASIZE(rqsrc->req_cdb); i++) { ISP_IOXPUT_8(isp, rqsrc->req_cdb[i], &rqdst->req_cdb[i]); } for (i = 0; i < ISP_RQDSEG; i++) { @@ -332,203 +362,340 @@ isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst) } void -isp_put_request_t2(ispsoftc_t *isp, ispreqt2_t *tqsrc, ispreqt2_t *tqdst) +isp_put_marker(ispsoftc_t *isp, isp_marker_t *src, isp_marker_t *dst) { int i; - isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); - ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); - ISP_IOXPUT_8(isp, tqsrc->req_lun_trn, &tqdst->req_lun_trn); - ISP_IOXPUT_8(isp, tqsrc->req_target, &tqdst->req_target); - ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); - ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); - ISP_IOXPUT_16(isp, tqsrc->_res2, &tqdst->_res2); - ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); - ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); - for (i = 0; i < 16; i++) { - ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header); + ISP_IOXPUT_32(isp, src->mrk_handle, &dst->mrk_handle); + if (ISP_IS_SBUS(isp)) { + ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_target); + ISP_IOXPUT_8(isp, src->mrk_target, &dst->mrk_reserved0); + } else { + ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_reserved0); + ISP_IOXPUT_8(isp, src->mrk_target, &dst->mrk_target); } - ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); - for (i = 0; i < ISP_RQDSEG_T2; i++) { - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, - &tqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, - &tqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_16(isp, src->mrk_modifier, &dst->mrk_modifier); + ISP_IOXPUT_16(isp, src->mrk_flags, &dst->mrk_flags); + ISP_IOXPUT_16(isp, src->mrk_lun, &dst->mrk_lun); + for (i = 0; i < ASIZE(src->mrk_reserved1); i++) { + ISP_IOXPUT_8(isp, src->mrk_reserved1[i], + &dst->mrk_reserved1[i]); } } void -isp_put_request_t2e(ispsoftc_t *isp, ispreqt2e_t *tqsrc, ispreqt2e_t *tqdst) +isp_put_marker_24xx(ispsoftc_t *isp, + isp_marker_24xx_t *src, isp_marker_24xx_t *dst) { int i; - isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); - ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); - ISP_IOXPUT_16(isp, tqsrc->req_target, &tqdst->req_target); - ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); - ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); - ISP_IOXPUT_16(isp, tqsrc->_res2, &tqdst->_res2); - ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); - ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); - for (i = 0; i < 16; i++) { - ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header); + ISP_IOXPUT_32(isp, src->mrk_handle, &dst->mrk_handle); + ISP_IOXPUT_16(isp, src->mrk_nphdl, &dst->mrk_nphdl); + ISP_IOXPUT_8(isp, src->mrk_modifier, &dst->mrk_modifier); + ISP_IOXPUT_8(isp, src->mrk_reserved0, &dst->mrk_reserved0); + ISP_IOXPUT_8(isp, src->mrk_reserved1, &dst->mrk_reserved1); + ISP_IOXPUT_8(isp, src->mrk_vphdl, &dst->mrk_vphdl); + ISP_IOXPUT_8(isp, src->mrk_reserved2, &dst->mrk_reserved2); + for (i = 0; i < ASIZE(src->mrk_lun); i++) { + ISP_IOXPUT_8(isp, src->mrk_lun[i], &dst->mrk_lun[i]); } - ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); + for (i = 0; i < ASIZE(src->mrk_reserved3); i++) { + ISP_IOXPUT_8(isp, src->mrk_reserved3[i], + &dst->mrk_reserved3[i]); + } +} + +void +isp_put_request_t2(ispsoftc_t *isp, ispreqt2_t *src, ispreqt2_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); for (i = 0; i < ISP_RQDSEG_T2; i++) { - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, - &tqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, - &tqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_request_t3(ispsoftc_t *isp, ispreqt3_t *tqsrc, ispreqt3_t *tqdst) +isp_put_request_t2e(ispsoftc_t *isp, ispreqt2e_t *src, ispreqt2e_t *dst) { int i; - isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); - ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); - ISP_IOXPUT_8(isp, tqsrc->req_lun_trn, &tqdst->req_lun_trn); - ISP_IOXPUT_8(isp, tqsrc->req_target, &tqdst->req_target); - ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); - ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); - ISP_IOXPUT_16(isp, tqsrc->_res2, &tqdst->_res2); - ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); - ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); - for (i = 0; i < 16; i++) { - ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_16(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } - ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); +} + +void +isp_put_request_t3(ispsoftc_t *isp, ispreqt3_t *src, ispreqt3_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); for (i = 0; i < ISP_RQDSEG_T3; i++) { - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, - &tqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_basehi, - &tqdst->req_dataseg[i].ds_basehi); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, - &tqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, + &dst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_request_t3e(ispsoftc_t *isp, ispreqt3e_t *tqsrc, ispreqt3e_t *tqdst) +isp_put_request_t3e(ispsoftc_t *isp, ispreqt3e_t *src, ispreqt3e_t *dst) { int i; - isp_copy_out_hdr(isp, &tqsrc->req_header, &tqdst->req_header); - ISP_IOXPUT_32(isp, tqsrc->req_handle, &tqdst->req_handle); - ISP_IOXPUT_16(isp, tqsrc->req_target, &tqdst->req_target); - ISP_IOXPUT_16(isp, tqsrc->req_scclun, &tqdst->req_scclun); - ISP_IOXPUT_16(isp, tqsrc->req_flags, &tqdst->req_flags); - ISP_IOXPUT_16(isp, tqsrc->_res2, &tqdst->_res2); - ISP_IOXPUT_16(isp, tqsrc->req_time, &tqdst->req_time); - ISP_IOXPUT_16(isp, tqsrc->req_seg_count, &tqdst->req_seg_count); - for (i = 0; i < 16; i++) { - ISP_IOXPUT_8(isp, tqsrc->req_cdb[i], &tqdst->req_cdb[i]); - } - ISP_IOXPUT_32(isp, tqsrc->req_totalcnt, &tqdst->req_totalcnt); + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_16(isp, src->req_target, &dst->req_target); + ISP_IOXPUT_16(isp, src->req_scclun, &dst->req_scclun); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); + } + ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt); for (i = 0; i < ISP_RQDSEG_T3; i++) { - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_base, - &tqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_basehi, - &tqdst->req_dataseg[i].ds_basehi); - ISP_IOXPUT_32(isp, tqsrc->req_dataseg[i].ds_count, - &tqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, + &dst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_extended_request(ispsoftc_t *isp, ispextreq_t *xqsrc, - ispextreq_t *xqdst) +isp_put_extended_request(ispsoftc_t *isp, ispextreq_t *src, ispextreq_t *dst) { int i; - isp_copy_out_hdr(isp, &xqsrc->req_header, &xqdst->req_header); - ISP_IOXPUT_32(isp, xqsrc->req_handle, &xqdst->req_handle); + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, xqsrc->req_lun_trn, &xqdst->req_target); - ISP_IOXPUT_8(isp, xqsrc->req_target, &xqdst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_target); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_lun_trn); } else { - ISP_IOXPUT_8(isp, xqsrc->req_lun_trn, &xqdst->req_lun_trn); - ISP_IOXPUT_8(isp, xqsrc->req_target, &xqdst->req_target); + ISP_IOXPUT_8(isp, src->req_lun_trn, &dst->req_lun_trn); + ISP_IOXPUT_8(isp, src->req_target, &dst->req_target); } - ISP_IOXPUT_16(isp, xqsrc->req_cdblen, &xqdst->req_cdblen); - ISP_IOXPUT_16(isp, xqsrc->req_flags, &xqdst->req_flags); - ISP_IOXPUT_16(isp, xqsrc->req_time, &xqdst->req_time); - ISP_IOXPUT_16(isp, xqsrc->req_seg_count, &xqdst->req_seg_count); - for (i = 0; i < 44; i++) { - ISP_IOXPUT_8(isp, xqsrc->req_cdb[i], &xqdst->req_cdb[i]); + ISP_IOXPUT_16(isp, src->req_cdblen, &dst->req_cdblen); + ISP_IOXPUT_16(isp, src->req_flags, &dst->req_flags); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + for (i = 0; i < ASIZE(src->req_cdb); i++) { + ISP_IOXPUT_8(isp, src->req_cdb[i], &dst->req_cdb[i]); } } void -isp_put_cont_req(ispsoftc_t *isp, ispcontreq_t *cqsrc, ispcontreq_t *cqdst) +isp_put_request_t7(ispsoftc_t *isp, ispreqt7_t *src, ispreqt7_t *dst) { int i; - isp_copy_out_hdr(isp, &cqsrc->req_header, &cqdst->req_header); + uint32_t *a, *b; + + isp_put_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXPUT_32(isp, src->req_handle, &dst->req_handle); + ISP_IOXPUT_16(isp, src->req_nphdl, &dst->req_nphdl); + ISP_IOXPUT_16(isp, src->req_time, &dst->req_time); + ISP_IOXPUT_16(isp, src->req_seg_count, &dst->req_seg_count); + ISP_IOXPUT_16(isp, src->req_reserved, &dst->req_reserved); + a = (uint32_t *) src->req_lun; + b = (uint32_t *) dst->req_lun; + for (i = 0; i < (ASIZE(src->req_lun) >> 2); i++ ) { + ISP_IOZPUT_32(isp, *a++, b++); + } + ISP_IOXPUT_8(isp, src->req_alen_datadir, &dst->req_alen_datadir); + ISP_IOXPUT_8(isp, src->req_task_management, &dst->req_task_management); + ISP_IOXPUT_8(isp, src->req_task_attribute, &dst->req_task_attribute); + ISP_IOXPUT_8(isp, src->req_crn, &dst->req_crn); + a = (uint32_t *) src->req_cdb; + b = (uint32_t *) dst->req_cdb; + for (i = 0; i < (ASIZE(src->req_cdb) >> 2); i++ ) { + ISP_IOZPUT_32(isp, *a++, b++); + } + ISP_IOXPUT_32(isp, src->req_dl, &dst->req_dl); + ISP_IOXPUT_16(isp, src->req_tidlo, &dst->req_tidlo); + ISP_IOXPUT_8(isp, src->req_tidhi, &dst->req_tidhi); + ISP_IOXPUT_8(isp, src->req_vpidx, &dst->req_vpidx); + ISP_IOXPUT_32(isp, src->req_dataseg.ds_base, + &dst->req_dataseg.ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg.ds_basehi, + &dst->req_dataseg.ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg.ds_count, + &dst->req_dataseg.ds_count); +} + +void +isp_put_24xx_abrt(ispsoftc_t *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst) +{ + int i; + isp_put_hdr(isp, &src->abrt_header, &dst->abrt_header); + ISP_IOXPUT_32(isp, src->abrt_handle, &dst->abrt_handle); + ISP_IOXPUT_16(isp, src->abrt_nphdl, &dst->abrt_nphdl); + ISP_IOXPUT_16(isp, src->abrt_options, &dst->abrt_options); + ISP_IOXPUT_32(isp, src->abrt_cmd_handle, &dst->abrt_cmd_handle); + for (i = 0; i < ASIZE(src->abrt_reserved); i++) { + ISP_IOXPUT_8(isp, src->abrt_reserved[i], + &dst->abrt_reserved[i]); + } + ISP_IOXPUT_16(isp, src->abrt_tidlo, &dst->abrt_tidlo); + ISP_IOXPUT_8(isp, src->abrt_tidhi, &dst->abrt_tidhi); + ISP_IOXPUT_8(isp, src->abrt_vpidx, &dst->abrt_vpidx); + for (i = 0; i < ASIZE(src->abrt_reserved1); i++) { + ISP_IOXPUT_8(isp, src->abrt_reserved1[i], + &dst->abrt_reserved1[i]); + } +} + +void +isp_put_cont_req(ispsoftc_t *isp, ispcontreq_t *src, ispcontreq_t *dst) +{ + int i; + isp_put_hdr(isp, &src->req_header, &dst->req_header); for (i = 0; i < ISP_CDSEG; i++) { - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_base, - &cqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_count, - &cqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_put_cont64_req(ispsoftc_t *isp, ispcontreq64_t *cqsrc, - ispcontreq64_t *cqdst) +isp_put_cont64_req(ispsoftc_t *isp, ispcontreq64_t *src, ispcontreq64_t *dst) { int i; - isp_copy_out_hdr(isp, &cqsrc->req_header, &cqdst->req_header); + isp_put_hdr(isp, &src->req_header, &dst->req_header); for (i = 0; i < ISP_CDSEG64; i++) { - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_base, - &cqdst->req_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_basehi, - &cqdst->req_dataseg[i].ds_basehi); - ISP_IOXPUT_32(isp, cqsrc->req_dataseg[i].ds_count, - &cqdst->req_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, + &dst->req_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, + &dst->req_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, + &dst->req_dataseg[i].ds_count); } } void -isp_get_response(ispsoftc_t *isp, ispstatusreq_t *spsrc, - ispstatusreq_t *spdst) +isp_get_response(ispsoftc_t *isp, ispstatusreq_t *src, ispstatusreq_t *dst) { int i; - isp_copy_in_hdr(isp, &spsrc->req_header, &spdst->req_header); - ISP_IOXGET_32(isp, &spsrc->req_handle, spdst->req_handle); - ISP_IOXGET_16(isp, &spsrc->req_scsi_status, spdst->req_scsi_status); - ISP_IOXGET_16(isp, &spsrc->req_completion_status, - spdst->req_completion_status); - ISP_IOXGET_16(isp, &spsrc->req_state_flags, spdst->req_state_flags); - ISP_IOXGET_16(isp, &spsrc->req_status_flags, spdst->req_status_flags); - ISP_IOXGET_16(isp, &spsrc->req_time, spdst->req_time); - ISP_IOXGET_16(isp, &spsrc->req_sense_len, spdst->req_sense_len); - ISP_IOXGET_32(isp, &spsrc->req_resid, spdst->req_resid); + isp_get_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle); + ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status); + ISP_IOXGET_16(isp, &src->req_completion_status, + dst->req_completion_status); + ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags); + ISP_IOXGET_16(isp, &src->req_status_flags, dst->req_status_flags); + ISP_IOXGET_16(isp, &src->req_time, dst->req_time); + ISP_IOXGET_16(isp, &src->req_sense_len, dst->req_sense_len); + ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid); for (i = 0; i < 8; i++) { - ISP_IOXGET_8(isp, &spsrc->req_response[i], - spdst->req_response[i]); + ISP_IOXGET_8(isp, &src->req_response[i], + dst->req_response[i]); } for (i = 0; i < 32; i++) { - ISP_IOXGET_8(isp, &spsrc->req_sense_data[i], - spdst->req_sense_data[i]); + ISP_IOXGET_8(isp, &src->req_sense_data[i], + dst->req_sense_data[i]); + } +} + +void +isp_get_24xx_response(ispsoftc_t *isp, isp24xx_statusreq_t *src, + isp24xx_statusreq_t *dst) +{ + int i; + isp_get_hdr(isp, &src->req_header, &dst->req_header); + ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle); + ISP_IOXGET_16(isp, &src->req_completion_status, + dst->req_completion_status); + ISP_IOXGET_16(isp, &src->req_oxid, dst->req_oxid); + ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid); + ISP_IOXGET_16(isp, &src->req_reserved0, dst->req_reserved0); + ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags); + ISP_IOXGET_16(isp, &src->req_reserved1, dst->req_reserved1); + ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status); + ISP_IOXGET_32(isp, &src->req_fcp_residual, dst->req_fcp_residual); + ISP_IOXGET_32(isp, &src->req_sense_len, dst->req_sense_len); + ISP_IOXGET_32(isp, &src->req_response_len, dst->req_response_len); + for (i = 0; i < 28; i++) { + ISP_IOXGET_8(isp, &src->req_rsp_sense[i], + dst->req_rsp_sense[i]); } } void -isp_get_response_x(ispsoftc_t *isp, ispstatus_cont_t *cpsrc, - ispstatus_cont_t *cpdst) +isp_get_24xx_abrt(ispsoftc_t *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst) { int i; - isp_copy_in_hdr(isp, &cpsrc->req_header, &cpdst->req_header); - for (i = 0; i < 60; i++) { - ISP_IOXGET_8(isp, &cpsrc->req_sense_data[i], - cpdst->req_sense_data[i]); + isp_get_hdr(isp, &src->abrt_header, &dst->abrt_header); + ISP_IOXGET_32(isp, &src->abrt_handle, dst->abrt_handle); + ISP_IOXGET_16(isp, &src->abrt_nphdl, dst->abrt_nphdl); + ISP_IOXGET_16(isp, &src->abrt_options, dst->abrt_options); + ISP_IOXGET_32(isp, &src->abrt_cmd_handle, dst->abrt_cmd_handle); + for (i = 0; i < ASIZE(&src->abrt_reserved); i++) { + ISP_IOXGET_8(isp, &src->abrt_reserved[i], + dst->abrt_reserved[i]); + } + ISP_IOXGET_16(isp, &src->abrt_tidlo, dst->abrt_tidlo); + ISP_IOXGET_8(isp, &src->abrt_tidhi, dst->abrt_tidhi); + ISP_IOXGET_8(isp, &src->abrt_vpidx, dst->abrt_vpidx); + for (i = 0; i < ASIZE(&src->abrt_reserved1); i++) { + ISP_IOXGET_8(isp, &src->abrt_reserved1[i], + dst->abrt_reserved1[i]); } } + void isp_get_rio2(ispsoftc_t *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst) { int i; - isp_copy_in_hdr(isp, &r2src->req_header, &r2dst->req_header); - if (r2dst->req_header.rqs_seqno > 30) + isp_get_hdr(isp, &r2src->req_header, &r2dst->req_header); + if (r2dst->req_header.rqs_seqno > 30) { r2dst->req_header.rqs_seqno = 30; + } for (i = 0; i < r2dst->req_header.rqs_seqno; i++) { ISP_IOXGET_16(isp, &r2src->req_handles[i], r2dst->req_handles[i]); @@ -539,73 +706,128 @@ isp_get_rio2(ispsoftc_t *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst) } void -isp_put_icb(ispsoftc_t *isp, isp_icb_t *Is, isp_icb_t *Id) +isp_put_icb(ispsoftc_t *isp, isp_icb_t *src, isp_icb_t *dst) { int i; if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, Is->icb_version, &Id->_reserved0); - ISP_IOXPUT_8(isp, Is->_reserved0, &Id->icb_version); + ISP_IOXPUT_8(isp, src->icb_version, &dst->icb_reserved0); + ISP_IOXPUT_8(isp, src->icb_reserved0, &dst->icb_version); } else { - ISP_IOXPUT_8(isp, Is->icb_version, &Id->icb_version); - ISP_IOXPUT_8(isp, Is->_reserved0, &Id->_reserved0); + ISP_IOXPUT_8(isp, src->icb_version, &dst->icb_version); + ISP_IOXPUT_8(isp, src->icb_reserved0, &dst->icb_reserved0); } - ISP_IOXPUT_16(isp, Is->icb_fwoptions, &Id->icb_fwoptions); - ISP_IOXPUT_16(isp, Is->icb_maxfrmlen, &Id->icb_maxfrmlen); - ISP_IOXPUT_16(isp, Is->icb_maxalloc, &Id->icb_maxalloc); - ISP_IOXPUT_16(isp, Is->icb_execthrottle, &Id->icb_execthrottle); + ISP_IOXPUT_16(isp, src->icb_fwoptions, &dst->icb_fwoptions); + ISP_IOXPUT_16(isp, src->icb_maxfrmlen, &dst->icb_maxfrmlen); + ISP_IOXPUT_16(isp, src->icb_maxalloc, &dst->icb_maxalloc); + ISP_IOXPUT_16(isp, src->icb_execthrottle, &dst->icb_execthrottle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, Is->icb_retry_count, &Id->icb_retry_delay); - ISP_IOXPUT_8(isp, Is->icb_retry_delay, &Id->icb_retry_count); + ISP_IOXPUT_8(isp, src->icb_retry_count, &dst->icb_retry_delay); + ISP_IOXPUT_8(isp, src->icb_retry_delay, &dst->icb_retry_count); } else { - ISP_IOXPUT_8(isp, Is->icb_retry_count, &Id->icb_retry_count); - ISP_IOXPUT_8(isp, Is->icb_retry_delay, &Id->icb_retry_delay); + ISP_IOXPUT_8(isp, src->icb_retry_count, &dst->icb_retry_count); + ISP_IOXPUT_8(isp, src->icb_retry_delay, &dst->icb_retry_delay); } for (i = 0; i < 8; i++) { - ISP_IOXPUT_8(isp, Is->icb_portname[i], &Id->icb_portname[i]); + ISP_IOXPUT_8(isp, src->icb_portname[i], &dst->icb_portname[i]); } - ISP_IOXPUT_16(isp, Is->icb_hardaddr, &Id->icb_hardaddr); + ISP_IOXPUT_16(isp, src->icb_hardaddr, &dst->icb_hardaddr); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, Is->icb_iqdevtype, &Id->icb_logintime); - ISP_IOXPUT_8(isp, Is->icb_logintime, &Id->icb_iqdevtype); + ISP_IOXPUT_8(isp, src->icb_iqdevtype, &dst->icb_logintime); + ISP_IOXPUT_8(isp, src->icb_logintime, &dst->icb_iqdevtype); } else { - ISP_IOXPUT_8(isp, Is->icb_iqdevtype, &Id->icb_iqdevtype); - ISP_IOXPUT_8(isp, Is->icb_logintime, &Id->icb_logintime); + ISP_IOXPUT_8(isp, src->icb_iqdevtype, &dst->icb_iqdevtype); + ISP_IOXPUT_8(isp, src->icb_logintime, &dst->icb_logintime); } for (i = 0; i < 8; i++) { - ISP_IOXPUT_8(isp, Is->icb_nodename[i], &Id->icb_nodename[i]); + ISP_IOXPUT_8(isp, src->icb_nodename[i], &dst->icb_nodename[i]); } - ISP_IOXPUT_16(isp, Is->icb_rqstout, &Id->icb_rqstout); - ISP_IOXPUT_16(isp, Is->icb_rspnsin, &Id->icb_rspnsin); - ISP_IOXPUT_16(isp, Is->icb_rqstqlen, &Id->icb_rqstqlen); - ISP_IOXPUT_16(isp, Is->icb_rsltqlen, &Id->icb_rsltqlen); + ISP_IOXPUT_16(isp, src->icb_rqstout, &dst->icb_rqstout); + ISP_IOXPUT_16(isp, src->icb_rspnsin, &dst->icb_rspnsin); + ISP_IOXPUT_16(isp, src->icb_rqstqlen, &dst->icb_rqstqlen); + ISP_IOXPUT_16(isp, src->icb_rsltqlen, &dst->icb_rsltqlen); for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, Is->icb_rqstaddr[i], &Id->icb_rqstaddr[i]); + ISP_IOXPUT_16(isp, src->icb_rqstaddr[i], &dst->icb_rqstaddr[i]); } for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, Is->icb_respaddr[i], &Id->icb_respaddr[i]); + ISP_IOXPUT_16(isp, src->icb_respaddr[i], &dst->icb_respaddr[i]); } - ISP_IOXPUT_16(isp, Is->icb_lunenables, &Id->icb_lunenables); + ISP_IOXPUT_16(isp, src->icb_lunenables, &dst->icb_lunenables); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, Is->icb_ccnt, &Id->icb_icnt); - ISP_IOXPUT_8(isp, Is->icb_icnt, &Id->icb_ccnt); + ISP_IOXPUT_8(isp, src->icb_ccnt, &dst->icb_icnt); + ISP_IOXPUT_8(isp, src->icb_icnt, &dst->icb_ccnt); } else { - ISP_IOXPUT_8(isp, Is->icb_ccnt, &Id->icb_ccnt); - ISP_IOXPUT_8(isp, Is->icb_icnt, &Id->icb_icnt); + ISP_IOXPUT_8(isp, src->icb_ccnt, &dst->icb_ccnt); + ISP_IOXPUT_8(isp, src->icb_icnt, &dst->icb_icnt); } - ISP_IOXPUT_16(isp, Is->icb_lunetimeout, &Id->icb_lunetimeout); - ISP_IOXPUT_16(isp, Is->icb_xfwoptions, &Id->icb_xfwoptions); + ISP_IOXPUT_16(isp, src->icb_lunetimeout, &dst->icb_lunetimeout); + ISP_IOXPUT_16(isp, src->icb_reserved1, &dst->icb_reserved1); + ISP_IOXPUT_16(isp, src->icb_xfwoptions, &dst->icb_xfwoptions); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, Is->icb_racctimer, &Id->icb_idelaytimer); - ISP_IOXPUT_8(isp, Is->icb_idelaytimer, &Id->icb_racctimer); + ISP_IOXPUT_8(isp, src->icb_racctimer, &dst->icb_idelaytimer); + ISP_IOXPUT_8(isp, src->icb_idelaytimer, &dst->icb_racctimer); } else { - ISP_IOXPUT_8(isp, Is->icb_racctimer, &Id->icb_racctimer); - ISP_IOXPUT_8(isp, Is->icb_idelaytimer, &Id->icb_idelaytimer); + ISP_IOXPUT_8(isp, src->icb_racctimer, &dst->icb_racctimer); + ISP_IOXPUT_8(isp, src->icb_idelaytimer, &dst->icb_idelaytimer); + } + ISP_IOXPUT_16(isp, src->icb_zfwoptions, &dst->icb_zfwoptions); +} + +void +isp_put_icb_2400(ispsoftc_t *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst) +{ + int i; + ISP_IOXPUT_16(isp, src->icb_version, &dst->icb_version); + ISP_IOXPUT_16(isp, src->icb_reserved0, &dst->icb_reserved0); + ISP_IOXPUT_16(isp, src->icb_maxfrmlen, &dst->icb_maxfrmlen); + ISP_IOXPUT_16(isp, src->icb_execthrottle, &dst->icb_execthrottle); + ISP_IOXPUT_16(isp, src->icb_xchgcnt, &dst->icb_xchgcnt); + ISP_IOXPUT_16(isp, src->icb_hardaddr, &dst->icb_hardaddr); + for (i = 0; i < 8; i++) { + ISP_IOXPUT_8(isp, src->icb_portname[i], &dst->icb_portname[i]); + } + for (i = 0; i < 8; i++) { + ISP_IOXPUT_8(isp, src->icb_nodename[i], &dst->icb_nodename[i]); + } + ISP_IOXPUT_16(isp, src->icb_rspnsin, &dst->icb_rspnsin); + ISP_IOXPUT_16(isp, src->icb_rqstout, &dst->icb_rqstout); + ISP_IOXPUT_16(isp, src->icb_retry_count, &dst->icb_retry_count); + ISP_IOXPUT_16(isp, src->icb_priout, &dst->icb_priout); + ISP_IOXPUT_16(isp, src->icb_rsltqlen, &dst->icb_rsltqlen); + ISP_IOXPUT_16(isp, src->icb_rqstqlen, &dst->icb_rqstqlen); + ISP_IOXPUT_16(isp, src->icb_ldn_nols, &dst->icb_ldn_nols); + ISP_IOXPUT_16(isp, src->icb_prqstqlen, &dst->icb_prqstqlen); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_rqstaddr[i], &dst->icb_rqstaddr[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_respaddr[i], &dst->icb_respaddr[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_priaddr[i], &dst->icb_priaddr[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_reserved1[i], + &dst->icb_reserved1[i]); + } + ISP_IOXPUT_16(isp, src->icb_atio_in, &dst->icb_atio_in); + ISP_IOXPUT_16(isp, src->icb_atioqlen, &dst->icb_atioqlen); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, src->icb_atioqaddr[i], + &dst->icb_atioqaddr[i]); + } + ISP_IOXPUT_16(isp, src->icb_idelaytimer, &dst->icb_idelaytimer); + ISP_IOXPUT_16(isp, src->icb_logintime, &dst->icb_logintime); + ISP_IOXPUT_32(isp, src->icb_fwoptions1, &dst->icb_fwoptions1); + ISP_IOXPUT_32(isp, src->icb_fwoptions2, &dst->icb_fwoptions2); + ISP_IOXPUT_32(isp, src->icb_fwoptions3, &dst->icb_fwoptions3); + for (i = 0; i < 12; i++) { + ISP_IOXPUT_16(isp, src->icb_reserved2[i], + &dst->icb_reserved2[i]); } - ISP_IOXPUT_16(isp, Is->icb_zfwoptions, &Id->icb_zfwoptions); } void -isp_get_pdb(ispsoftc_t *isp, isp_pdb_t *src, isp_pdb_t *dst) +isp_get_pdb_21xx(ispsoftc_t *isp, isp_pdb_21xx_t *src, isp_pdb_21xx_t *dst) { int i; ISP_IOXGET_16(isp, &src->pdb_options, dst->pdb_options); @@ -658,29 +880,144 @@ isp_get_pdb(ispsoftc_t *isp, isp_pdb_t *src, isp_pdb_t *dst) ISP_IOXGET_16(isp, &src->pdb_sl_ptr, dst->pdb_sl_ptr); } +void +isp_get_pdb_24xx(ispsoftc_t *isp, isp_pdb_24xx_t *src, isp_pdb_24xx_t *dst) +{ + int i; + ISP_IOXGET_16(isp, &src->pdb_flags, dst->pdb_flags); + ISP_IOXGET_8(isp, &src->pdb_curstate, dst->pdb_curstate); + ISP_IOXGET_8(isp, &src->pdb_laststate, dst->pdb_laststate); + for (i = 0; i < 4; i++) { + ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i], + dst->pdb_hardaddr_bits[i]); + } + for (i = 0; i < 4; i++) { + ISP_IOXGET_8(isp, &src->pdb_portid_bits[i], + dst->pdb_portid_bits[i]); + } + ISP_IOXGET_16(isp, &src->pdb_retry_timer, dst->pdb_retry_timer); + ISP_IOXGET_16(isp, &src->pdb_handle, dst->pdb_handle); + ISP_IOXGET_16(isp, &src->pdb_rcv_dsize, dst->pdb_rcv_dsize); + ISP_IOXGET_16(isp, &src->pdb_reserved0, dst->pdb_reserved0); + ISP_IOXGET_16(isp, &src->pdb_prli_svc0, dst->pdb_prli_svc0); + ISP_IOXGET_16(isp, &src->pdb_prli_svc3, dst->pdb_prli_svc3); + for (i = 0; i < 8; i++) { + ISP_IOXGET_8(isp, &src->pdb_nodename[i], dst->pdb_nodename[i]); + } + for (i = 0; i < 8; i++) { + ISP_IOXGET_8(isp, &src->pdb_portname[i], dst->pdb_portname[i]); + } + for (i = 0; i < 24; i++) { + ISP_IOXGET_8(isp, &src->pdb_reserved1[i], + dst->pdb_reserved1[i]); + } +} /* - * CT_HDR canonicalization- only needed for SNS responses + * PLOGI/LOGO IOCB canonicalization */ + void -isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst) +isp_get_plogx(ispsoftc_t *isp, isp_plogx_t *src, isp_plogx_t *dst) +{ + int i; + isp_get_hdr(isp, &src->plogx_header, &dst->plogx_header); + ISP_IOXGET_32(isp, &src->plogx_handle, dst->plogx_handle); + ISP_IOXGET_16(isp, &src->plogx_status, dst->plogx_status); + ISP_IOXGET_16(isp, &src->plogx_nphdl, dst->plogx_nphdl); + ISP_IOXGET_16(isp, &src->plogx_flags, dst->plogx_flags); + ISP_IOXGET_16(isp, &src->plogx_vphdl, dst->plogx_vphdl); + ISP_IOXGET_16(isp, &src->plogx_portlo, dst->plogx_portlo); + ISP_IOXGET_16(isp, &src->plogx_rspsz_porthi, dst->plogx_rspsz_porthi); + for (i = 0; i < 11; i++) { + ISP_IOXGET_16(isp, &src->plogx_ioparm[i].lo16, + dst->plogx_ioparm[i].lo16); + ISP_IOXGET_16(isp, &src->plogx_ioparm[i].hi16, + dst->plogx_ioparm[i].hi16); + } +} + +void +isp_put_plogx(ispsoftc_t *isp, isp_plogx_t *src, isp_plogx_t *dst) { - ISP_IOXGET_8(isp, &src->ct_revision, dst->ct_revision); - ISP_IOXGET_8(isp, &src->ct_portid[0], dst->ct_portid[0]); - ISP_IOXGET_8(isp, &src->ct_portid[1], dst->ct_portid[1]); - ISP_IOXGET_8(isp, &src->ct_portid[2], dst->ct_portid[2]); - ISP_IOXGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type); - ISP_IOXGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype); - ISP_IOXGET_8(isp, &src->ct_options, dst->ct_options); - ISP_IOXGET_8(isp, &src->ct_res0, dst->ct_res0); - ISP_IOXGET_16(isp, &src->ct_response, dst->ct_response); - dst->ct_response = (dst->ct_response << 8) | (dst->ct_response >> 8); - ISP_IOXGET_16(isp, &src->ct_resid, dst->ct_resid); - dst->ct_resid = (dst->ct_resid << 8) | (dst->ct_resid >> 8); - ISP_IOXGET_8(isp, &src->ct_res1, dst->ct_res1); - ISP_IOXGET_8(isp, &src->ct_reason, dst->ct_reason); - ISP_IOXGET_8(isp, &src->ct_explanation, dst->ct_explanation); - ISP_IOXGET_8(isp, &src->ct_vunique, dst->ct_vunique); + int i; + isp_put_hdr(isp, &src->plogx_header, &dst->plogx_header); + ISP_IOXPUT_32(isp, src->plogx_handle, &dst->plogx_handle); + ISP_IOXPUT_16(isp, src->plogx_status, &dst->plogx_status); + ISP_IOXPUT_16(isp, src->plogx_nphdl, &dst->plogx_nphdl); + ISP_IOXPUT_16(isp, src->plogx_flags, &dst->plogx_flags); + ISP_IOXPUT_16(isp, src->plogx_vphdl, &dst->plogx_vphdl); + ISP_IOXPUT_16(isp, src->plogx_portlo, &dst->plogx_portlo); + ISP_IOXPUT_16(isp, src->plogx_rspsz_porthi, &dst->plogx_rspsz_porthi); + for (i = 0; i < 11; i++) { + ISP_IOXPUT_16(isp, src->plogx_ioparm[i].lo16, + &dst->plogx_ioparm[i].lo16); + ISP_IOXPUT_16(isp, src->plogx_ioparm[i].hi16, + &dst->plogx_ioparm[i].hi16); + } +} + +/* + * CT Passthru canonicalization + */ +void +isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ctp_header, &dst->ctp_header); + ISP_IOXGET_32(isp, &src->ctp_handle, dst->ctp_handle); + ISP_IOXGET_16(isp, &src->ctp_status, dst->ctp_status); + ISP_IOXGET_16(isp, &src->ctp_nphdl, dst->ctp_nphdl); + ISP_IOXGET_16(isp, &src->ctp_cmd_cnt, dst->ctp_cmd_cnt); + ISP_IOXGET_16(isp, &src->ctp_vpidx, dst->ctp_vpidx); + ISP_IOXGET_16(isp, &src->ctp_time, dst->ctp_time); + ISP_IOXGET_16(isp, &src->ctp_reserved0, dst->ctp_reserved0); + ISP_IOXGET_16(isp, &src->ctp_rsp_cnt, dst->ctp_rsp_cnt); + for (i = 0; i < 5; i++) { + ISP_IOXGET_16(isp, &src->ctp_reserved1[i], + dst->ctp_reserved1[i]); + } + ISP_IOXGET_32(isp, &src->ctp_rsp_bcnt, dst->ctp_rsp_bcnt); + ISP_IOXGET_32(isp, &src->ctp_cmd_bcnt, dst->ctp_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_base, + dst->ctp_dataseg[i].ds_base); + ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_basehi, + dst->ctp_dataseg[i].ds_basehi); + ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_count, + dst->ctp_dataseg[i].ds_count); + } +} + +void +isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->ctp_header, &dst->ctp_header); + ISP_IOXPUT_32(isp, src->ctp_handle, &dst->ctp_handle); + ISP_IOXPUT_16(isp, src->ctp_status, &dst->ctp_status); + ISP_IOXPUT_16(isp, src->ctp_nphdl, &dst->ctp_nphdl); + ISP_IOXPUT_16(isp, src->ctp_cmd_cnt, &dst->ctp_cmd_cnt); + ISP_IOXPUT_16(isp, src->ctp_vpidx, &dst->ctp_vpidx); + ISP_IOXPUT_16(isp, src->ctp_time, &dst->ctp_time); + ISP_IOXPUT_16(isp, src->ctp_reserved0, &dst->ctp_reserved0); + ISP_IOXPUT_16(isp, src->ctp_rsp_cnt, &dst->ctp_rsp_cnt); + for (i = 0; i < 5; i++) { + ISP_IOXPUT_16(isp, src->ctp_reserved1[i], + &dst->ctp_reserved1[i]); + } + ISP_IOXPUT_32(isp, src->ctp_rsp_bcnt, &dst->ctp_rsp_bcnt); + ISP_IOXPUT_32(isp, src->ctp_cmd_bcnt, &dst->ctp_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_base, + &dst->ctp_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_basehi, + &dst->ctp_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_count, + &dst->ctp_dataseg[i].ds_count); + } } /* @@ -707,16 +1044,16 @@ isp_put_gid_ft_request(ispsoftc_t *isp, sns_gid_ft_req_t *src, sns_gid_ft_req_t *dst) { ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen); - ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0); + ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0); ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]); ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]); ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]); ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]); ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen); - ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1); + ISP_IOXPUT_16(isp, src->snscb_reserved1, &dst->snscb_reserved1); ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd); ISP_IOXPUT_16(isp, src->snscb_mword_div_2, &dst->snscb_mword_div_2); - ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3); + ISP_IOXPUT_32(isp, src->snscb_reserved3, &dst->snscb_reserved3); ISP_IOXPUT_32(isp, src->snscb_fc4_type, &dst->snscb_fc4_type); } @@ -725,16 +1062,16 @@ isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src, sns_gxn_id_req_t *dst) { ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen); - ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0); + ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0); ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]); ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]); ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]); ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]); ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen); - ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1); + ISP_IOXPUT_16(isp, src->snscb_reserved1, &dst->snscb_reserved1); ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd); - ISP_IOXPUT_16(isp, src->snscb_res2, &dst->snscb_res2); - ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3); + ISP_IOXPUT_16(isp, src->snscb_reserved2, &dst->snscb_reserved2); + ISP_IOXPUT_32(isp, src->snscb_reserved3, &dst->snscb_reserved3); ISP_IOXPUT_32(isp, src->snscb_portid, &dst->snscb_portid); } @@ -858,10 +1195,182 @@ isp_get_ga_nxt_response(ispsoftc_t *isp, sns_ga_nxt_rsp_t *src, } } -#ifdef ISP_TARGET_MODE +void +isp_get_els(ispsoftc_t *isp, els_t *src, els_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->els_hdr, &dst->els_hdr); + ISP_IOXGET_32(isp, &src->els_handle, dst->els_handle); + ISP_IOXGET_16(isp, &src->els_status, dst->els_status); + ISP_IOXGET_16(isp, &src->els_nphdl, dst->els_nphdl); + ISP_IOXGET_16(isp, &src->els_xmit_dsd_count, dst->els_xmit_dsd_count); + ISP_IOXGET_8(isp, &src->els_vphdl, dst->els_vphdl); + ISP_IOXGET_8(isp, &src->els_sof, dst->els_sof); + ISP_IOXGET_32(isp, &src->els_rxid, dst->els_rxid); + ISP_IOXGET_16(isp, &src->els_recv_dsd_count, dst->els_recv_dsd_count); + ISP_IOXGET_8(isp, &src->els_opcode, dst->els_opcode); + ISP_IOXGET_8(isp, &src->els_reserved2, dst->els_reserved1); + ISP_IOXGET_8(isp, &src->els_did_lo, dst->els_did_lo); + ISP_IOXGET_8(isp, &src->els_did_mid, dst->els_did_mid); + ISP_IOXGET_8(isp, &src->els_did_hi, dst->els_did_hi); + ISP_IOXGET_8(isp, &src->els_reserved2, dst->els_reserved2); + ISP_IOXGET_16(isp, &src->els_reserved3, dst->els_reserved3); + ISP_IOXGET_16(isp, &src->els_ctl_flags, dst->els_ctl_flags); + ISP_IOXGET_32(isp, &src->els_bytecnt, dst->els_bytecnt); + ISP_IOXGET_32(isp, &src->els_subcode1, dst->els_subcode1); + ISP_IOXGET_32(isp, &src->els_subcode2, dst->els_subcode2); + for (i = 0; i < 20; i++) { + ISP_IOXGET_8(isp, &src->els_reserved4[i], + dst->els_reserved4[i]); + } +} + +void +isp_put_els(ispsoftc_t *isp, els_t *src, els_t *dst) +{ + isp_put_hdr(isp, &src->els_hdr, &dst->els_hdr); + ISP_IOXPUT_32(isp, src->els_handle, &dst->els_handle); + ISP_IOXPUT_16(isp, src->els_status, &dst->els_status); + ISP_IOXPUT_16(isp, src->els_nphdl, &dst->els_nphdl); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_count, &dst->els_xmit_dsd_count); + ISP_IOXPUT_8(isp, src->els_vphdl, &dst->els_vphdl); + ISP_IOXPUT_8(isp, src->els_sof, &dst->els_sof); + ISP_IOXPUT_32(isp, src->els_rxid, &dst->els_rxid); + ISP_IOXPUT_16(isp, src->els_recv_dsd_count, &dst->els_recv_dsd_count); + ISP_IOXPUT_8(isp, src->els_opcode, &dst->els_opcode); + ISP_IOXPUT_8(isp, src->els_reserved2, &dst->els_reserved1); + ISP_IOXPUT_8(isp, src->els_did_lo, &dst->els_did_lo); + ISP_IOXPUT_8(isp, src->els_did_mid, &dst->els_did_mid); + ISP_IOXPUT_8(isp, src->els_did_hi, &dst->els_did_hi); + ISP_IOXPUT_8(isp, src->els_reserved2, &dst->els_reserved2); + ISP_IOXPUT_16(isp, src->els_reserved3, &dst->els_reserved3); + ISP_IOXPUT_16(isp, src->els_ctl_flags, &dst->els_ctl_flags); + ISP_IOXPUT_32(isp, src->els_recv_bytecnt, &dst->els_recv_bytecnt); + ISP_IOXPUT_32(isp, src->els_xmit_bytecnt, &dst->els_xmit_bytecnt); + ISP_IOXPUT_32(isp, src->els_xmit_dsd_length, &dst->els_xmit_dsd_length); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a1500, &dst->els_xmit_dsd_a1500); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a3116, &dst->els_xmit_dsd_a3116); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a4732, &dst->els_xmit_dsd_a4732); + ISP_IOXPUT_16(isp, src->els_xmit_dsd_a6348, &dst->els_xmit_dsd_a6348); + ISP_IOXPUT_32(isp, src->els_recv_dsd_length, &dst->els_recv_dsd_length); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a1500, &dst->els_recv_dsd_a1500); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a3116, &dst->els_recv_dsd_a3116); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a4732, &dst->els_recv_dsd_a4732); + ISP_IOXPUT_16(isp, src->els_recv_dsd_a6348, &dst->els_recv_dsd_a6348); +} + +/* + * FC Structure Canonicalization + */ + +void +isp_get_fc_hdr(ispsoftc_t *isp, fc_hdr_t *src, fc_hdr_t *dst) +{ + ISP_IOZGET_8(isp, &src->r_ctl, dst->r_ctl); + ISP_IOZGET_8(isp, &src->d_id[0], dst->d_id[0]); + ISP_IOZGET_8(isp, &src->d_id[1], dst->d_id[1]); + ISP_IOZGET_8(isp, &src->d_id[2], dst->d_id[2]); + ISP_IOZGET_8(isp, &src->cs_ctl, dst->cs_ctl); + ISP_IOZGET_8(isp, &src->s_id[0], dst->s_id[0]); + ISP_IOZGET_8(isp, &src->s_id[1], dst->s_id[1]); + ISP_IOZGET_8(isp, &src->s_id[2], dst->s_id[2]); + ISP_IOZGET_8(isp, &src->type, dst->type); + ISP_IOZGET_8(isp, &src->f_ctl, dst->f_ctl); + ISP_IOZGET_8(isp, &src->seq_id, dst->seq_id); + ISP_IOZGET_8(isp, &src->df_ctl, dst->df_ctl); + ISP_IOZGET_16(isp, &src->seq_cnt, dst->seq_cnt); + /* XXX SOMETHING WAS AND STILL CONTINUES WRONG HERE XXX */ +#if 0 + ISP_IOZGET_16(isp, &src->ox_id, dst->ox_id); + ISP_IOZGET_16(isp, &src->rx_id, dst->rx_id); +#else + ISP_IOZGET_32(isp, &src->ox_id, dst->parameter); + dst->ox_id = dst->parameter; + dst->rx_id = dst->parameter >> 16; +#endif + ISP_IOZGET_32(isp, &src->parameter, dst->parameter); +} + +void +isp_get_fcp_cmnd_iu(ispsoftc_t *isp, fcp_cmnd_iu_t *src, fcp_cmnd_iu_t *dst) +{ + int i; + + for (i = 0; i < 8; i++) { + ISP_IOZGET_8(isp, &src->fcp_cmnd_lun[i], dst->fcp_cmnd_lun[i]); + } + ISP_IOZGET_8(isp, &src->fcp_cmnd_crn, dst->fcp_cmnd_crn); + ISP_IOZGET_8(isp, &src->fcp_cmnd_task_attribute, + dst->fcp_cmnd_task_attribute); + ISP_IOZGET_8(isp, &src->fcp_cmnd_task_management, + dst->fcp_cmnd_task_management); + ISP_IOZGET_8(isp, &src->fcp_cmnd_alen_datadir, + dst->fcp_cmnd_alen_datadir); + for (i = 0; i < 16; i++) { + ISP_IOZGET_8(isp, &src->cdb_dl.sf.fcp_cmnd_cdb[i], + dst->cdb_dl.sf.fcp_cmnd_cdb[i]); + } + ISP_IOZGET_32(isp, &src->cdb_dl.sf.fcp_cmnd_dl, + dst->cdb_dl.sf.fcp_cmnd_dl); +} + +void +isp_put_rft_id(ispsoftc_t *isp, rft_id_t *src, rft_id_t *dst) +{ + int i; + isp_put_ct_hdr(isp, &src->rftid_hdr, &dst->rftid_hdr); + ISP_IOZPUT_8(isp, src->rftid_reserved, &dst->rftid_reserved); + for (i = 0; i < 3; i++) { + ISP_IOZPUT_8(isp, src->rftid_portid[i], &dst->rftid_portid[i]); + } + for (i = 0; i < 8; i++) { + ISP_IOZPUT_32(isp, src->rftid_fc4types[i], + &dst->rftid_fc4types[i]); + } +} + +void +isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst) +{ + ISP_IOZGET_8(isp, &src->ct_revision, dst->ct_revision); + ISP_IOZGET_8(isp, &src->ct_in_id[0], dst->ct_in_id[0]); + ISP_IOZGET_8(isp, &src->ct_in_id[1], dst->ct_in_id[1]); + ISP_IOZGET_8(isp, &src->ct_in_id[2], dst->ct_in_id[2]); + ISP_IOZGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type); + ISP_IOZGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype); + ISP_IOZGET_8(isp, &src->ct_options, dst->ct_options); + ISP_IOZGET_8(isp, &src->ct_reserved0, dst->ct_reserved0); + ISP_IOZGET_16(isp, &src->ct_cmd_resp, dst->ct_cmd_resp); + ISP_IOZGET_16(isp, &src->ct_bcnt_resid, dst->ct_bcnt_resid); + ISP_IOZGET_8(isp, &src->ct_reserved1, dst->ct_reserved1); + ISP_IOZGET_8(isp, &src->ct_reason, dst->ct_reason); + ISP_IOZGET_8(isp, &src->ct_explanation, dst->ct_explanation); + ISP_IOZGET_8(isp, &src->ct_vunique, dst->ct_vunique); +} +void +isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst) +{ + ISP_IOZPUT_8(isp, src->ct_revision, &dst->ct_revision); + ISP_IOZPUT_8(isp, src->ct_in_id[0], &dst->ct_in_id[0]); + ISP_IOZPUT_8(isp, src->ct_in_id[1], &dst->ct_in_id[1]); + ISP_IOZPUT_8(isp, src->ct_in_id[2], &dst->ct_in_id[2]); + ISP_IOZPUT_8(isp, src->ct_fcs_type, &dst->ct_fcs_type); + ISP_IOZPUT_8(isp, src->ct_fcs_subtype, &dst->ct_fcs_subtype); + ISP_IOZPUT_8(isp, src->ct_options, &dst->ct_options); + ISP_IOZPUT_8(isp, src->ct_reserved0, &dst->ct_reserved0); + ISP_IOZPUT_16(isp, src->ct_cmd_resp, &dst->ct_cmd_resp); + ISP_IOZPUT_16(isp, src->ct_bcnt_resid, &dst->ct_bcnt_resid); + ISP_IOZPUT_8(isp, src->ct_reserved1, &dst->ct_reserved1); + ISP_IOZPUT_8(isp, src->ct_reason, &dst->ct_reason); + ISP_IOZPUT_8(isp, src->ct_explanation, &dst->ct_explanation); + ISP_IOZPUT_8(isp, src->ct_vunique, &dst->ct_vunique); +} + +#ifdef ISP_TARGET_MODE int -isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint16_t *handlep) +isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep) { int i; @@ -874,28 +1383,30 @@ isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint16_t *handlep) return (-1); } isp->isp_tgtlist[i] = xs; - *handlep = i+1; + *handlep = (i+1) | 0x8000; return (0); } void * -isp_find_xs_tgt(ispsoftc_t *isp, uint16_t handle) +isp_find_xs_tgt(ispsoftc_t *isp, uint32_t handle) { - if (handle < 1 || handle > (uint16_t) isp->isp_maxcmds) { + if (handle == 0 || (handle & 0x8000) == 0 || + (handle & 0x7fff) > isp->isp_maxcmds) { + isp_prt(isp, ISP_LOGERR, "bad handle in isp_find_xs_tgt"); return (NULL); } else { - return (isp->isp_tgtlist[handle - 1]); + return (isp->isp_tgtlist[(handle & 0x7fff) - 1]); } } -uint16_t +uint32_t isp_find_tgt_handle(ispsoftc_t *isp, void *xs) { int i; if (xs != NULL) { for (i = 0; i < isp->isp_maxcmds; i++) { if (isp->isp_tgtlist[i] == xs) { - return ((uint16_t) i+1); + return ((i+1) & 0x7fff); } } } @@ -903,489 +1414,758 @@ isp_find_tgt_handle(ispsoftc_t *isp, void *xs) } void -isp_destroy_tgt_handle(ispsoftc_t *isp, uint16_t handle) +isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle) { - if (handle > 0 && handle <= (uint16_t) isp->isp_maxcmds) { - isp->isp_tgtlist[handle - 1] = NULL; + if (handle == 0 || (handle & 0x8000) == 0 || + (handle & 0x7fff) > isp->isp_maxcmds) { + isp_prt(isp, ISP_LOGERR, + "bad handle in isp_destroy_tgt_handle"); + } else { + isp->isp_tgtlist[(handle & 0x7fff) - 1] = NULL; } } + void -isp_put_atio(ispsoftc_t *isp, at_entry_t *atsrc, at_entry_t *atdst) +isp_put_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXPUT_16(isp, atsrc->at_reserved, &atdst->at_reserved); - ISP_IOXPUT_16(isp, atsrc->at_handle, &atdst->at_handle); + isp_put_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXPUT_16(isp, src->at_reserved, &dst->at_reserved); + ISP_IOXPUT_16(isp, src->at_handle, &dst->at_handle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_iid); - ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_lun); - ISP_IOXPUT_8(isp, atsrc->at_cdblen, &atdst->at_tgt); - ISP_IOXPUT_8(isp, atsrc->at_tgt, &atdst->at_cdblen); - ISP_IOXPUT_8(isp, atsrc->at_status, &atdst->at_scsi_status); - ISP_IOXPUT_8(isp, atsrc->at_scsi_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_tag_val, &atdst->at_tag_type); - ISP_IOXPUT_8(isp, atsrc->at_tag_type, &atdst->at_tag_val); + ISP_IOXPUT_8(isp, src->at_lun, &dst->at_iid); + ISP_IOXPUT_8(isp, src->at_iid, &dst->at_lun); + ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_tgt); + ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_cdblen); + ISP_IOXPUT_8(isp, src->at_status, &dst->at_scsi_status); + ISP_IOXPUT_8(isp, src->at_scsi_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_type); + ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_val); } else { - ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_lun); - ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_iid); - ISP_IOXPUT_8(isp, atsrc->at_cdblen, &atdst->at_cdblen); - ISP_IOXPUT_8(isp, atsrc->at_tgt, &atdst->at_tgt); - ISP_IOXPUT_8(isp, atsrc->at_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_scsi_status, - &atdst->at_scsi_status); - ISP_IOXPUT_8(isp, atsrc->at_tag_val, &atdst->at_tag_val); - ISP_IOXPUT_8(isp, atsrc->at_tag_type, &atdst->at_tag_type); - } - ISP_IOXPUT_32(isp, atsrc->at_flags, &atdst->at_flags); + ISP_IOXPUT_8(isp, src->at_lun, &dst->at_lun); + ISP_IOXPUT_8(isp, src->at_iid, &dst->at_iid); + ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_cdblen); + ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_tgt); + ISP_IOXPUT_8(isp, src->at_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_scsi_status, + &dst->at_scsi_status); + ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_val); + ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_type); + } + ISP_IOXPUT_32(isp, src->at_flags, &dst->at_flags); for (i = 0; i < ATIO_CDBLEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]); + ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_sense[i], &atdst->at_sense[i]); + ISP_IOXPUT_8(isp, src->at_sense[i], &dst->at_sense[i]); } } void -isp_get_atio(ispsoftc_t *isp, at_entry_t *atsrc, at_entry_t *atdst) +isp_get_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXGET_16(isp, &atsrc->at_reserved, atdst->at_reserved); - ISP_IOXGET_16(isp, &atsrc->at_handle, atdst->at_handle); + isp_get_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXGET_16(isp, &src->at_reserved, dst->at_reserved); + ISP_IOXGET_16(isp, &src->at_handle, dst->at_handle); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_iid); - ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_lun); - ISP_IOXGET_8(isp, &atsrc->at_cdblen, atdst->at_tgt); - ISP_IOXGET_8(isp, &atsrc->at_tgt, atdst->at_cdblen); - ISP_IOXGET_8(isp, &atsrc->at_status, atdst->at_scsi_status); - ISP_IOXGET_8(isp, &atsrc->at_scsi_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_tag_val, atdst->at_tag_type); - ISP_IOXGET_8(isp, &atsrc->at_tag_type, atdst->at_tag_val); + ISP_IOXGET_8(isp, &src->at_lun, dst->at_iid); + ISP_IOXGET_8(isp, &src->at_iid, dst->at_lun); + ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_tgt); + ISP_IOXGET_8(isp, &src->at_tgt, dst->at_cdblen); + ISP_IOXGET_8(isp, &src->at_status, dst->at_scsi_status); + ISP_IOXGET_8(isp, &src->at_scsi_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_type); + ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_val); } else { - ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_lun); - ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_iid); - ISP_IOXGET_8(isp, &atsrc->at_cdblen, atdst->at_cdblen); - ISP_IOXGET_8(isp, &atsrc->at_tgt, atdst->at_tgt); - ISP_IOXGET_8(isp, &atsrc->at_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_scsi_status, - atdst->at_scsi_status); - ISP_IOXGET_8(isp, &atsrc->at_tag_val, atdst->at_tag_val); - ISP_IOXGET_8(isp, &atsrc->at_tag_type, atdst->at_tag_type); - } - ISP_IOXGET_32(isp, &atsrc->at_flags, atdst->at_flags); + ISP_IOXGET_8(isp, &src->at_lun, dst->at_lun); + ISP_IOXGET_8(isp, &src->at_iid, dst->at_iid); + ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_cdblen); + ISP_IOXGET_8(isp, &src->at_tgt, dst->at_tgt); + ISP_IOXGET_8(isp, &src->at_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_scsi_status, + dst->at_scsi_status); + ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_val); + ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_type); + } + ISP_IOXGET_32(isp, &src->at_flags, dst->at_flags); for (i = 0; i < ATIO_CDBLEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]); + ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_sense[i], atdst->at_sense[i]); + ISP_IOXGET_8(isp, &src->at_sense[i], dst->at_sense[i]); } } void -isp_put_atio2(ispsoftc_t *isp, at2_entry_t *atsrc, at2_entry_t *atdst) +isp_put_atio2(ispsoftc_t *isp, at2_entry_t *src, at2_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXPUT_32(isp, atsrc->at_reserved, &atdst->at_reserved); - ISP_IOXPUT_8(isp, atsrc->at_lun, &atdst->at_lun); - ISP_IOXPUT_8(isp, atsrc->at_iid, &atdst->at_iid); - ISP_IOXPUT_16(isp, atsrc->at_rxid, &atdst->at_rxid); - ISP_IOXPUT_16(isp, atsrc->at_flags, &atdst->at_flags); - ISP_IOXPUT_16(isp, atsrc->at_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_crn, &atdst->at_crn); - ISP_IOXPUT_8(isp, atsrc->at_taskcodes, &atdst->at_taskcodes); - ISP_IOXPUT_8(isp, atsrc->at_taskflags, &atdst->at_taskflags); - ISP_IOXPUT_8(isp, atsrc->at_execodes, &atdst->at_execodes); + isp_put_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXPUT_32(isp, src->at_reserved, &dst->at_reserved); + ISP_IOXPUT_8(isp, src->at_lun, &dst->at_lun); + ISP_IOXPUT_8(isp, src->at_iid, &dst->at_iid); + ISP_IOXPUT_16(isp, src->at_rxid, &dst->at_rxid); + ISP_IOXPUT_16(isp, src->at_flags, &dst->at_flags); + ISP_IOXPUT_16(isp, src->at_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_crn, &dst->at_crn); + ISP_IOXPUT_8(isp, src->at_taskcodes, &dst->at_taskcodes); + ISP_IOXPUT_8(isp, src->at_taskflags, &dst->at_taskflags); + ISP_IOXPUT_8(isp, src->at_execodes, &dst->at_execodes); for (i = 0; i < ATIO2_CDBLEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]); + ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]); } - ISP_IOXPUT_32(isp, atsrc->at_datalen, &atdst->at_datalen); - ISP_IOXPUT_16(isp, atsrc->at_scclun, &atdst->at_scclun); + ISP_IOXPUT_32(isp, src->at_datalen, &dst->at_datalen); + ISP_IOXPUT_16(isp, src->at_scclun, &dst->at_scclun); for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, atsrc->at_wwpn[i], &atdst->at_wwpn[i]); + ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->at_wwpn[i]); } for (i = 0; i < 6; i++) { - ISP_IOXPUT_16(isp, atsrc->at_reserved2[i], - &atdst->at_reserved2[i]); + ISP_IOXPUT_16(isp, src->at_reserved2[i], + &dst->at_reserved2[i]); } - ISP_IOXPUT_16(isp, atsrc->at_oxid, &atdst->at_oxid); + ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid); } void -isp_put_atio2e(ispsoftc_t *isp, at2e_entry_t *atsrc, at2e_entry_t *atdst) +isp_put_atio2e(ispsoftc_t *isp, at2e_entry_t *src, at2e_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXPUT_32(isp, atsrc->at_reserved, &atdst->at_reserved); - ISP_IOXPUT_16(isp, atsrc->at_iid, &atdst->at_iid); - ISP_IOXPUT_16(isp, atsrc->at_rxid, &atdst->at_rxid); - ISP_IOXPUT_16(isp, atsrc->at_flags, &atdst->at_flags); - ISP_IOXPUT_16(isp, atsrc->at_status, &atdst->at_status); - ISP_IOXPUT_8(isp, atsrc->at_crn, &atdst->at_crn); - ISP_IOXPUT_8(isp, atsrc->at_taskcodes, &atdst->at_taskcodes); - ISP_IOXPUT_8(isp, atsrc->at_taskflags, &atdst->at_taskflags); - ISP_IOXPUT_8(isp, atsrc->at_execodes, &atdst->at_execodes); + isp_put_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXPUT_32(isp, src->at_reserved, &dst->at_reserved); + ISP_IOXPUT_16(isp, src->at_iid, &dst->at_iid); + ISP_IOXPUT_16(isp, src->at_rxid, &dst->at_rxid); + ISP_IOXPUT_16(isp, src->at_flags, &dst->at_flags); + ISP_IOXPUT_16(isp, src->at_status, &dst->at_status); + ISP_IOXPUT_8(isp, src->at_crn, &dst->at_crn); + ISP_IOXPUT_8(isp, src->at_taskcodes, &dst->at_taskcodes); + ISP_IOXPUT_8(isp, src->at_taskflags, &dst->at_taskflags); + ISP_IOXPUT_8(isp, src->at_execodes, &dst->at_execodes); for (i = 0; i < ATIO2_CDBLEN; i++) { - ISP_IOXPUT_8(isp, atsrc->at_cdb[i], &atdst->at_cdb[i]); + ISP_IOXPUT_8(isp, src->at_cdb[i], &dst->at_cdb[i]); } - ISP_IOXPUT_32(isp, atsrc->at_datalen, &atdst->at_datalen); - ISP_IOXPUT_16(isp, atsrc->at_scclun, &atdst->at_scclun); + ISP_IOXPUT_32(isp, src->at_datalen, &dst->at_datalen); + ISP_IOXPUT_16(isp, src->at_scclun, &dst->at_scclun); for (i = 0; i < 4; i++) { - ISP_IOXPUT_16(isp, atsrc->at_wwpn[i], &atdst->at_wwpn[i]); + ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->at_wwpn[i]); } for (i = 0; i < 6; i++) { - ISP_IOXPUT_16(isp, atsrc->at_reserved2[i], - &atdst->at_reserved2[i]); + ISP_IOXPUT_16(isp, src->at_reserved2[i], + &dst->at_reserved2[i]); } - ISP_IOXPUT_16(isp, atsrc->at_oxid, &atdst->at_oxid); + ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid); } void -isp_get_atio2(ispsoftc_t *isp, at2_entry_t *atsrc, at2_entry_t *atdst) +isp_get_atio2(ispsoftc_t *isp, at2_entry_t *src, at2_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXGET_32(isp, &atsrc->at_reserved, atdst->at_reserved); - ISP_IOXGET_8(isp, &atsrc->at_lun, atdst->at_lun); - ISP_IOXGET_8(isp, &atsrc->at_iid, atdst->at_iid); - ISP_IOXGET_16(isp, &atsrc->at_rxid, atdst->at_rxid); - ISP_IOXGET_16(isp, &atsrc->at_flags, atdst->at_flags); - ISP_IOXGET_16(isp, &atsrc->at_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_crn, atdst->at_crn); - ISP_IOXGET_8(isp, &atsrc->at_taskcodes, atdst->at_taskcodes); - ISP_IOXGET_8(isp, &atsrc->at_taskflags, atdst->at_taskflags); - ISP_IOXGET_8(isp, &atsrc->at_execodes, atdst->at_execodes); + isp_get_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXGET_32(isp, &src->at_reserved, dst->at_reserved); + ISP_IOXGET_8(isp, &src->at_lun, dst->at_lun); + ISP_IOXGET_8(isp, &src->at_iid, dst->at_iid); + ISP_IOXGET_16(isp, &src->at_rxid, dst->at_rxid); + ISP_IOXGET_16(isp, &src->at_flags, dst->at_flags); + ISP_IOXGET_16(isp, &src->at_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_crn, dst->at_crn); + ISP_IOXGET_8(isp, &src->at_taskcodes, dst->at_taskcodes); + ISP_IOXGET_8(isp, &src->at_taskflags, dst->at_taskflags); + ISP_IOXGET_8(isp, &src->at_execodes, dst->at_execodes); for (i = 0; i < ATIO2_CDBLEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]); + ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]); } - ISP_IOXGET_32(isp, &atsrc->at_datalen, atdst->at_datalen); - ISP_IOXGET_16(isp, &atsrc->at_scclun, atdst->at_scclun); + ISP_IOXGET_32(isp, &src->at_datalen, dst->at_datalen); + ISP_IOXGET_16(isp, &src->at_scclun, dst->at_scclun); for (i = 0; i < 4; i++) { - ISP_IOXGET_16(isp, &atsrc->at_wwpn[i], atdst->at_wwpn[i]); + ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->at_wwpn[i]); } for (i = 0; i < 6; i++) { - ISP_IOXGET_16(isp, &atsrc->at_reserved2[i], - atdst->at_reserved2[i]); + ISP_IOXGET_16(isp, &src->at_reserved2[i], + dst->at_reserved2[i]); } - ISP_IOXGET_16(isp, &atsrc->at_oxid, atdst->at_oxid); + ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid); } void -isp_get_atio2e(ispsoftc_t *isp, at2e_entry_t *atsrc, at2e_entry_t *atdst) +isp_get_atio2e(ispsoftc_t *isp, at2e_entry_t *src, at2e_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &atsrc->at_header, &atdst->at_header); - ISP_IOXGET_32(isp, &atsrc->at_reserved, atdst->at_reserved); - ISP_IOXGET_16(isp, &atsrc->at_iid, atdst->at_iid); - ISP_IOXGET_16(isp, &atsrc->at_rxid, atdst->at_rxid); - ISP_IOXGET_16(isp, &atsrc->at_flags, atdst->at_flags); - ISP_IOXGET_16(isp, &atsrc->at_status, atdst->at_status); - ISP_IOXGET_8(isp, &atsrc->at_crn, atdst->at_crn); - ISP_IOXGET_8(isp, &atsrc->at_taskcodes, atdst->at_taskcodes); - ISP_IOXGET_8(isp, &atsrc->at_taskflags, atdst->at_taskflags); - ISP_IOXGET_8(isp, &atsrc->at_execodes, atdst->at_execodes); + isp_get_hdr(isp, &src->at_header, &dst->at_header); + ISP_IOXGET_32(isp, &src->at_reserved, dst->at_reserved); + ISP_IOXGET_16(isp, &src->at_iid, dst->at_iid); + ISP_IOXGET_16(isp, &src->at_rxid, dst->at_rxid); + ISP_IOXGET_16(isp, &src->at_flags, dst->at_flags); + ISP_IOXGET_16(isp, &src->at_status, dst->at_status); + ISP_IOXGET_8(isp, &src->at_crn, dst->at_crn); + ISP_IOXGET_8(isp, &src->at_taskcodes, dst->at_taskcodes); + ISP_IOXGET_8(isp, &src->at_taskflags, dst->at_taskflags); + ISP_IOXGET_8(isp, &src->at_execodes, dst->at_execodes); for (i = 0; i < ATIO2_CDBLEN; i++) { - ISP_IOXGET_8(isp, &atsrc->at_cdb[i], atdst->at_cdb[i]); + ISP_IOXGET_8(isp, &src->at_cdb[i], dst->at_cdb[i]); } - ISP_IOXGET_32(isp, &atsrc->at_datalen, atdst->at_datalen); - ISP_IOXGET_16(isp, &atsrc->at_scclun, atdst->at_scclun); + ISP_IOXGET_32(isp, &src->at_datalen, dst->at_datalen); + ISP_IOXGET_16(isp, &src->at_scclun, dst->at_scclun); for (i = 0; i < 4; i++) { - ISP_IOXGET_16(isp, &atsrc->at_wwpn[i], atdst->at_wwpn[i]); + ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->at_wwpn[i]); } for (i = 0; i < 6; i++) { - ISP_IOXGET_16(isp, &atsrc->at_reserved2[i], - atdst->at_reserved2[i]); + ISP_IOXGET_16(isp, &src->at_reserved2[i], + dst->at_reserved2[i]); } - ISP_IOXGET_16(isp, &atsrc->at_oxid, atdst->at_oxid); + ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid); } void -isp_put_ctio(ispsoftc_t *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst) +isp_get_atio7(ispsoftc_t *isp, at7_entry_t *src, at7_entry_t *dst) +{ + ISP_IOXGET_8(isp, &src->at_type, dst->at_type); + ISP_IOXGET_8(isp, &src->at_count, dst->at_count); + ISP_IOXGET_16(isp, &src->at_ta_len, dst->at_ta_len); + ISP_IOXGET_32(isp, &src->at_rxid, dst->at_rxid); + isp_get_fc_hdr(isp, &src->at_hdr, &dst->at_hdr); + isp_get_fcp_cmnd_iu(isp, &src->at_cmnd, &dst->at_cmnd); +} + +void +isp_put_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXPUT_16(isp, ctsrc->ct_reserved, &ctdst->ct_reserved); - ISP_IOXPUT_16(isp, ctsrc->ct_fwhandle, &ctdst->ct_fwhandle); + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_16(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_16(isp, src->ct_fwhandle, &dst->ct_fwhandle); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_lun); - ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_iid); - ISP_IOXPUT_8(isp, ctsrc->ct_tgt, &ctdst->ct_reserved2); - ISP_IOXPUT_8(isp, ctsrc->ct_reserved2, &ctdst->ct_tgt); - ISP_IOXPUT_8(isp, ctsrc->ct_status, &ctdst->ct_scsi_status); - ISP_IOXPUT_8(isp, ctsrc->ct_scsi_status, &ctdst->ct_status); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_type, &ctdst->ct_tag_val); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_val, &ctdst->ct_tag_type); + ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_lun); + ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_iid); + ISP_IOXPUT_8(isp, src->ct_tgt, &dst->ct_reserved2); + ISP_IOXPUT_8(isp, src->ct_reserved2, &dst->ct_tgt); + ISP_IOXPUT_8(isp, src->ct_status, &dst->ct_scsi_status); + ISP_IOXPUT_8(isp, src->ct_scsi_status, &dst->ct_status); + ISP_IOXPUT_8(isp, src->ct_tag_type, &dst->ct_tag_val); + ISP_IOXPUT_8(isp, src->ct_tag_val, &dst->ct_tag_type); } else { - ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_iid); - ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_lun); - ISP_IOXPUT_8(isp, ctsrc->ct_tgt, &ctdst->ct_tgt); - ISP_IOXPUT_8(isp, ctsrc->ct_reserved2, &ctdst->ct_reserved2); - ISP_IOXPUT_8(isp, ctsrc->ct_scsi_status, - &ctdst->ct_scsi_status); - ISP_IOXPUT_8(isp, ctsrc->ct_status, &ctdst->ct_status); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_type, &ctdst->ct_tag_type); - ISP_IOXPUT_8(isp, ctsrc->ct_tag_val, &ctdst->ct_tag_val); - } - ISP_IOXPUT_32(isp, ctsrc->ct_flags, &ctdst->ct_flags); - ISP_IOXPUT_32(isp, ctsrc->ct_xfrlen, &ctdst->ct_xfrlen); - ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid); - ISP_IOXPUT_16(isp, ctsrc->ct_timeout, &ctdst->ct_timeout); - ISP_IOXPUT_16(isp, ctsrc->ct_seg_count, &ctdst->ct_seg_count); + ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_iid); + ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_lun); + ISP_IOXPUT_8(isp, src->ct_tgt, &dst->ct_tgt); + ISP_IOXPUT_8(isp, src->ct_reserved2, &dst->ct_reserved2); + ISP_IOXPUT_8(isp, src->ct_scsi_status, + &dst->ct_scsi_status); + ISP_IOXPUT_8(isp, src->ct_status, &dst->ct_status); + ISP_IOXPUT_8(isp, src->ct_tag_type, &dst->ct_tag_type); + ISP_IOXPUT_8(isp, src->ct_tag_val, &dst->ct_tag_val); + } + ISP_IOXPUT_32(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_32(isp, src->ct_xfrlen, &dst->ct_xfrlen); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); for (i = 0; i < ISP_RQDSEG; i++) { - ISP_IOXPUT_32(isp, ctsrc->ct_dataseg[i].ds_base, - &ctdst->ct_dataseg[i].ds_base); - ISP_IOXPUT_32(isp, ctsrc->ct_dataseg[i].ds_count, - &ctdst->ct_dataseg[i].ds_count); + ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_base, + &dst->ct_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_count, + &dst->ct_dataseg[i].ds_count); } } void -isp_get_ctio(ispsoftc_t *isp, ct_entry_t *ctsrc, ct_entry_t *ctdst) +isp_get_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXGET_16(isp, &ctsrc->ct_reserved, ctdst->ct_reserved); - ISP_IOXGET_16(isp, &ctsrc->ct_fwhandle, ctdst->ct_fwhandle); + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_16(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_16(isp, &src->ct_fwhandle, dst->ct_fwhandle); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_iid); - ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_lun); - ISP_IOXGET_8(isp, &ctsrc->ct_reserved2, ctdst->ct_tgt); - ISP_IOXGET_8(isp, &ctsrc->ct_tgt, ctdst->ct_reserved2); - ISP_IOXGET_8(isp, &ctsrc->ct_status, ctdst->ct_scsi_status); - ISP_IOXGET_8(isp, &ctsrc->ct_scsi_status, ctdst->ct_status); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_val, ctdst->ct_tag_type); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_type, ctdst->ct_tag_val); + ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_iid); + ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_lun); + ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_tgt); + ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_reserved2); + ISP_IOXGET_8(isp, &src->ct_status, dst->ct_scsi_status); + ISP_IOXGET_8(isp, &src->ct_scsi_status, dst->ct_status); + ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_type); + ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_val); } else { - ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_lun); - ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_iid); - ISP_IOXGET_8(isp, &ctsrc->ct_reserved2, ctdst->ct_reserved2); - ISP_IOXGET_8(isp, &ctsrc->ct_tgt, ctdst->ct_tgt); - ISP_IOXGET_8(isp, &ctsrc->ct_status, ctdst->ct_status); - ISP_IOXGET_8(isp, &ctsrc->ct_scsi_status, - ctdst->ct_scsi_status); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_val, ctdst->ct_tag_val); - ISP_IOXGET_8(isp, &ctsrc->ct_tag_type, ctdst->ct_tag_type); - } - ISP_IOXGET_32(isp, &ctsrc->ct_flags, ctdst->ct_flags); - ISP_IOXGET_32(isp, &ctsrc->ct_xfrlen, ctdst->ct_xfrlen); - ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid); - ISP_IOXGET_16(isp, &ctsrc->ct_timeout, ctdst->ct_timeout); - ISP_IOXGET_16(isp, &ctsrc->ct_seg_count, ctdst->ct_seg_count); + ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_lun); + ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_iid); + ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_reserved2); + ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_tgt); + ISP_IOXGET_8(isp, &src->ct_status, dst->ct_status); + ISP_IOXGET_8(isp, &src->ct_scsi_status, + dst->ct_scsi_status); + ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_val); + ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_type); + } + ISP_IOXGET_32(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_32(isp, &src->ct_xfrlen, dst->ct_xfrlen); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); for (i = 0; i < ISP_RQDSEG; i++) { ISP_IOXGET_32(isp, - &ctsrc->ct_dataseg[i].ds_base, - ctdst->ct_dataseg[i].ds_base); + &src->ct_dataseg[i].ds_base, + dst->ct_dataseg[i].ds_base); ISP_IOXGET_32(isp, - &ctsrc->ct_dataseg[i].ds_count, - ctdst->ct_dataseg[i].ds_count); - } -} - -void -isp_put_ctio2(ispsoftc_t *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) -{ - int i; - isp_copy_out_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXPUT_16(isp, ctsrc->ct_reserved, &ctdst->ct_reserved); - ISP_IOXPUT_16(isp, ctsrc->ct_fwhandle, &ctdst->ct_fwhandle); - ISP_IOXPUT_8(isp, ctsrc->ct_lun, &ctdst->ct_lun); - ISP_IOXPUT_8(isp, ctsrc->ct_iid, &ctdst->ct_iid); - ISP_IOXPUT_16(isp, ctsrc->ct_rxid, &ctdst->ct_rxid); - ISP_IOXPUT_16(isp, ctsrc->ct_flags, &ctdst->ct_flags); - ISP_IOXPUT_16(isp, ctsrc->ct_timeout, &ctdst->ct_timeout); - ISP_IOXPUT_16(isp, ctsrc->ct_seg_count, &ctdst->ct_seg_count); - ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid); - ISP_IOXPUT_32(isp, ctsrc->ct_reloff, &ctdst->ct_reloff); - if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { - ISP_IOXPUT_32(isp, ctsrc->rsp.m0._reserved, - &ctdst->rsp.m0._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m0._reserved2, - &ctdst->rsp.m0._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_scsi_status, - &ctdst->rsp.m0.ct_scsi_status); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_xfrlen, - &ctdst->rsp.m0.ct_xfrlen); - if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + &src->ct_dataseg[i].ds_count, + dst->ct_dataseg[i].ds_count); + } +} + +void +isp_put_ctio2(ispsoftc_t *isp, ct2_entry_t *src, ct2_entry_t *dst) +{ + int i; + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_8(isp, src->ct_lun, &dst->ct_lun); + ISP_IOXPUT_8(isp, src->ct_iid, &dst->ct_iid); + ISP_IOXPUT_16(isp, src->ct_rxid, &dst->ct_rxid); + ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff); + if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXPUT_32(isp, src->rsp.m0._reserved, + &dst->rsp.m0._reserved); + ISP_IOXPUT_16(isp, src->rsp.m0._reserved2, + &dst->rsp.m0._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status, + &dst->rsp.m0.ct_scsi_status); + ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, + &dst->rsp.m0.ct_xfrlen); + if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { for (i = 0; i < ISP_RQDSEG_T2; i++) { ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg[i].ds_base, - &ctdst->rsp.m0.ct_dataseg[i].ds_base); + src->rsp.m0.u.ct_dataseg[i].ds_base, + &dst->rsp.m0.u.ct_dataseg[i].ds_base); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg[i].ds_count, - &ctdst->rsp.m0.ct_dataseg[i].ds_count); + src->rsp.m0.u.ct_dataseg[i].ds_count, + &dst->rsp.m0.u.ct_dataseg[i].ds_count); } - } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { for (i = 0; i < ISP_RQDSEG_T3; i++) { ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_base, - &ctdst->rsp.m0.ct_dataseg64[i].ds_base); + src->rsp.m0.u.ct_dataseg64[i].ds_base, + &dst->rsp.m0.u.ct_dataseg64[i].ds_base); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_basehi, - &ctdst->rsp.m0.ct_dataseg64[i].ds_basehi); + src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_count, - &ctdst->rsp.m0.ct_dataseg64[i].ds_count); + src->rsp.m0.u.ct_dataseg64[i].ds_count, + &dst->rsp.m0.u.ct_dataseg64[i].ds_count); } - } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { - ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_dslist.ds_type, - &ctdst->rsp.m0.ct_dslist.ds_type); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_segment, - &ctdst->rsp.m0.ct_dslist.ds_segment); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_base, - &ctdst->rsp.m0.ct_dslist.ds_base); + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type, + &dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment, + &dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base, + &dst->rsp.m0.u.ct_dslist.ds_base); } - } else if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { - ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved, - &ctdst->rsp.m1._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved2, - &ctdst->rsp.m1._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_senselen, - &ctdst->rsp.m1.ct_senselen); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_scsi_status, - &ctdst->rsp.m1.ct_scsi_status); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_resplen, - &ctdst->rsp.m1.ct_resplen); + } else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXPUT_16(isp, src->rsp.m1._reserved, + &dst->rsp.m1._reserved); + ISP_IOXPUT_16(isp, src->rsp.m1._reserved2, + &dst->rsp.m1._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen, + &dst->rsp.m1.ct_senselen); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status, + &dst->rsp.m1.ct_scsi_status); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, + &dst->rsp.m1.ct_resplen); for (i = 0; i < MAXRESPLEN; i++) { - ISP_IOXPUT_8(isp, ctsrc->rsp.m1.ct_resp[i], - &ctdst->rsp.m1.ct_resp[i]); + ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], + &dst->rsp.m1.ct_resp[i]); } } else { - ISP_IOXPUT_32(isp, ctsrc->rsp.m2._reserved, - &ctdst->rsp.m2._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved2, - &ctdst->rsp.m2._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved3, - &ctdst->rsp.m2._reserved3); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_datalen, - &ctdst->rsp.m2.ct_datalen); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_base, - &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_base); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_count, - &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_count); - } -} - -void -isp_put_ctio2e(ispsoftc_t *isp, ct2e_entry_t *ctsrc, ct2e_entry_t *ctdst) -{ - int i; - isp_copy_out_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXPUT_16(isp, ctsrc->ct_reserved, &ctdst->ct_reserved); - ISP_IOXPUT_16(isp, ctsrc->ct_fwhandle, &ctdst->ct_fwhandle); - ISP_IOXPUT_16(isp, ctsrc->ct_iid, &ctdst->ct_iid); - ISP_IOXPUT_16(isp, ctsrc->ct_rxid, &ctdst->ct_rxid); - ISP_IOXPUT_16(isp, ctsrc->ct_flags, &ctdst->ct_flags); - ISP_IOXPUT_16(isp, ctsrc->ct_timeout, &ctdst->ct_timeout); - ISP_IOXPUT_16(isp, ctsrc->ct_seg_count, &ctdst->ct_seg_count); - ISP_IOXPUT_32(isp, ctsrc->ct_resid, &ctdst->ct_resid); - ISP_IOXPUT_32(isp, ctsrc->ct_reloff, &ctdst->ct_reloff); - if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { - ISP_IOXPUT_32(isp, ctsrc->rsp.m0._reserved, - &ctdst->rsp.m0._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m0._reserved2, - &ctdst->rsp.m0._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_scsi_status, - &ctdst->rsp.m0.ct_scsi_status); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_xfrlen, - &ctdst->rsp.m0.ct_xfrlen); - if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + ISP_IOXPUT_32(isp, src->rsp.m2._reserved, + &dst->rsp.m2._reserved); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved2, + &dst->rsp.m2._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved3, + &dst->rsp.m2._reserved3); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, + &dst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + +void +isp_put_ctio2e(ispsoftc_t *isp, ct2e_entry_t *src, ct2e_entry_t *dst) +{ + int i; + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_16(isp, src->ct_iid, &dst->ct_iid); + ISP_IOXPUT_16(isp, src->ct_rxid, &dst->ct_rxid); + ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff); + if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXPUT_32(isp, src->rsp.m0._reserved, + &dst->rsp.m0._reserved); + ISP_IOXPUT_16(isp, src->rsp.m0._reserved2, + &dst->rsp.m0._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status, + &dst->rsp.m0.ct_scsi_status); + ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, + &dst->rsp.m0.ct_xfrlen); + if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { for (i = 0; i < ISP_RQDSEG_T2; i++) { ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg[i].ds_base, - &ctdst->rsp.m0.ct_dataseg[i].ds_base); + src->rsp.m0.u.ct_dataseg[i].ds_base, + &dst->rsp.m0.u.ct_dataseg[i].ds_base); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg[i].ds_count, - &ctdst->rsp.m0.ct_dataseg[i].ds_count); + src->rsp.m0.u.ct_dataseg[i].ds_count, + &dst->rsp.m0.u.ct_dataseg[i].ds_count); } - } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { for (i = 0; i < ISP_RQDSEG_T3; i++) { ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_base, - &ctdst->rsp.m0.ct_dataseg64[i].ds_base); + src->rsp.m0.u.ct_dataseg64[i].ds_base, + &dst->rsp.m0.u.ct_dataseg64[i].ds_base); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_basehi, - &ctdst->rsp.m0.ct_dataseg64[i].ds_basehi); + src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); ISP_IOXPUT_32(isp, - ctsrc->rsp.m0.ct_dataseg64[i].ds_count, - &ctdst->rsp.m0.ct_dataseg64[i].ds_count); + src->rsp.m0.u.ct_dataseg64[i].ds_count, + &dst->rsp.m0.u.ct_dataseg64[i].ds_count); + } + } else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type, + &dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment, + &dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base, + &dst->rsp.m0.u.ct_dslist.ds_base); + } + } else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXPUT_16(isp, src->rsp.m1._reserved, + &dst->rsp.m1._reserved); + ISP_IOXPUT_16(isp, src->rsp.m1._reserved2, + &dst->rsp.m1._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen, + &dst->rsp.m1.ct_senselen); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status, + &dst->rsp.m1.ct_scsi_status); + ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, + &dst->rsp.m1.ct_resplen); + for (i = 0; i < MAXRESPLEN; i++) { + ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], + &dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXPUT_32(isp, src->rsp.m2._reserved, + &dst->rsp.m2._reserved); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved2, + &dst->rsp.m2._reserved2); + ISP_IOXPUT_16(isp, src->rsp.m2._reserved3, + &dst->rsp.m2._reserved3); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, + &dst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + +void +isp_put_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXPUT_32(isp, src->ct_syshandle, &dst->ct_syshandle); + ISP_IOXPUT_16(isp, src->ct_nphdl, &dst->ct_nphdl); + ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout); + ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count); + ISP_IOXPUT_8(isp, src->ct_vpindex, &dst->ct_vpindex); + ISP_IOXPUT_8(isp, src->ct_xflags, &dst->ct_xflags); + ISP_IOXPUT_16(isp, src->ct_iid_lo, &dst->ct_iid_lo); + ISP_IOXPUT_8(isp, src->ct_iid_hi, &dst->ct_iid_hi); + ISP_IOXPUT_8(isp, src->ct_reserved, &dst->ct_reserved); + ISP_IOXPUT_32(isp, src->ct_rxid, &dst->ct_rxid); + ISP_IOXPUT_16(isp, src->ct_senselen, &dst->ct_senselen); + ISP_IOXPUT_16(isp, src->ct_flags, &dst->ct_flags); + ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid); + ISP_IOXPUT_16(isp, src->ct_oxid, &dst->ct_oxid); + ISP_IOXPUT_16(isp, src->ct_scsi_status, &dst->ct_scsi_status); + if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) { + ISP_IOXPUT_32(isp, src->rsp.m0.reloff, &dst->rsp.m0.reloff); + ISP_IOXPUT_32(isp, src->rsp.m0.reserved0, + &dst->rsp.m0.reserved0); + ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, + &dst->rsp.m0.ct_xfrlen); + ISP_IOXPUT_32(isp, src->rsp.m0.reserved1, + &dst->rsp.m0.reserved1); + ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_base, + &dst->rsp.m0.ds.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_basehi, + &dst->rsp.m0.ds.ds_basehi); + ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_count, + &dst->rsp.m0.ds.ds_count); + } else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) { + ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, + &dst->rsp.m1.ct_resplen); + ISP_IOXPUT_16(isp, src->rsp.m1.reserved, &dst->rsp.m1.reserved); + for (i = 0; i < MAXRESPLEN_24XX; i++) { + ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], + &dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXPUT_32(isp, src->rsp.m2.reserved0, + &dst->rsp.m2.reserved0); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, + &dst->rsp.m2.ct_datalen); + ISP_IOXPUT_32(isp, src->rsp.m2.reserved1, + &dst->rsp.m2.reserved1); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi); + ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } +} + + +void +isp_get_ctio2(ispsoftc_t *isp, ct2_entry_t *src, ct2_entry_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_8(isp, &src->ct_lun, dst->ct_lun); + ISP_IOXGET_8(isp, &src->ct_iid, dst->ct_iid); + ISP_IOXGET_16(isp, &src->ct_rxid, dst->ct_rxid); + ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_16(isp, &src->ct_status, dst->ct_status); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); + ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXGET_32(isp, &src->rsp.m0._reserved, + dst->rsp.m0._reserved); + ISP_IOXGET_16(isp, &src->rsp.m0._reserved2, + dst->rsp.m0._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status, + dst->rsp.m0.ct_scsi_status); + ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, + dst->rsp.m0.ct_xfrlen); + if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_base, + dst->rsp.m0.u.ct_dataseg[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_count, + dst->rsp.m0.u.ct_dataseg[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_base, + dst->rsp.m0.u.ct_dataseg64[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_count, + dst->rsp.m0.u.ct_dataseg64[i].ds_count); } - } else if (ctsrc->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { - ISP_IOXPUT_16(isp, ctsrc->rsp.m0.ct_dslist.ds_type, - &ctdst->rsp.m0.ct_dslist.ds_type); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_segment, - &ctdst->rsp.m0.ct_dslist.ds_segment); - ISP_IOXPUT_32(isp, ctsrc->rsp.m0.ct_dslist.ds_base, - &ctdst->rsp.m0.ct_dslist.ds_base); + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type, + dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment, + dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base, + dst->rsp.m0.u.ct_dslist.ds_base); } - } else if ((ctsrc->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { - ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved, - &ctdst->rsp.m1._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1._reserved2, - &ctdst->rsp.m1._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_senselen, - &ctdst->rsp.m1.ct_senselen); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_scsi_status, - &ctdst->rsp.m1.ct_scsi_status); - ISP_IOXPUT_16(isp, ctsrc->rsp.m1.ct_resplen, - &ctdst->rsp.m1.ct_resplen); + } else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXGET_16(isp, &src->rsp.m1._reserved, + dst->rsp.m1._reserved); + ISP_IOXGET_16(isp, &src->rsp.m1._reserved2, + dst->rsp.m1._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen, + dst->rsp.m1.ct_senselen); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status, + dst->rsp.m1.ct_scsi_status); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, + dst->rsp.m1.ct_resplen); for (i = 0; i < MAXRESPLEN; i++) { - ISP_IOXPUT_8(isp, ctsrc->rsp.m1.ct_resp[i], - &ctdst->rsp.m1.ct_resp[i]); + ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], + dst->rsp.m1.ct_resp[i]); } } else { - ISP_IOXPUT_32(isp, ctsrc->rsp.m2._reserved, - &ctdst->rsp.m2._reserved); - ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved2, - &ctdst->rsp.m2._reserved2); - ISP_IOXPUT_16(isp, ctsrc->rsp.m2._reserved3, - &ctdst->rsp.m2._reserved3); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_datalen, - &ctdst->rsp.m2.ct_datalen); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_base, - &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_base); - ISP_IOXPUT_32(isp, ctsrc->rsp.m2.ct_fcp_rsp_iudata.ds_count, - &ctdst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + ISP_IOXGET_32(isp, &src->rsp.m2._reserved, + dst->rsp.m2._reserved); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved2, + dst->rsp.m2._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved3, + dst->rsp.m2._reserved3); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, + dst->rsp.m2.ct_datalen); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); } } void -isp_get_ctio2(ispsoftc_t *isp, ct2_entry_t *ctsrc, ct2_entry_t *ctdst) +isp_get_ctio2e(ispsoftc_t *isp, ct2e_entry_t *src, ct2e_entry_t *dst) { - isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXGET_16(isp, &ctsrc->ct_reserved, ctdst->ct_reserved); - ISP_IOXGET_16(isp, &ctsrc->ct_fwhandle, ctdst->ct_fwhandle); - ISP_IOXGET_8(isp, &ctsrc->ct_lun, ctdst->ct_lun); - ISP_IOXGET_8(isp, &ctsrc->ct_iid, ctdst->ct_iid); - ISP_IOXGET_16(isp, &ctsrc->ct_rxid, ctdst->ct_rxid); - ISP_IOXGET_16(isp, &ctsrc->ct_flags, ctdst->ct_flags); - ISP_IOXGET_16(isp, &ctsrc->ct_status, ctdst->ct_status); - ISP_IOXGET_16(isp, &ctsrc->ct_timeout, ctdst->ct_timeout); - ISP_IOXGET_16(isp, &ctsrc->ct_seg_count, ctdst->ct_seg_count); - ISP_IOXGET_32(isp, &ctsrc->ct_reloff, ctdst->ct_reloff); - ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid); + int i; + + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_16(isp, &src->ct_iid, dst->ct_iid); + ISP_IOXGET_16(isp, &src->ct_rxid, dst->ct_rxid); + ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_16(isp, &src->ct_status, dst->ct_status); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); + ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) { + ISP_IOXGET_32(isp, &src->rsp.m0._reserved, + dst->rsp.m0._reserved); + ISP_IOXGET_16(isp, &src->rsp.m0._reserved2, + dst->rsp.m0._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status, + dst->rsp.m0.ct_scsi_status); + ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, + dst->rsp.m0.ct_xfrlen); + if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) { + for (i = 0; i < ISP_RQDSEG_T2; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_base, + dst->rsp.m0.u.ct_dataseg[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg[i].ds_count, + dst->rsp.m0.u.ct_dataseg[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { + for (i = 0; i < ISP_RQDSEG_T3; i++) { + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_base, + dst->rsp.m0.u.ct_dataseg64[i].ds_base); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_basehi, + dst->rsp.m0.u.ct_dataseg64[i].ds_basehi); + ISP_IOXGET_32(isp, + &src->rsp.m0.u.ct_dataseg64[i].ds_count, + dst->rsp.m0.u.ct_dataseg64[i].ds_count); + } + } else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) { + ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type, + dst->rsp.m0.u.ct_dslist.ds_type); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment, + dst->rsp.m0.u.ct_dslist.ds_segment); + ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base, + dst->rsp.m0.u.ct_dslist.ds_base); + } + } else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) { + ISP_IOXGET_16(isp, &src->rsp.m1._reserved, + dst->rsp.m1._reserved); + ISP_IOXGET_16(isp, &src->rsp.m1._reserved2, + dst->rsp.m1._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen, + dst->rsp.m1.ct_senselen); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status, + dst->rsp.m1.ct_scsi_status); + ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, + dst->rsp.m1.ct_resplen); + for (i = 0; i < MAXRESPLEN; i++) { + ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], + dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXGET_32(isp, &src->rsp.m2._reserved, + dst->rsp.m2._reserved); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved2, + dst->rsp.m2._reserved2); + ISP_IOXGET_16(isp, &src->rsp.m2._reserved3, + dst->rsp.m2._reserved3); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, + dst->rsp.m2.ct_datalen); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } } void -isp_get_ctio2e(ispsoftc_t *isp, ct2e_entry_t *ctsrc, ct2e_entry_t *ctdst) +isp_get_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst) { - isp_copy_in_hdr(isp, &ctsrc->ct_header, &ctdst->ct_header); - ISP_IOXGET_16(isp, &ctsrc->ct_reserved, ctdst->ct_reserved); - ISP_IOXGET_16(isp, &ctsrc->ct_fwhandle, ctdst->ct_fwhandle); - ISP_IOXGET_16(isp, &ctsrc->ct_iid, ctdst->ct_iid); - ISP_IOXGET_16(isp, &ctsrc->ct_rxid, ctdst->ct_rxid); - ISP_IOXGET_16(isp, &ctsrc->ct_flags, ctdst->ct_flags); - ISP_IOXGET_16(isp, &ctsrc->ct_status, ctdst->ct_status); - ISP_IOXGET_16(isp, &ctsrc->ct_timeout, ctdst->ct_timeout); - ISP_IOXGET_16(isp, &ctsrc->ct_seg_count, ctdst->ct_seg_count); - ISP_IOXGET_32(isp, &ctsrc->ct_reloff, ctdst->ct_reloff); - ISP_IOXGET_32(isp, &ctsrc->ct_resid, ctdst->ct_resid); + int i; + + isp_get_hdr(isp, &src->ct_header, &dst->ct_header); + ISP_IOXGET_32(isp, &src->ct_syshandle, dst->ct_syshandle); + ISP_IOXGET_16(isp, &src->ct_nphdl, dst->ct_nphdl); + ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout); + ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count); + ISP_IOXGET_8(isp, &src->ct_vpindex, dst->ct_vpindex); + ISP_IOXGET_8(isp, &src->ct_xflags, dst->ct_xflags); + ISP_IOXGET_16(isp, &src->ct_iid_lo, dst->ct_iid_lo); + ISP_IOXGET_8(isp, &src->ct_iid_hi, dst->ct_iid_hi); + ISP_IOXGET_8(isp, &src->ct_reserved, dst->ct_reserved); + ISP_IOXGET_32(isp, &src->ct_rxid, dst->ct_rxid); + ISP_IOXGET_16(isp, &src->ct_senselen, dst->ct_senselen); + ISP_IOXGET_16(isp, &src->ct_flags, dst->ct_flags); + ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid); + ISP_IOXGET_16(isp, &src->ct_oxid, dst->ct_oxid); + ISP_IOXGET_16(isp, &src->ct_scsi_status, dst->ct_scsi_status); + if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) { + ISP_IOXGET_32(isp, &src->rsp.m0.reloff, dst->rsp.m0.reloff); + ISP_IOXGET_32(isp, &src->rsp.m0.reserved0, + dst->rsp.m0.reserved0); + ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, + dst->rsp.m0.ct_xfrlen); + ISP_IOXGET_32(isp, &src->rsp.m0.reserved1, + dst->rsp.m0.reserved1); + ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_base, + dst->rsp.m0.ds.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_basehi, + dst->rsp.m0.ds.ds_basehi); + ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_count, + dst->rsp.m0.ds.ds_count); + } else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) { + ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, + dst->rsp.m1.ct_resplen); + ISP_IOXGET_16(isp, &src->rsp.m1.reserved, dst->rsp.m1.reserved); + for (i = 0; i < MAXRESPLEN_24XX; i++) { + ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], + dst->rsp.m1.ct_resp[i]); + } + } else { + ISP_IOXGET_32(isp, &src->rsp.m2.reserved0, + dst->rsp.m2.reserved0); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, + dst->rsp.m2.ct_datalen); + ISP_IOXGET_32(isp, &src->rsp.m2.reserved1, + dst->rsp.m2.reserved1); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_base); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi); + ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, + dst->rsp.m2.ct_fcp_rsp_iudata.ds_count); + } } void isp_put_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst) { int i; - isp_copy_out_hdr(isp, &lesrc->le_header, &ledst->le_header); + isp_put_hdr(isp, &lesrc->le_header, &ledst->le_header); ISP_IOXPUT_32(isp, lesrc->le_reserved, &ledst->le_reserved); if (ISP_IS_SBUS(isp)) { ISP_IOXPUT_8(isp, lesrc->le_lun, &ledst->le_rsvd); @@ -1422,7 +2202,7 @@ void isp_get_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst) { int i; - isp_copy_in_hdr(isp, &lesrc->le_header, &ledst->le_header); + isp_get_hdr(isp, &lesrc->le_header, &ledst->le_header); ISP_IOXGET_32(isp, &lesrc->le_reserved, ledst->le_reserved); if (ISP_IS_SBUS(isp)) { ISP_IOXGET_8(isp, &lesrc->le_lun, ledst->le_rsvd); @@ -1456,270 +2236,557 @@ isp_get_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst) } void -isp_put_notify(ispsoftc_t *isp, in_entry_t *insrc, in_entry_t *indst) +isp_put_notify(ispsoftc_t *isp, in_entry_t *src, in_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved); + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_iid); - ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_lun); - ISP_IOXPUT_8(isp, insrc->in_reserved2, &indst->in_tgt); - ISP_IOXPUT_8(isp, insrc->in_tgt, &indst->in_reserved2); - ISP_IOXPUT_8(isp, insrc->in_status, &indst->in_rsvd2); - ISP_IOXPUT_8(isp, insrc->in_rsvd2, &indst->in_status); - ISP_IOXPUT_8(isp, insrc->in_tag_val, &indst->in_tag_type); - ISP_IOXPUT_8(isp, insrc->in_tag_type, &indst->in_tag_val); + ISP_IOXPUT_8(isp, src->in_lun, &dst->in_iid); + ISP_IOXPUT_8(isp, src->in_iid, &dst->in_lun); + ISP_IOXPUT_8(isp, src->in_reserved2, &dst->in_tgt); + ISP_IOXPUT_8(isp, src->in_tgt, &dst->in_reserved2); + ISP_IOXPUT_8(isp, src->in_status, &dst->in_rsvd2); + ISP_IOXPUT_8(isp, src->in_rsvd2, &dst->in_status); + ISP_IOXPUT_8(isp, src->in_tag_val, &dst->in_tag_type); + ISP_IOXPUT_8(isp, src->in_tag_type, &dst->in_tag_val); } else { - ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_lun); - ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_iid); - ISP_IOXPUT_8(isp, insrc->in_reserved2, &indst->in_reserved2); - ISP_IOXPUT_8(isp, insrc->in_tgt, &indst->in_tgt); - ISP_IOXPUT_8(isp, insrc->in_status, &indst->in_status); - ISP_IOXPUT_8(isp, insrc->in_rsvd2, &indst->in_rsvd2); - ISP_IOXPUT_8(isp, insrc->in_tag_val, &indst->in_tag_val); - ISP_IOXPUT_8(isp, insrc->in_tag_type, &indst->in_tag_type); - } - ISP_IOXPUT_32(isp, insrc->in_flags, &indst->in_flags); - ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid); + ISP_IOXPUT_8(isp, src->in_lun, &dst->in_lun); + ISP_IOXPUT_8(isp, src->in_iid, &dst->in_iid); + ISP_IOXPUT_8(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_8(isp, src->in_tgt, &dst->in_tgt); + ISP_IOXPUT_8(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_8(isp, src->in_rsvd2, &dst->in_rsvd2); + ISP_IOXPUT_8(isp, src->in_tag_val, &dst->in_tag_val); + ISP_IOXPUT_8(isp, src->in_tag_type, &dst->in_tag_type); + } + ISP_IOXPUT_32(isp, src->in_flags, &dst->in_flags); + ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid); for (i = 0; i < IN_MSGLEN; i++) { - ISP_IOXPUT_8(isp, insrc->in_msg[i], &indst->in_msg[i]); + ISP_IOXPUT_8(isp, src->in_msg[i], &dst->in_msg[i]); } for (i = 0; i < IN_RSVDLEN; i++) { - ISP_IOXPUT_8(isp, insrc->in_reserved3[i], - &indst->in_reserved3[i]); + ISP_IOXPUT_8(isp, src->in_reserved3[i], + &dst->in_reserved3[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXPUT_8(isp, insrc->in_sense[i], - &indst->in_sense[i]); + ISP_IOXPUT_8(isp, src->in_sense[i], + &dst->in_sense[i]); } } void -isp_get_notify(ispsoftc_t *isp, in_entry_t *insrc, in_entry_t *indst) +isp_get_notify(ispsoftc_t *isp, in_entry_t *src, in_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved); + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_iid); - ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_lun); - ISP_IOXGET_8(isp, &insrc->in_reserved2, indst->in_tgt); - ISP_IOXGET_8(isp, &insrc->in_tgt, indst->in_reserved2); - ISP_IOXGET_8(isp, &insrc->in_status, indst->in_rsvd2); - ISP_IOXGET_8(isp, &insrc->in_rsvd2, indst->in_status); - ISP_IOXGET_8(isp, &insrc->in_tag_val, indst->in_tag_type); - ISP_IOXGET_8(isp, &insrc->in_tag_type, indst->in_tag_val); + ISP_IOXGET_8(isp, &src->in_lun, dst->in_iid); + ISP_IOXGET_8(isp, &src->in_iid, dst->in_lun); + ISP_IOXGET_8(isp, &src->in_reserved2, dst->in_tgt); + ISP_IOXGET_8(isp, &src->in_tgt, dst->in_reserved2); + ISP_IOXGET_8(isp, &src->in_status, dst->in_rsvd2); + ISP_IOXGET_8(isp, &src->in_rsvd2, dst->in_status); + ISP_IOXGET_8(isp, &src->in_tag_val, dst->in_tag_type); + ISP_IOXGET_8(isp, &src->in_tag_type, dst->in_tag_val); } else { - ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_lun); - ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_iid); - ISP_IOXGET_8(isp, &insrc->in_reserved2, indst->in_reserved2); - ISP_IOXGET_8(isp, &insrc->in_tgt, indst->in_tgt); - ISP_IOXGET_8(isp, &insrc->in_status, indst->in_status); - ISP_IOXGET_8(isp, &insrc->in_rsvd2, indst->in_rsvd2); - ISP_IOXGET_8(isp, &insrc->in_tag_val, indst->in_tag_val); - ISP_IOXGET_8(isp, &insrc->in_tag_type, indst->in_tag_type); - } - ISP_IOXGET_32(isp, &insrc->in_flags, indst->in_flags); - ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid); + ISP_IOXGET_8(isp, &src->in_lun, dst->in_lun); + ISP_IOXGET_8(isp, &src->in_iid, dst->in_iid); + ISP_IOXGET_8(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_8(isp, &src->in_tgt, dst->in_tgt); + ISP_IOXGET_8(isp, &src->in_status, dst->in_status); + ISP_IOXGET_8(isp, &src->in_rsvd2, dst->in_rsvd2); + ISP_IOXGET_8(isp, &src->in_tag_val, dst->in_tag_val); + ISP_IOXGET_8(isp, &src->in_tag_type, dst->in_tag_type); + } + ISP_IOXGET_32(isp, &src->in_flags, dst->in_flags); + ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid); for (i = 0; i < IN_MSGLEN; i++) { - ISP_IOXGET_8(isp, &insrc->in_msg[i], indst->in_msg[i]); + ISP_IOXGET_8(isp, &src->in_msg[i], dst->in_msg[i]); } for (i = 0; i < IN_RSVDLEN; i++) { - ISP_IOXGET_8(isp, &insrc->in_reserved3[i], - indst->in_reserved3[i]); + ISP_IOXGET_8(isp, &src->in_reserved3[i], + dst->in_reserved3[i]); } for (i = 0; i < QLTM_SENSELEN; i++) { - ISP_IOXGET_8(isp, &insrc->in_sense[i], - indst->in_sense[i]); + ISP_IOXGET_8(isp, &src->in_sense[i], + dst->in_sense[i]); } } void -isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *insrc, - in_fcentry_t *indst) +isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *src, + in_fcentry_t *dst) +{ + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); + ISP_IOXPUT_8(isp, src->in_lun, &dst->in_lun); + ISP_IOXPUT_8(isp, src->in_iid, &dst->in_iid); + ISP_IOXPUT_16(isp, src->in_scclun, &dst->in_scclun); + ISP_IOXPUT_32(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_16(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_16(isp, src->in_task_flags, &dst->in_task_flags); + ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid); +} + +void +isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src, + in_fcentry_e_t *dst) +{ + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); + ISP_IOXPUT_16(isp, src->in_iid, &dst->in_iid); + ISP_IOXPUT_16(isp, src->in_scclun, &dst->in_scclun); + ISP_IOXPUT_32(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_16(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_16(isp, src->in_task_flags, &dst->in_task_flags); + ISP_IOXPUT_16(isp, src->in_seqid, &dst->in_seqid); +} + +void +isp_put_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src, + in_fcentry_24xx_t *dst) { - isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved); - ISP_IOXPUT_8(isp, insrc->in_lun, &indst->in_lun); - ISP_IOXPUT_8(isp, insrc->in_iid, &indst->in_iid); - ISP_IOXPUT_16(isp, insrc->in_scclun, &indst->in_scclun); - ISP_IOXPUT_32(isp, insrc->in_reserved2, &indst->in_reserved2); - ISP_IOXPUT_16(isp, insrc->in_status, &indst->in_status); - ISP_IOXPUT_16(isp, insrc->in_task_flags, &indst->in_task_flags); - ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid); + int i; + + isp_put_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved); + ISP_IOXPUT_16(isp, src->in_nphdl, &dst->in_nphdl); + ISP_IOXPUT_16(isp, src->in_reserved1, &dst->in_reserved1); + ISP_IOXPUT_16(isp, src->in_flags, &dst->in_flags); + ISP_IOXPUT_16(isp, src->in_srr_rxid, &dst->in_srr_rxid); + ISP_IOXPUT_16(isp, src->in_status, &dst->in_status); + ISP_IOXPUT_8(isp, src->in_status_subcode, &dst->in_status_subcode); + ISP_IOXPUT_16(isp, src->in_reserved2, &dst->in_reserved2); + ISP_IOXPUT_32(isp, src->in_rxid, &dst->in_rxid); + ISP_IOXPUT_16(isp, src->in_srr_reloff_hi, &dst->in_srr_reloff_hi); + ISP_IOXPUT_16(isp, src->in_srr_reloff_lo, &dst->in_srr_reloff_lo); + ISP_IOXPUT_16(isp, src->in_srr_iu, &dst->in_srr_iu); + ISP_IOXPUT_16(isp, src->in_srr_oxid, &dst->in_srr_oxid); + for (i = 0; i < 18; i++) { + ISP_IOXPUT_8(isp, src->in_reserved3[i], &dst->in_reserved3[i]); + } + ISP_IOXPUT_8(isp, src->in_reserved4, &dst->in_reserved4); + ISP_IOXPUT_8(isp, src->in_vpindex, &dst->in_vpindex); + ISP_IOXPUT_32(isp, src->in_reserved5, &dst->in_reserved5); + ISP_IOXPUT_16(isp, src->in_portid_lo, &dst->in_portid_lo); + ISP_IOXPUT_8(isp, src->in_portid_hi, &dst->in_portid_hi); + ISP_IOXPUT_8(isp, src->in_reserved6, &dst->in_reserved6); + ISP_IOXPUT_16(isp, src->in_reserved7, &dst->in_reserved7); + ISP_IOXPUT_16(isp, src->in_oxid, &dst->in_oxid); } void -isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *insrc, - in_fcentry_e_t *indst) +isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *src, + in_fcentry_t *dst) { - isp_copy_out_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXPUT_32(isp, insrc->in_reserved, &indst->in_reserved); - ISP_IOXPUT_16(isp, insrc->in_iid, &indst->in_iid); - ISP_IOXPUT_16(isp, insrc->in_scclun, &indst->in_scclun); - ISP_IOXPUT_32(isp, insrc->in_reserved2, &indst->in_reserved2); - ISP_IOXPUT_16(isp, insrc->in_status, &indst->in_status); - ISP_IOXPUT_16(isp, insrc->in_task_flags, &indst->in_task_flags); - ISP_IOXPUT_16(isp, insrc->in_seqid, &indst->in_seqid); + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); + ISP_IOXGET_8(isp, &src->in_lun, dst->in_lun); + ISP_IOXGET_8(isp, &src->in_iid, dst->in_iid); + ISP_IOXGET_16(isp, &src->in_scclun, dst->in_scclun); + ISP_IOXGET_32(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_16(isp, &src->in_status, dst->in_status); + ISP_IOXGET_16(isp, &src->in_task_flags, dst->in_task_flags); + ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid); } void -isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *insrc, - in_fcentry_t *indst) +isp_get_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src, + in_fcentry_e_t *dst) { - isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved); - ISP_IOXGET_8(isp, &insrc->in_lun, indst->in_lun); - ISP_IOXGET_8(isp, &insrc->in_iid, indst->in_iid); - ISP_IOXGET_16(isp, &insrc->in_scclun, indst->in_scclun); - ISP_IOXGET_32(isp, &insrc->in_reserved2, indst->in_reserved2); - ISP_IOXGET_16(isp, &insrc->in_status, indst->in_status); - ISP_IOXGET_16(isp, &insrc->in_task_flags, indst->in_task_flags); - ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid); + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); + ISP_IOXGET_16(isp, &src->in_iid, dst->in_iid); + ISP_IOXGET_16(isp, &src->in_scclun, dst->in_scclun); + ISP_IOXGET_32(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_16(isp, &src->in_status, dst->in_status); + ISP_IOXGET_16(isp, &src->in_task_flags, dst->in_task_flags); + ISP_IOXGET_16(isp, &src->in_seqid, dst->in_seqid); } void -isp_get_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *insrc, - in_fcentry_e_t *indst) +isp_get_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src, + in_fcentry_24xx_t *dst) { - isp_copy_in_hdr(isp, &insrc->in_header, &indst->in_header); - ISP_IOXGET_32(isp, &insrc->in_reserved, indst->in_reserved); - ISP_IOXGET_16(isp, &insrc->in_iid, indst->in_iid); - ISP_IOXGET_16(isp, &insrc->in_scclun, indst->in_scclun); - ISP_IOXGET_32(isp, &insrc->in_reserved2, indst->in_reserved2); - ISP_IOXGET_16(isp, &insrc->in_status, indst->in_status); - ISP_IOXGET_16(isp, &insrc->in_task_flags, indst->in_task_flags); - ISP_IOXGET_16(isp, &insrc->in_seqid, indst->in_seqid); + int i; + + isp_get_hdr(isp, &src->in_header, &dst->in_header); + ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved); + ISP_IOXGET_16(isp, &src->in_nphdl, dst->in_nphdl); + ISP_IOXGET_16(isp, &src->in_reserved1, dst->in_reserved1); + ISP_IOXGET_16(isp, &src->in_flags, dst->in_flags); + ISP_IOXGET_16(isp, &src->in_srr_rxid, dst->in_srr_rxid); + ISP_IOXGET_16(isp, &src->in_status, dst->in_status); + ISP_IOXGET_8(isp, &src->in_status_subcode, dst->in_status_subcode); + ISP_IOXGET_16(isp, &src->in_reserved2, dst->in_reserved2); + ISP_IOXGET_32(isp, &src->in_rxid, dst->in_rxid); + ISP_IOXGET_16(isp, &src->in_srr_reloff_hi, dst->in_srr_reloff_hi); + ISP_IOXGET_16(isp, &src->in_srr_reloff_lo, dst->in_srr_reloff_lo); + ISP_IOXGET_16(isp, &src->in_srr_iu, dst->in_srr_iu); + ISP_IOXGET_16(isp, &src->in_srr_oxid, dst->in_srr_oxid); + for (i = 0; i < 18; i++) { + ISP_IOXGET_8(isp, &src->in_reserved3[i], dst->in_reserved3[i]); + } + ISP_IOXGET_8(isp, &src->in_reserved4, dst->in_reserved4); + ISP_IOXGET_8(isp, &src->in_vpindex, dst->in_vpindex); + ISP_IOXGET_32(isp, &src->in_reserved5, dst->in_reserved5); + ISP_IOXGET_16(isp, &src->in_portid_lo, dst->in_portid_lo); + ISP_IOXGET_8(isp, &src->in_portid_hi, dst->in_portid_hi); + ISP_IOXGET_8(isp, &src->in_reserved6, dst->in_reserved6); + ISP_IOXGET_16(isp, &src->in_reserved7, dst->in_reserved7); + ISP_IOXGET_16(isp, &src->in_oxid, dst->in_oxid); } void -isp_put_notify_ack(ispsoftc_t *isp, na_entry_t *nasrc, na_entry_t *nadst) +isp_put_notify_ack(ispsoftc_t *isp, na_entry_t *src, na_entry_t *dst) { int i; - isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved); + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_iid); - ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_lun); - ISP_IOXPUT_8(isp, nasrc->na_status, &nadst->na_event); - ISP_IOXPUT_8(isp, nasrc->na_event, &nadst->na_status); + ISP_IOXPUT_8(isp, src->na_lun, &dst->na_iid); + ISP_IOXPUT_8(isp, src->na_iid, &dst->na_lun); + ISP_IOXPUT_8(isp, src->na_status, &dst->na_event); + ISP_IOXPUT_8(isp, src->na_event, &dst->na_status); } else { - ISP_IOXPUT_8(isp, nasrc->na_lun, &nadst->na_lun); - ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_iid); - ISP_IOXPUT_8(isp, nasrc->na_status, &nadst->na_status); - ISP_IOXPUT_8(isp, nasrc->na_event, &nadst->na_event); + ISP_IOXPUT_8(isp, src->na_lun, &dst->na_lun); + ISP_IOXPUT_8(isp, src->na_iid, &dst->na_iid); + ISP_IOXPUT_8(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_8(isp, src->na_event, &dst->na_event); } - ISP_IOXPUT_32(isp, nasrc->na_flags, &nadst->na_flags); + ISP_IOXPUT_32(isp, src->na_flags, &dst->na_flags); for (i = 0; i < NA_RSVDLEN; i++) { - ISP_IOXPUT_16(isp, nasrc->na_reserved3[i], - &nadst->na_reserved3[i]); + ISP_IOXPUT_16(isp, src->na_reserved3[i], + &dst->na_reserved3[i]); } } void -isp_get_notify_ack(ispsoftc_t *isp, na_entry_t *nasrc, na_entry_t *nadst) +isp_get_notify_ack(ispsoftc_t *isp, na_entry_t *src, na_entry_t *dst) { int i; - isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved); + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved); if (ISP_IS_SBUS(isp)) { - ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_iid); - ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_lun); - ISP_IOXGET_8(isp, &nasrc->na_status, nadst->na_event); - ISP_IOXGET_8(isp, &nasrc->na_event, nadst->na_status); + ISP_IOXGET_8(isp, &src->na_lun, dst->na_iid); + ISP_IOXGET_8(isp, &src->na_iid, dst->na_lun); + ISP_IOXGET_8(isp, &src->na_status, dst->na_event); + ISP_IOXGET_8(isp, &src->na_event, dst->na_status); } else { - ISP_IOXGET_8(isp, &nasrc->na_lun, nadst->na_lun); - ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_iid); - ISP_IOXGET_8(isp, &nasrc->na_status, nadst->na_status); - ISP_IOXGET_8(isp, &nasrc->na_event, nadst->na_event); + ISP_IOXGET_8(isp, &src->na_lun, dst->na_lun); + ISP_IOXGET_8(isp, &src->na_iid, dst->na_iid); + ISP_IOXGET_8(isp, &src->na_status, dst->na_status); + ISP_IOXGET_8(isp, &src->na_event, dst->na_event); } - ISP_IOXGET_32(isp, &nasrc->na_flags, nadst->na_flags); + ISP_IOXGET_32(isp, &src->na_flags, dst->na_flags); for (i = 0; i < NA_RSVDLEN; i++) { - ISP_IOXGET_16(isp, &nasrc->na_reserved3[i], - nadst->na_reserved3[i]); + ISP_IOXGET_16(isp, &src->na_reserved3[i], + dst->na_reserved3[i]); } } void -isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *nasrc, - na_fcentry_t *nadst) +isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src, + na_fcentry_t *dst) { int i; - isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved); - ISP_IOXPUT_8(isp, nasrc->na_reserved1, &nadst->na_reserved1); - ISP_IOXPUT_8(isp, nasrc->na_iid, &nadst->na_iid); - ISP_IOXPUT_16(isp, nasrc->na_response, &nadst->na_response); - ISP_IOXPUT_16(isp, nasrc->na_flags, &nadst->na_flags); - ISP_IOXPUT_16(isp, nasrc->na_reserved2, &nadst->na_reserved2); - ISP_IOXPUT_16(isp, nasrc->na_status, &nadst->na_status); - ISP_IOXPUT_16(isp, nasrc->na_task_flags, &nadst->na_task_flags); - ISP_IOXPUT_16(isp, nasrc->na_seqid, &nadst->na_seqid); + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved); + ISP_IOXPUT_8(isp, src->na_reserved1, &dst->na_reserved1); + ISP_IOXPUT_8(isp, src->na_iid, &dst->na_iid); + ISP_IOXPUT_16(isp, src->na_response, &dst->na_response); + ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags); + ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2); + ISP_IOXPUT_16(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags); + ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid); for (i = 0; i < NA2_RSVDLEN; i++) { - ISP_IOXPUT_16(isp, nasrc->na_reserved3[i], - &nadst->na_reserved3[i]); + ISP_IOXPUT_16(isp, src->na_reserved3[i], + &dst->na_reserved3[i]); } } void -isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *nasrc, - na_fcentry_e_t *nadst) +isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src, + na_fcentry_e_t *dst) { int i; - isp_copy_out_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXPUT_32(isp, nasrc->na_reserved, &nadst->na_reserved); - ISP_IOXPUT_16(isp, nasrc->na_iid, &nadst->na_iid); - ISP_IOXPUT_16(isp, nasrc->na_response, &nadst->na_response); - ISP_IOXPUT_16(isp, nasrc->na_flags, &nadst->na_flags); - ISP_IOXPUT_16(isp, nasrc->na_reserved2, &nadst->na_reserved2); - ISP_IOXPUT_16(isp, nasrc->na_status, &nadst->na_status); - ISP_IOXPUT_16(isp, nasrc->na_task_flags, &nadst->na_task_flags); - ISP_IOXPUT_16(isp, nasrc->na_seqid, &nadst->na_seqid); + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_reserved, &dst->na_reserved); + ISP_IOXPUT_16(isp, src->na_iid, &dst->na_iid); + ISP_IOXPUT_16(isp, src->na_response, &dst->na_response); + ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags); + ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2); + ISP_IOXPUT_16(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags); + ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid); for (i = 0; i < NA2_RSVDLEN; i++) { - ISP_IOXPUT_16(isp, nasrc->na_reserved3[i], - &nadst->na_reserved3[i]); + ISP_IOXPUT_16(isp, src->na_reserved3[i], + &dst->na_reserved3[i]); } } void -isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *nasrc, - na_fcentry_t *nadst) +isp_put_notify_24xx_ack(ispsoftc_t *isp, na_fcentry_24xx_t *src, + na_fcentry_24xx_t *dst) { int i; - isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved); - ISP_IOXGET_8(isp, &nasrc->na_reserved1, nadst->na_reserved1); - ISP_IOXGET_8(isp, &nasrc->na_iid, nadst->na_iid); - ISP_IOXGET_16(isp, &nasrc->na_response, nadst->na_response); - ISP_IOXGET_16(isp, &nasrc->na_flags, nadst->na_flags); - ISP_IOXGET_16(isp, &nasrc->na_reserved2, nadst->na_reserved2); - ISP_IOXGET_16(isp, &nasrc->na_status, nadst->na_status); - ISP_IOXGET_16(isp, &nasrc->na_task_flags, nadst->na_task_flags); - ISP_IOXGET_16(isp, &nasrc->na_seqid, nadst->na_seqid); + + isp_put_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXPUT_32(isp, src->na_handle, &dst->na_handle); + ISP_IOXPUT_16(isp, src->na_nphdl, &dst->na_nphdl); + ISP_IOXPUT_16(isp, src->na_reserved1, &dst->na_reserved1); + ISP_IOXPUT_16(isp, src->na_flags, &dst->na_flags); + ISP_IOXPUT_16(isp, src->na_srr_rxid, &dst->na_srr_rxid); + ISP_IOXPUT_16(isp, src->na_status, &dst->na_status); + ISP_IOXPUT_8(isp, src->na_status_subcode, &dst->na_status_subcode); + ISP_IOXPUT_16(isp, src->na_reserved2, &dst->na_reserved2); + ISP_IOXPUT_32(isp, src->na_rxid, &dst->na_rxid); + ISP_IOXPUT_16(isp, src->na_srr_reloff_hi, &dst->na_srr_reloff_hi); + ISP_IOXPUT_16(isp, src->na_srr_reloff_lo, &dst->na_srr_reloff_lo); + ISP_IOXPUT_16(isp, src->na_srr_iu, &dst->na_srr_iu); + ISP_IOXPUT_16(isp, src->na_srr_flags, &dst->na_srr_flags); + for (i = 0; i < 18; i++) { + ISP_IOXPUT_8(isp, src->na_reserved3[i], &dst->na_reserved3[i]); + } + ISP_IOXPUT_8(isp, src->na_reserved4, &dst->na_reserved4); + ISP_IOXPUT_8(isp, src->na_vpindex, &dst->na_vpindex); + ISP_IOXPUT_8(isp, src->na_srr_reject_vunique, + &dst->na_srr_reject_vunique); + ISP_IOXPUT_8(isp, src->na_srr_reject_explanation, + &dst->na_srr_reject_explanation); + ISP_IOXPUT_8(isp, src->na_srr_reject_code, &dst->na_srr_reject_code); + ISP_IOXPUT_8(isp, src->na_reserved5, &dst->na_reserved5); + for (i = 0; i < 6; i++) { + ISP_IOXPUT_8(isp, src->na_reserved6[i], &dst->na_reserved6[i]); + } + ISP_IOXPUT_16(isp, src->na_oxid, &dst->na_oxid); +} + +void +isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src, + na_fcentry_t *dst) +{ + int i; + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved); + ISP_IOXGET_8(isp, &src->na_reserved1, dst->na_reserved1); + ISP_IOXGET_8(isp, &src->na_iid, dst->na_iid); + ISP_IOXGET_16(isp, &src->na_response, dst->na_response); + ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags); + ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2); + ISP_IOXGET_16(isp, &src->na_status, dst->na_status); + ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags); + ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid); for (i = 0; i < NA2_RSVDLEN; i++) { - ISP_IOXGET_16(isp, &nasrc->na_reserved3[i], - nadst->na_reserved3[i]); + ISP_IOXGET_16(isp, &src->na_reserved3[i], + dst->na_reserved3[i]); } } void -isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *nasrc, - na_fcentry_e_t *nadst) +isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src, + na_fcentry_e_t *dst) { int i; - isp_copy_in_hdr(isp, &nasrc->na_header, &nadst->na_header); - ISP_IOXGET_32(isp, &nasrc->na_reserved, nadst->na_reserved); - ISP_IOXGET_16(isp, &nasrc->na_iid, nadst->na_iid); - ISP_IOXGET_16(isp, &nasrc->na_response, nadst->na_response); - ISP_IOXGET_16(isp, &nasrc->na_flags, nadst->na_flags); - ISP_IOXGET_16(isp, &nasrc->na_reserved2, nadst->na_reserved2); - ISP_IOXGET_16(isp, &nasrc->na_status, nadst->na_status); - ISP_IOXGET_16(isp, &nasrc->na_task_flags, nadst->na_task_flags); - ISP_IOXGET_16(isp, &nasrc->na_seqid, nadst->na_seqid); + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_reserved, dst->na_reserved); + ISP_IOXGET_16(isp, &src->na_iid, dst->na_iid); + ISP_IOXGET_16(isp, &src->na_response, dst->na_response); + ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags); + ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2); + ISP_IOXGET_16(isp, &src->na_status, dst->na_status); + ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags); + ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid); for (i = 0; i < NA2_RSVDLEN; i++) { - ISP_IOXGET_16(isp, &nasrc->na_reserved3[i], - nadst->na_reserved3[i]); + ISP_IOXGET_16(isp, &src->na_reserved3[i], + dst->na_reserved3[i]); } } + +void +isp_get_notify_ack_24xx(ispsoftc_t *isp, na_fcentry_24xx_t *src, + na_fcentry_24xx_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->na_header, &dst->na_header); + ISP_IOXGET_32(isp, &src->na_handle, dst->na_handle); + ISP_IOXGET_16(isp, &src->na_nphdl, dst->na_nphdl); + ISP_IOXGET_16(isp, &src->na_reserved1, dst->na_reserved1); + ISP_IOXGET_16(isp, &src->na_flags, dst->na_flags); + ISP_IOXGET_16(isp, &src->na_srr_rxid, dst->na_srr_rxid); + ISP_IOXGET_16(isp, &src->na_status, dst->na_status); + ISP_IOXGET_8(isp, &src->na_status_subcode, dst->na_status_subcode); + ISP_IOXGET_16(isp, &src->na_reserved2, dst->na_reserved2); + ISP_IOXGET_32(isp, &src->na_rxid, dst->na_rxid); + ISP_IOXGET_16(isp, &src->na_srr_reloff_hi, dst->na_srr_reloff_hi); + ISP_IOXGET_16(isp, &src->na_srr_reloff_lo, dst->na_srr_reloff_lo); + ISP_IOXGET_16(isp, &src->na_srr_iu, dst->na_srr_iu); + ISP_IOXGET_16(isp, &src->na_srr_flags, dst->na_srr_flags); + for (i = 0; i < 18; i++) { + ISP_IOXGET_8(isp, &src->na_reserved3[i], dst->na_reserved3[i]); + } + ISP_IOXGET_8(isp, &src->na_reserved4, dst->na_reserved4); + ISP_IOXGET_8(isp, &src->na_vpindex, dst->na_vpindex); + ISP_IOXGET_8(isp, &src->na_srr_reject_vunique, + dst->na_srr_reject_vunique); + ISP_IOXGET_8(isp, &src->na_srr_reject_explanation, + dst->na_srr_reject_explanation); + ISP_IOXGET_8(isp, &src->na_srr_reject_code, dst->na_srr_reject_code); + ISP_IOXGET_8(isp, &src->na_reserved5, dst->na_reserved5); + for (i = 0; i < 6; i++) { + ISP_IOXGET_8(isp, &src->na_reserved6[i], dst->na_reserved6[i]); + } + ISP_IOXGET_16(isp, &src->na_oxid, dst->na_oxid); +} + +void +isp_get_abts(ispsoftc_t *isp, abts_t *src, abts_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->abts_header, &dst->abts_header); + for (i = 0; i < 6; i++) { + ISP_IOXGET_8(isp, &src->abts_reserved0[i], + dst->abts_reserved0[i]); + } + ISP_IOXGET_16(isp, &src->abts_nphdl, dst->abts_nphdl); + ISP_IOXGET_16(isp, &src->abts_reserved1, dst->abts_reserved1); + ISP_IOXGET_16(isp, &src->abts_sof, dst->abts_sof); + ISP_IOXGET_32(isp, &src->abts_rxid_abts, dst->abts_rxid_abts); + ISP_IOXGET_16(isp, &src->abts_did_lo, dst->abts_did_lo); + ISP_IOXGET_8(isp, &src->abts_did_hi, dst->abts_did_hi); + ISP_IOXGET_8(isp, &src->abts_r_ctl, dst->abts_r_ctl); + ISP_IOXGET_16(isp, &src->abts_sid_lo, dst->abts_sid_lo); + ISP_IOXGET_8(isp, &src->abts_sid_hi, dst->abts_sid_hi); + ISP_IOXGET_8(isp, &src->abts_cs_ctl, dst->abts_cs_ctl); + ISP_IOXGET_16(isp, &src->abts_fs_ctl, dst->abts_fs_ctl); + ISP_IOXGET_8(isp, &src->abts_f_ctl, dst->abts_f_ctl); + ISP_IOXGET_8(isp, &src->abts_type, dst->abts_type); + ISP_IOXGET_16(isp, &src->abts_seq_cnt, dst->abts_seq_cnt); + ISP_IOXGET_8(isp, &src->abts_df_ctl, dst->abts_df_ctl); + ISP_IOXGET_8(isp, &src->abts_seq_id, dst->abts_seq_id); + ISP_IOXGET_16(isp, &src->abts_rx_id, dst->abts_rx_id); + ISP_IOXGET_16(isp, &src->abts_ox_id, dst->abts_ox_id); + ISP_IOXGET_32(isp, &src->abts_param, dst->abts_param); + for (i = 0; i < 16; i++) { + ISP_IOXGET_8(isp, &src->abts_reserved2[i], + dst->abts_reserved2[i]); + } + ISP_IOXGET_32(isp, &src->abts_rxid_task, dst->abts_rxid_task); +} + +void +isp_put_abts_rsp(ispsoftc_t *isp, abts_rsp_t *src, abts_rsp_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->abts_rsp_header, &dst->abts_rsp_header); + ISP_IOXPUT_32(isp, src->abts_rsp_handle, &dst->abts_rsp_handle); + ISP_IOXPUT_16(isp, src->abts_rsp_status, &dst->abts_rsp_status); + ISP_IOXPUT_16(isp, src->abts_rsp_nphdl, &dst->abts_rsp_nphdl); + ISP_IOXPUT_16(isp, src->abts_rsp_ctl_flags, &dst->abts_rsp_ctl_flags); + ISP_IOXPUT_16(isp, src->abts_rsp_sof, &dst->abts_rsp_sof); + ISP_IOXPUT_32(isp, src->abts_rsp_rxid_abts, &dst->abts_rsp_rxid_abts); + ISP_IOXPUT_16(isp, src->abts_rsp_did_lo, &dst->abts_rsp_did_lo); + ISP_IOXPUT_8(isp, src->abts_rsp_did_hi, &dst->abts_rsp_did_hi); + ISP_IOXPUT_8(isp, src->abts_rsp_r_ctl, &dst->abts_rsp_r_ctl); + ISP_IOXPUT_16(isp, src->abts_rsp_sid_lo, &dst->abts_rsp_sid_lo); + ISP_IOXPUT_8(isp, src->abts_rsp_sid_hi, &dst->abts_rsp_sid_hi); + ISP_IOXPUT_8(isp, src->abts_rsp_cs_ctl, &dst->abts_rsp_cs_ctl); + ISP_IOXPUT_16(isp, src->abts_rsp_f_ctl_lo, &dst->abts_rsp_f_ctl_lo); + ISP_IOXPUT_8(isp, src->abts_rsp_f_ctl_hi, &dst->abts_rsp_f_ctl_hi); + ISP_IOXPUT_8(isp, src->abts_rsp_type, &dst->abts_rsp_type); + ISP_IOXPUT_16(isp, src->abts_rsp_seq_cnt, &dst->abts_rsp_seq_cnt); + ISP_IOXPUT_8(isp, src->abts_rsp_df_ctl, &dst->abts_rsp_df_ctl); + ISP_IOXPUT_8(isp, src->abts_rsp_seq_id, &dst->abts_rsp_seq_id); + ISP_IOXPUT_16(isp, src->abts_rsp_rx_id, &dst->abts_rsp_rx_id); + ISP_IOXPUT_16(isp, src->abts_rsp_ox_id, &dst->abts_rsp_ox_id); + ISP_IOXPUT_32(isp, src->abts_rsp_param, &dst->abts_rsp_param); + if (src->abts_rsp_r_ctl == BA_ACC) { + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.reserved, + &dst->abts_rsp_payload.ba_acc.reserved); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.last_seq_id, + &dst->abts_rsp_payload.ba_acc.last_seq_id); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.seq_id_valid, + &dst->abts_rsp_payload.ba_acc.seq_id_valid); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_rx_id, + &dst->abts_rsp_payload.ba_acc.aborted_rx_id); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_ox_id, + &dst->abts_rsp_payload.ba_acc.aborted_ox_id); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.high_seq_cnt, + &dst->abts_rsp_payload.ba_acc.high_seq_cnt); + ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.low_seq_cnt, + &dst->abts_rsp_payload.ba_acc.low_seq_cnt); + for (i = 0; i < 4; i++) { + ISP_IOXPUT_16(isp, + src->abts_rsp_payload.ba_acc.reserved2[i], + &dst->abts_rsp_payload.ba_acc.reserved2[i]); + } + } else if (src->abts_rsp_r_ctl == BA_RJT) { + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.vendor_unique, + &dst->abts_rsp_payload.ba_rjt.vendor_unique); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.explanation, + &dst->abts_rsp_payload.ba_rjt.explanation); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reason, + &dst->abts_rsp_payload.ba_rjt.reason); + ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reserved, + &dst->abts_rsp_payload.ba_rjt.reserved); + for (i = 0; i < 12; i++) { + ISP_IOXPUT_16(isp, + src->abts_rsp_payload.ba_rjt.reserved2[i], + &dst->abts_rsp_payload.ba_rjt.reserved2[i]); + } + } else { + for (i = 0; i < 16; i++) { + ISP_IOXPUT_8(isp, src->abts_rsp_payload.reserved[i], + &dst->abts_rsp_payload.reserved[i]); + } + } + ISP_IOXPUT_32(isp, src->abts_rsp_rxid_task, &dst->abts_rsp_rxid_task); +} + +void +isp_get_abts_rsp(ispsoftc_t *isp, abts_rsp_t *src, abts_rsp_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->abts_rsp_header, &dst->abts_rsp_header); + ISP_IOXGET_32(isp, &src->abts_rsp_handle, dst->abts_rsp_handle); + ISP_IOXGET_16(isp, &src->abts_rsp_status, dst->abts_rsp_status); + ISP_IOXGET_16(isp, &src->abts_rsp_nphdl, dst->abts_rsp_nphdl); + ISP_IOXGET_16(isp, &src->abts_rsp_ctl_flags, dst->abts_rsp_ctl_flags); + ISP_IOXGET_16(isp, &src->abts_rsp_sof, dst->abts_rsp_sof); + ISP_IOXGET_32(isp, &src->abts_rsp_rxid_abts, dst->abts_rsp_rxid_abts); + ISP_IOXGET_16(isp, &src->abts_rsp_did_lo, dst->abts_rsp_did_lo); + ISP_IOXGET_8(isp, &src->abts_rsp_did_hi, dst->abts_rsp_did_hi); + ISP_IOXGET_8(isp, &src->abts_rsp_r_ctl, dst->abts_rsp_r_ctl); + ISP_IOXGET_16(isp, &src->abts_rsp_sid_lo, dst->abts_rsp_sid_lo); + ISP_IOXGET_8(isp, &src->abts_rsp_sid_hi, dst->abts_rsp_sid_hi); + ISP_IOXGET_8(isp, &src->abts_rsp_cs_ctl, dst->abts_rsp_cs_ctl); + ISP_IOXGET_16(isp, &src->abts_rsp_f_ctl_lo, dst->abts_rsp_f_ctl_lo); + ISP_IOXGET_8(isp, &src->abts_rsp_f_ctl_hi, dst->abts_rsp_f_ctl_hi); + ISP_IOXGET_8(isp, &src->abts_rsp_type, dst->abts_rsp_type); + ISP_IOXGET_16(isp, &src->abts_rsp_seq_cnt, dst->abts_rsp_seq_cnt); + ISP_IOXGET_8(isp, &src->abts_rsp_df_ctl, dst->abts_rsp_df_ctl); + ISP_IOXGET_8(isp, &src->abts_rsp_seq_id, dst->abts_rsp_seq_id); + ISP_IOXGET_16(isp, &src->abts_rsp_rx_id, dst->abts_rsp_rx_id); + ISP_IOXGET_16(isp, &src->abts_rsp_ox_id, dst->abts_rsp_ox_id); + ISP_IOXGET_32(isp, &src->abts_rsp_param, dst->abts_rsp_param); + for (i = 0; i < 8; i++) { + ISP_IOXGET_8(isp, &src->abts_rsp_payload.rsp.reserved[i], + dst->abts_rsp_payload.rsp.reserved[i]); + } + ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode1, + dst->abts_rsp_payload.rsp.subcode1); + ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode2, + dst->abts_rsp_payload.rsp.subcode2); + ISP_IOXGET_32(isp, &src->abts_rsp_rxid_task, dst->abts_rsp_rxid_task); +} #endif /* ISP_TARGET_MODE */ +/* + * vim:ts=8:sw=8 + */ diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h index 4faa320..9447741 100644 --- a/sys/dev/isp/isp_library.h +++ b/sys/dev/isp/isp_library.h @@ -30,22 +30,26 @@ #ifndef _ISP_LIBRARY_H #define _ISP_LIBRARY_H -extern int isp_save_xs(ispsoftc_t *, XS_T *, uint16_t *); -extern XS_T *isp_find_xs(ispsoftc_t *, uint16_t); -extern uint16_t isp_find_handle(ispsoftc_t *, XS_T *); -extern int isp_handle_index(uint16_t); -extern uint16_t isp_index_handle(int); -extern void isp_destroy_handle(ispsoftc_t *, uint16_t); -extern int isp_getrqentry(ispsoftc_t *, uint16_t *, uint16_t *, void **); +extern int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *); +extern XS_T *isp_find_xs(ispsoftc_t *, uint32_t); +extern uint32_t isp_find_handle(ispsoftc_t *, XS_T *); +extern uint32_t isp_handle_index(uint32_t); +extern void isp_destroy_handle(ispsoftc_t *, uint32_t); +extern int isp_getrqentry(ispsoftc_t *, uint32_t *, uint32_t *, void **); extern void isp_print_qentry (ispsoftc_t *, char *, int, void *); extern void isp_print_bytes(ispsoftc_t *, char *, int, void *); extern int isp_fc_runstate(ispsoftc_t *, int); -extern void isp_copy_out_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *); -extern void isp_copy_in_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *); +extern void isp_shutdown(ispsoftc_t *); +extern void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *); +extern void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *); extern int isp_get_response_type(ispsoftc_t *, isphdr_t *); extern void isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *); extern void +isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *); +extern void +isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *); +extern void isp_put_request_t2(ispsoftc_t *, ispreqt2_t *, ispreqt2_t *); extern void isp_put_request_t2e(ispsoftc_t *, ispreqt2e_t *, ispreqt2e_t *); @@ -56,21 +60,37 @@ isp_put_request_t3e(ispsoftc_t *, ispreqt3e_t *, ispreqt3e_t *); extern void isp_put_extended_request(ispsoftc_t *, ispextreq_t *, ispextreq_t *); extern void +isp_put_request_t7(ispsoftc_t *, ispreqt7_t *, ispreqt7_t *); +extern void +isp_put_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *); +extern void isp_put_cont_req(ispsoftc_t *, ispcontreq_t *, ispcontreq_t *); extern void isp_put_cont64_req(ispsoftc_t *, ispcontreq64_t *, ispcontreq64_t *); extern void isp_get_response(ispsoftc_t *, ispstatusreq_t *, ispstatusreq_t *); -extern void -isp_get_response_x(ispsoftc_t *, ispstatus_cont_t *, ispstatus_cont_t *); +extern void isp_get_24xx_response(ispsoftc_t *, isp24xx_statusreq_t *, + isp24xx_statusreq_t *); +void +isp_get_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *); extern void isp_get_rio2(ispsoftc_t *, isp_rio2_t *, isp_rio2_t *); extern void isp_put_icb(ispsoftc_t *, isp_icb_t *, isp_icb_t *); extern void -isp_get_pdb(ispsoftc_t *, isp_pdb_t *, isp_pdb_t *); +isp_put_icb_2400(ispsoftc_t *, isp_icb_2400_t *, isp_icb_2400_t *); +extern void +isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *); extern void -isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *); +isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *); +extern void +isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *); +extern void +isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *); +extern void +isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *); +extern void +isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *); extern void isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *); extern void @@ -93,6 +113,17 @@ isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *, extern void isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *, sns_ga_nxt_rsp_t *); +extern void +isp_get_els(ispsoftc_t *, els_t *, els_t *); +extern void +isp_put_els(ispsoftc_t *, els_t *, els_t *); +extern void +isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *); +extern void +isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *); +extern void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *); +extern void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *); +extern void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *); #ifdef ISP_TARGET_MODE #if defined(__NetBSD__) || defined(__OpenBSD__) @@ -103,10 +134,12 @@ isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *, #include "isp_target.h" #endif -extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint16_t *); -extern void *isp_find_xs_tgt(ispsoftc_t *, uint16_t); -extern uint16_t isp_find_tgt_handle(ispsoftc_t *, void *); -extern void isp_destroy_tgt_handle(ispsoftc_t *, uint16_t); +#define IS_TARGET_HANDLE(x) ((x) & 0x8000) + +extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *); +extern void *isp_find_xs_tgt(ispsoftc_t *, uint32_t); +extern uint32_t isp_find_tgt_handle(ispsoftc_t *, void *); +extern void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t); extern void isp_put_atio(ispsoftc_t *, at_entry_t *, at_entry_t *); @@ -121,6 +154,8 @@ isp_get_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *); extern void isp_get_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *); extern void +isp_get_atio7(ispsoftc_t *isp, at7_entry_t *, at7_entry_t *); +extern void isp_put_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *); extern void isp_get_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *); @@ -129,10 +164,14 @@ isp_put_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *); extern void isp_put_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *); extern void +isp_put_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *); +extern void isp_get_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *); extern void isp_get_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *); extern void +isp_get_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *); +extern void isp_put_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *); extern void isp_get_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *); @@ -145,20 +184,36 @@ isp_put_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *); extern void isp_put_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *); extern void +isp_put_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *); +extern void isp_get_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *); extern void isp_get_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *); extern void +isp_get_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *); +extern void isp_put_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *); extern void isp_get_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *); extern void +isp_put_notify_24xx_ack(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *); +extern void isp_put_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *); extern void isp_put_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *); +extern void isp_put_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *, + na_fcentry_24xx_t *); extern void isp_get_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *); extern void isp_get_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *); +extern void isp_get_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *, + na_fcentry_24xx_t *); +extern void +isp_get_abts(ispsoftc_t *, abts_t *, abts_t *); +extern void +isp_put_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *); +extern void +isp_get_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *); #endif /* ISP_TARGET_MODE */ #endif /* _ISP_LIBRARY_H */ diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index 6bb6956..db17cc7 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -62,19 +62,23 @@ __FBSDID("$FreeBSD$"); #define BUS_PROBE_DEFAULT 0 #endif -static uint16_t isp_pci_rd_reg(ispsoftc_t *, int); -static void isp_pci_wr_reg(ispsoftc_t *, int, uint16_t); -static uint16_t isp_pci_rd_reg_1080(ispsoftc_t *, int); -static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint16_t); +static uint32_t isp_pci_rd_reg(ispsoftc_t *, int); +static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t); +static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int); +static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t); +static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int); +static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t); static int -isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); +isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); static int -isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); +isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); +static int +isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); static int isp_pci_mbxdma(ispsoftc_t *); static int -isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t); +isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t); static void -isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint16_t); +isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint32_t); static void isp_pci_reset1(ispsoftc_t *); @@ -158,6 +162,18 @@ static struct ispmdvec mdvec_2300 = { isp_pci_dumpregs }; +static struct ispmdvec mdvec_2400 = { + isp_pci_rd_isr_2400, + isp_pci_rd_reg_2400, + isp_pci_wr_reg_2400, + isp_pci_mbxdma, + isp_pci_dmasetup, + isp_pci_dmateardown, + NULL, + isp_pci_reset1, + NULL +}; + #ifndef PCIM_CMD_INVEN #define PCIM_CMD_INVEN 0x10 #endif @@ -306,6 +322,7 @@ static struct ispmdvec mdvec_2300 = { static int isp_pci_probe (device_t); static int isp_pci_attach (device_t); +static int isp_pci_detach (device_t); struct isp_pcisoftc { @@ -320,10 +337,12 @@ struct isp_pcisoftc { bus_dmamap_t *dmaps; }; + static device_method_t isp_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, isp_pci_probe), DEVMETHOD(device_attach, isp_pci_attach), + DEVMETHOD(device_detach, isp_pci_detach), { 0, 0 } }; static void isp_pci_intr(void *); @@ -380,11 +399,9 @@ isp_pci_probe(device_t dev) case PCI_QLOGIC_ISP2322: device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); break; -#if 0 case PCI_QLOGIC_ISP2422: device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); break; -#endif case PCI_QLOGIC_ISP6312: device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); break; @@ -487,6 +504,23 @@ isp_get_options(device_t dev, ispsoftc_t *isp) isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; } + bitmap = 0; + (void) getenv_int("isp_fabric_hysteresis", &bitmap); + if (bitmap >= 0 && bitmap < 256) { + isp->isp_osinfo.hysteresis = bitmap; + } else { + isp->isp_osinfo.hysteresis = isp_fabric_hysteresis; + } + + bitmap = 0; + (void) getenv_int("isp_loop_down_limit", &bitmap); + if (bitmap >= 0 && bitmap < 0xffff) { + isp->isp_osinfo.loop_down_limit = bitmap; + } else { + isp->isp_osinfo.loop_down_limit = isp_loop_down_limit; + } + + #ifdef ISP_FW_CRASH_DUMP bitmap = 0; if (getenv_int("isp_fw_dump_enable", &bitmap)) { @@ -690,6 +724,24 @@ isp_get_options(device_t dev, ispsoftc_t *isp) isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; } + tval = 0; + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "hysteresis", &tval); + if (tval >= 0 && tval < 256) { + isp->isp_osinfo.hysteresis = tval; + } else { + isp->isp_osinfo.hysteresis = isp_fabric_hysteresis; + } + + tval = 0; + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "loop_down_limit", &tval); + if (tval >= 0 && tval < 0xffff) { + isp->isp_osinfo.loop_down_limit = tval; + } else { + isp->isp_osinfo.loop_down_limit = isp_loop_down_limit; + } + } static void @@ -886,11 +938,11 @@ isp_pci_attach(device_t dev) PCI_MBOX_REGS2300_OFF; } if (pci_get_devid(dev) == PCI_QLOGIC_ISP2422) { - mdvp = &mdvec_2300; - basetype = ISP_HA_FC_2422; + mdvp = &mdvec_2400; + basetype = ISP_HA_FC_2400; psize = sizeof (fcparam); pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = - PCI_MBOX_REGS2300_OFF; + PCI_MBOX_REGS2400_OFF; } isp = &pcs->pci_isp; isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); @@ -932,6 +984,9 @@ isp_pci_attach(device_t dev) case PCI_PRODUCT_QLOGIC_ISP6322: did = 0x2322; break; + case PCI_PRODUCT_QLOGIC_ISP2422: + did = 0x2400; + break; default: break; } @@ -976,16 +1031,40 @@ isp_pci_attach(device_t dev) cmd &= ~PCIM_CMD_INVEN; } - if (IS_23XX(isp)) { - /* - * Can't tell if ROM will hang on 'ABOUT FIRMWARE' command. - */ - isp->isp_touched = 1; - + if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { + cmd &= ~PCIM_CMD_INTX_DISABLE; } - if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { + if (IS_24XX(isp)) { + int reg; + cmd &= ~PCIM_CMD_INTX_DISABLE; + + /* + * Is this a PCI-X card? If so, set max read byte count. + */ + if (pci_find_extcap(dev, PCIY_PCIX, ®) == 0) { + uint16_t pxcmd; + reg += 2; + + pxcmd = pci_read_config(dev, reg, 2); + pxcmd &= ~0xc; + pxcmd |= 0x8; + pci_write_config(dev, reg, 2, pxcmd); + } + + /* + * Is this a PCI Express card? If so, set max read byte count. + */ + if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { + uint16_t pectl; + + reg += 0x8; + pectl = pci_read_config(dev, reg, 2); + pectl &= ~0x7000; + pectl |= 0x4000; + pci_write_config(dev, reg, 2, pectl); + } } pci_write_config(dev, PCIR_COMMAND, cmd, 2); @@ -1039,10 +1118,17 @@ isp_pci_attach(device_t dev) /* * Last minute checks... */ - if (IS_23XX(isp)) { + if (IS_23XX(isp) || IS_24XX(isp)) { isp->isp_port = pci_get_function(dev); } + if (IS_23XX(isp)) { + /* + * Can't tell if ROM will hang on 'ABOUT FIRMWARE' command. + */ + isp->isp_touched = 1; + } + /* * Make sure we're in reset state. */ @@ -1069,6 +1155,7 @@ isp_pci_attach(device_t dev) * XXXX: (or decrease the reference count to it). */ ISP_UNLOCK(isp); + return (0); bad: @@ -1110,21 +1197,34 @@ bad: return (ENXIO); } +static int +isp_pci_detach(device_t dev) +{ + struct isp_pcisoftc *pcs; + ispsoftc_t *isp; + + pcs = device_get_softc(dev); + if (pcs == NULL) { + return (ENXIO); + } + isp = (ispsoftc_t *) pcs; + ISP_DISABLE_INTS(isp); + return (0); +} + static void isp_pci_intr(void *arg) { ispsoftc_t *isp = arg; - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; ISP_LOCK(isp); isp->isp_intcnt++; if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { isp->isp_intbogus++; } else { - int iok = isp->isp_osinfo.intsok; - isp->isp_osinfo.intsok = 0; isp_intr(isp, isr, sema, mbox); - isp->isp_osinfo.intsok = iok; } ISP_UNLOCK(isp); } @@ -1138,13 +1238,17 @@ isp_pci_intr(void *arg) bus_space_read_2(pcs->pci_st, pcs->pci_sh, off) #define BXW2(pcs, off, v) \ bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v) +#define BXR4(pcs, off) \ + bus_space_read_4(pcs->pci_st, pcs->pci_sh, off) +#define BXW4(pcs, off, v) \ + bus_space_write_4(pcs->pci_st, pcs->pci_sh, off, v) static __inline int isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - uint16_t val0, val1; + uint32_t val0, val1; int i = 0; do { @@ -1159,7 +1263,7 @@ isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp) } static int -isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp, +isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; @@ -1196,19 +1300,18 @@ isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp, } static int -isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp, +isp_pci_rd_isr_2300(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbox0p) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - uint16_t hccr; + uint32_t hccr; uint32_t r2hisr; if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { *isrp = 0; return (0); } - r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh, - IspVirt2Off(pcs, BIU_R2HSTSLO)); + r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU_R2HSTSLO)); isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); if ((r2hisr & BIU_R2HST_INTR) == 0) { *isrp = 0; @@ -1252,17 +1355,54 @@ isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp, "RISC paused at interrupt (%x->%x\n", hccr, ISP_READ(isp, HCCR)); } else { - isp_prt(isp, ISP_LOGERR, "unknown interrerupt 0x%x\n", + isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); } return (0); } } -static uint16_t +static int +isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp, + uint16_t *semap, uint16_t *mbox0p) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + uint32_t r2hisr; + + r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU2400_R2HSTSLO)); + isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); + if ((r2hisr & BIU2400_R2HST_INTR) == 0) { + *isrp = 0; + return (0); + } + switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) { + case ISP2400R2HST_ROM_MBX_OK: + case ISP2400R2HST_ROM_MBX_FAIL: + case ISP2400R2HST_MBX_OK: + case ISP2400R2HST_MBX_FAIL: + case ISP2400R2HST_ASYNC_EVENT: + *isrp = r2hisr & 0xffff; + *mbox0p = (r2hisr >> 16); + *semap = 1; + return (1); + case ISP2400R2HST_RSPQ_UPDATE: + case ISP2400R2HST_ATIO_RSPQ_UPDATE: + case ISP2400R2HST_ATIO_RQST_UPDATE: + *isrp = r2hisr & 0xffff; + *mbox0p = 0; + *semap = 0; + return (1); + default: + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); + isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); + return (0); + } +} + +static uint32_t isp_pci_rd_reg(ispsoftc_t *isp, int regoff) { - uint16_t rv; + uint32_t rv; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; int oldconf = 0; @@ -1282,10 +1422,11 @@ isp_pci_rd_reg(ispsoftc_t *isp, int regoff) } static void -isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val) +isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; int oldconf = 0; + volatile int junk; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* @@ -1294,22 +1435,25 @@ isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val) oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); + junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); } BXW2(pcs, IspVirt2Off(isp, regoff), val); + junk = BXR2(pcs, IspVirt2Off(isp, regoff)); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); + junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); } } -static uint16_t +static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) { - uint16_t rv, oc = 0; + uint32_t rv, oc = 0; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { - uint16_t tc; + uint32_t tc; /* * We will assume that someone has paused the RISC processor. */ @@ -1333,14 +1477,15 @@ isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) } static void -isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint16_t val) +isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; int oc = 0; + volatile int junk; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { - uint16_t tc; + uint32_t tc; /* * We will assume that someone has paused the RISC processor. */ @@ -1351,14 +1496,137 @@ isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint16_t val) else tc |= BIU_PCI1080_CONF1_SXP0; BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); + junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc | BIU_PCI1080_CONF1_DMA); + junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); } BXW2(pcs, IspVirt2Off(isp, regoff), val); + junk = BXR2(pcs, IspVirt2Off(isp, regoff)); if (oc) { BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); + junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); + } +} + +static uint32_t +isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + uint32_t rv; + int block = regoff & _BLK_REG_MASK; + + switch (block) { + case BIU_BLOCK: + break; + case MBOX_BLOCK: + return (BXR2(pcs, IspVirt2Off(pcs, regoff))); + case SXP_BLOCK: + isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff); + return (0xffffffff); + case RISC_BLOCK: + isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff); + return (0xffffffff); + case DMA_BLOCK: + isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff); + return (0xffffffff); + default: + isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff); + return (0xffffffff); + } + + + switch (regoff) { + case BIU2400_FLASH_ADDR: + case BIU2400_FLASH_DATA: + case BIU2400_ICR: + case BIU2400_ISR: + case BIU2400_CSR: + case BIU2400_REQINP: + case BIU2400_REQOUTP: + case BIU2400_RSPINP: + case BIU2400_RSPOUTP: + case BIU2400_PRI_RQINP: + case BIU2400_PRI_RSPINP: + case BIU2400_ATIO_RSPINP: + case BIU2400_ATIO_REQINP: + case BIU2400_HCCR: + case BIU2400_GPIOD: + case BIU2400_GPIOE: + case BIU2400_HSEMA: + rv = BXR4(pcs, IspVirt2Off(pcs, regoff)); + break; + case BIU2400_R2HSTSLO: + rv = BXR4(pcs, IspVirt2Off(pcs, regoff)); + break; + case BIU2400_R2HSTSHI: + rv = BXR4(pcs, IspVirt2Off(pcs, regoff)) >> 16; + break; + default: + isp_prt(isp, ISP_LOGERR, + "isp_pci_rd_reg_2400: unknown offset %x", regoff); + rv = 0xffffffff; + break; + } + return (rv); +} + +static void +isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + int block = regoff & _BLK_REG_MASK; + volatile int junk; + + switch (block) { + case BIU_BLOCK: + break; + case MBOX_BLOCK: + BXW2(pcs, IspVirt2Off(pcs, regoff), val); + junk = BXR2(pcs, IspVirt2Off(pcs, regoff)); + return; + case SXP_BLOCK: + isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff); + return; + case RISC_BLOCK: + isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff); + return; + case DMA_BLOCK: + isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff); + return; + default: + isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x", + regoff); + break; + } + + switch (regoff) { + case BIU2400_FLASH_ADDR: + case BIU2400_FLASH_DATA: + case BIU2400_ICR: + case BIU2400_ISR: + case BIU2400_CSR: + case BIU2400_REQINP: + case BIU2400_REQOUTP: + case BIU2400_RSPINP: + case BIU2400_RSPOUTP: + case BIU2400_PRI_RQINP: + case BIU2400_PRI_RSPINP: + case BIU2400_ATIO_RSPINP: + case BIU2400_ATIO_REQINP: + case BIU2400_HCCR: + case BIU2400_GPIOD: + case BIU2400_GPIOE: + case BIU2400_HSEMA: + BXW4(pcs, IspVirt2Off(pcs, regoff), val); + junk = BXR4(pcs, IspVirt2Off(pcs, regoff)); + break; + default: + isp_prt(isp, ISP_LOGERR, + "isp_pci_wr_reg_2400: bad offset 0x%x", regoff); + break; } } @@ -1430,6 +1698,11 @@ isp_pci_mbxdma(ispsoftc_t *isp) return (0); } + if (isp->isp_maxcmds == 0) { + isp_prt(isp, ISP_LOGERR, "maxcmds not set"); + return (1); + } + hlim = BUS_SPACE_MAXADDR; if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { slim = (bus_size_t) (1ULL << 32); @@ -1576,8 +1849,8 @@ typedef struct { ispsoftc_t *isp; void *cmd_token; void *rq; - uint16_t *nxtip; - uint16_t optr; + uint32_t *nxtip; + uint32_t optr; int error; } mush_t; @@ -1615,7 +1888,7 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bus_dmamap_t *dp; ct_entry_t *cto, *qe; uint8_t scsi_status; - uint16_t curi, nxti, handle; + uint32_t curi, nxti, handle; uint32_t sflags; int32_t resid; int nth_ctio, nctios, send_status; @@ -1855,7 +2128,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) struct ccb_scsiio *csio; ispsoftc_t *isp; ct2_entry_t *cto, *qe; - uint16_t curi, nxti; + uint32_t curi, nxti; ispds_t *ds; ispds64_t *ds64; int segcnt, seglim; @@ -1894,7 +2167,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) "0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun, cto->ct_iid, cto->ct_flags, cto->ct_status, cto->rsp.m1.ct_scsi_status, cto->ct_resid); - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_put_ctio2e(isp, (ct2e_entry_t *)cto, (ct2e_entry_t *)qe); } else { @@ -1933,12 +2206,12 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) if (segcnt != nseg) { cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3; seglim = ISP_RQDSEG_T3; - ds64 = &cto->rsp.m0.ct_dataseg64[0]; + ds64 = &cto->rsp.m0.u.ct_dataseg64[0]; ds = NULL; } else { seglim = ISP_RQDSEG_T2; ds64 = NULL; - ds = &cto->rsp.m0.ct_dataseg[0]; + ds = &cto->rsp.m0.u.ct_dataseg[0]; } cto->ct_seg_count = 0; @@ -1973,7 +2246,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) } while (segcnt < nseg) { - uint16_t curip; + uint32_t curip; int seg; ispcontreq_t local, *crq = &local, *qep; @@ -2044,19 +2317,128 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) cto->ct_rxid, csio->ccb_h.target_lun, (int) cto->ct_iid, cto->ct_flags, cto->ct_status, cto->rsp.m1.ct_scsi_status, cto->ct_resid); - if (IS_2KLOGIN(isp)) + if (FCPARAM(isp)->isp_2klogin) { isp_put_ctio2e(isp, (ct2e_entry_t *)cto, (ct2e_entry_t *)qe); - else + } else { isp_put_ctio2(isp, cto, qe); + } ISP_TDQE(isp, "last dma2_tgt_fc", curi, qe); *mp->nxtip = nxti; } #endif +static void dma_2400(void *, bus_dma_segment_t *, int, int); static void dma2_a64(void *, bus_dma_segment_t *, int, int); static void dma2(void *, bus_dma_segment_t *, int, int); static void +dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) +{ + mush_t *mp; + ispsoftc_t *isp; + struct ccb_scsiio *csio; + struct isp_pcisoftc *pcs; + bus_dmamap_t *dp; + bus_dma_segment_t *eseg; + ispreqt7_t *rq; + int seglim, datalen; + uint32_t nxti; + + mp = (mush_t *) arg; + if (error) { + mp->error = error; + return; + } + + if (nseg < 1) { + isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg); + mp->error = EFAULT; + return; + } + + csio = mp->cmd_token; + isp = mp->isp; + rq = mp->rq; + pcs = (struct isp_pcisoftc *)mp->isp; + dp = &pcs->dmaps[isp_handle_index(rq->req_handle)]; + nxti = *mp->nxtip; + + if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); + } else { + bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); + } + datalen = XS_XFRLEN(csio); + + /* + * We're passed an initial partially filled in entry that + * has most fields filled in except for data transfer + * related values. + * + * Our job is to fill in the initial request queue entry and + * then to start allocating and filling in continuation entries + * until we've covered the entire transfer. + */ + + rq->req_header.rqs_entry_type = RQSTYPE_T7RQS; + rq->req_dl = datalen; + if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + rq->req_alen_datadir = 0x2; + } else { + rq->req_alen_datadir = 0x1; + } + + eseg = dm_segs + nseg; + + rq->req_dataseg.ds_base = DMA_LO32(dm_segs->ds_addr); + rq->req_dataseg.ds_basehi = DMA_HI32(dm_segs->ds_addr); + rq->req_dataseg.ds_count = dm_segs->ds_len; + + datalen -= dm_segs->ds_len; + + dm_segs++; + rq->req_seg_count++; + + while (datalen > 0 && dm_segs != eseg) { + uint32_t onxti; + ispcontreq64_t local, *crq = &local, *cqe; + + cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); + onxti = nxti; + nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp)); + if (nxti == mp->optr) { + isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++"); + mp->error = MUSHERR_NOQENTRIES; + return; + } + rq->req_header.rqs_entry_count++; + MEMZERO((void *)crq, sizeof (*crq)); + crq->req_header.rqs_entry_count = 1; + crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT; + + seglim = 0; + while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) { + crq->req_dataseg[seglim].ds_base = + DMA_LO32(dm_segs->ds_addr); + crq->req_dataseg[seglim].ds_basehi = + DMA_HI32(dm_segs->ds_addr); + crq->req_dataseg[seglim].ds_count = + dm_segs->ds_len; + rq->req_seg_count++; + dm_segs++; + seglim++; + datalen -= dm_segs->ds_len; + } + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq); + } + isp_put_cont64_req(isp, crq, cqe); + MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); + } + *mp->nxtip = nxti; +} + +static void dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) { mush_t *mp; @@ -2067,7 +2449,7 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bus_dma_segment_t *eseg; ispreq64_t *rq; int seglim, datalen; - uint16_t nxti; + uint32_t nxti; mp = (mush_t *) arg; if (error) { @@ -2152,7 +2534,7 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) } while (datalen > 0 && dm_segs != eseg) { - uint16_t onxti; + uint32_t onxti; ispcontreq64_t local, *crq = &local, *cqe; cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); @@ -2181,6 +2563,9 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) seglim++; datalen -= dm_segs->ds_len; } + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq); + } isp_put_cont64_req(isp, crq, cqe); MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); } @@ -2198,7 +2583,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bus_dma_segment_t *eseg; ispreq_t *rq; int seglim, datalen; - uint16_t nxti; + uint32_t nxti; mp = (mush_t *) arg; if (error) { @@ -2278,7 +2663,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) } while (datalen > 0 && dm_segs != eseg) { - uint16_t onxti; + uint32_t onxti; ispcontreq_t local, *crq = &local, *cqe; cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); @@ -2305,6 +2690,9 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) seglim++; datalen -= dm_segs->ds_len; } + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq); + } isp_put_cont_req(isp, crq, cqe); MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); } @@ -2316,7 +2704,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) */ static int isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, - uint16_t *nxtip, uint16_t optr) + uint32_t *nxtip, uint32_t optr) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; ispreq_t *qep; @@ -2348,7 +2736,9 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, } } else #endif - if (sizeof (bus_addr_t) > 4) { + if (IS_24XX(isp)) { + eptr = dma_2400; + } else if (sizeof (bus_addr_t) > 4) { eptr = dma2_a64; } else { eptr = dma2; @@ -2433,6 +2823,9 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, return (retval); } mbxsync: + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq); + } switch (rq->req_header.rqs_entry_type) { case RQSTYPE_REQUEST: isp_put_request(isp, rq, qep); @@ -2448,12 +2841,15 @@ mbxsync: case RQSTYPE_T3RQS: isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) qep); break; + case RQSTYPE_T7RQS: + isp_put_request_t7(isp, (ispreqt7_t *) rq, (ispreqt7_t *) qep); + break; } return (CMD_QUEUED); } static void -isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle) +isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; bus_dmamap_t *dp = &pcs->dmaps[isp_handle_index(handle)]; @@ -2469,10 +2865,12 @@ isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle) static void isp_pci_reset1(ispsoftc_t *isp) { - /* Make sure the BIOS is disabled */ - isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); + if (!IS_24XX(isp)) { + /* Make sure the BIOS is disabled */ + isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); + } /* and enable interrupts */ - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); } static void diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index c8b88fc..2e1273b 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -51,15 +51,17 @@ __FBSDID("$FreeBSD$"); #include <dev/isp/isp_freebsd.h> -static uint16_t isp_sbus_rd_reg(ispsoftc_t *, int); -static void isp_sbus_wr_reg(ispsoftc_t *, int, uint16_t); +static uint32_t +isp_sbus_rd_reg(ispsoftc_t *, int); +static void +isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t); static int -isp_sbus_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); +isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); static int isp_sbus_mbxdma(ispsoftc_t *); static int -isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t); +isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t); static void -isp_sbus_dmateardown(ispsoftc_t *, XS_T *, uint16_t); +isp_sbus_dmateardown(ispsoftc_t *, XS_T *, uint32_t); static void isp_sbus_reset1(ispsoftc_t *); static void isp_sbus_dumpregs(ispsoftc_t *, const char *); @@ -149,6 +151,7 @@ isp_sbus_attach(device_t dev) struct isp_sbussoftc *sbs; ispsoftc_t *isp = NULL; int locksetup = 0; + int ints_setup = 0; /* * Figure out if we're supposed to skip this one. @@ -184,10 +187,8 @@ isp_sbus_attach(device_t dev) regs = NULL; iqd = 0; - rid = 0; - regs = - bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (regs == 0) { device_printf(dev, "unable to map registers\n"); goto bad; @@ -243,19 +244,17 @@ isp_sbus_attach(device_t dev) } /* - * Some early versions of the PTI SBus adapter - * would fail in trying to download (via poking) - * FW. We give up on them. + * We don't trust NVRAM on SBus cards */ - if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 || - strcmp("ptisp", ofw_bus_get_name(dev)) == 0) { - isp->isp_confopts |= ISP_CFG_NORELOAD; - } + isp->isp_confopts |= ISP_CFG_NONVRAM; /* - * We don't trust NVRAM on SBus cards + * Mark things if we're a PTI SBus adapter. */ - isp->isp_confopts |= ISP_CFG_NONVRAM; + if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 || + strcmp("ptisp", ofw_bus_get_name(dev)) == 0) { + SDPARAM(isp)->isp_ptisp = 1; + } #if __FreeBSD_version >= 700000 @@ -277,14 +276,6 @@ isp_sbus_attach(device_t dev) } #endif - iqd = 0; - sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, - RF_ACTIVE | RF_SHAREABLE); - if (sbs->sbus_ires == NULL) { - device_printf(dev, "could not allocate interrupt\n"); - goto bad; - } - tval = 0; if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { @@ -313,11 +304,20 @@ isp_sbus_attach(device_t dev) mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); locksetup++; + iqd = 0; + sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, + RF_ACTIVE | RF_SHAREABLE); + if (sbs->sbus_ires == NULL) { + device_printf(dev, "could not allocate interrupt\n"); + goto bad; + } + if (bus_setup_intr(dev, sbs->sbus_ires, ISP_IFLAGS, isp_sbus_intr, isp, &sbs->ih)) { device_printf(dev, "could not setup interrupt\n"); goto bad; } + ints_setup++; /* * Set up logging levels. @@ -327,8 +327,9 @@ isp_sbus_attach(device_t dev) } else { isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; } - if (bootverbose) + if (bootverbose) { isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; + } /* * Make sure we're in reset state. @@ -336,6 +337,7 @@ isp_sbus_attach(device_t dev) ISP_LOCK(isp); isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { + isp_uninit(isp); ISP_UNLOCK(isp); goto bad; } @@ -351,42 +353,33 @@ isp_sbus_attach(device_t dev) ISP_UNLOCK(isp); goto bad; } - /* - * XXXX: Here is where we might unload the f/w module - * XXXX: (or decrease the reference count to it). - */ ISP_UNLOCK(isp); return (0); bad: - if (sbs && sbs->ih) { + if (sbs && ints_setup) { (void) bus_teardown_intr(dev, sbs->sbus_ires, sbs->ih); } - if (locksetup && isp) { - mtx_destroy(&isp->isp_osinfo.lock); - } - if (sbs && sbs->sbus_ires) { bus_release_resource(dev, SYS_RES_IRQ, iqd, sbs->sbus_ires); } + if (locksetup && isp) { + mtx_destroy(&isp->isp_osinfo.lock); + } if (regs) { (void) bus_release_resource(dev, 0, 0, regs); } if (sbs) { - if (sbs->sbus_isp.isp_param) + if (sbs->sbus_isp.isp_param) { free(sbs->sbus_isp.isp_param, M_DEVBUF); + } free(sbs, M_DEVBUF); } - - /* - * XXXX: Here is where we might unload the f/w module - * XXXX: (or decrease the reference count to it). - */ return (ENXIO); } @@ -394,17 +387,15 @@ static void isp_sbus_intr(void *arg) { ispsoftc_t *isp = arg; - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; ISP_LOCK(isp); isp->isp_intcnt++; if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { isp->isp_intbogus++; } else { - int iok = isp->isp_osinfo.intsok; - isp->isp_osinfo.intsok = 0; isp_intr(isp, isr, sema, mbox); - isp->isp_osinfo.intsok = iok; } ISP_UNLOCK(isp); } @@ -417,8 +408,7 @@ isp_sbus_intr(void *arg) bus_space_read_2(sbc->sbus_st, sbc->sbus_sh, off) static int -isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp, - uint16_t *semap, uint16_t *mbp) +isp_sbus_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp) { struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; uint16_t isr, sema; @@ -438,7 +428,7 @@ isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp, return (1); } -static uint16_t +static uint32_t isp_sbus_rd_reg(ispsoftc_t *isp, int regoff) { uint16_t rval; @@ -452,7 +442,7 @@ isp_sbus_rd_reg(ispsoftc_t *isp, int regoff) } static void -isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val) +isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) { struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp; int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; @@ -605,8 +595,8 @@ typedef struct { ispsoftc_t *isp; void *cmd_token; void *rq; - uint16_t *nxtip; - uint16_t optr; + uint32_t *nxtip; + uint32_t optr; int error; } mush_t; @@ -721,7 +711,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) static int isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, - uint16_t *nxtip, uint16_t optr) + uint32_t *nxtip, uint32_t optr) { struct isp_sbussoftc *sbs = (struct isp_sbussoftc *)isp; ispreq_t *qep; @@ -809,6 +799,9 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, return (retval); } mbxsync: + if (isp->isp_dblev & ISP_LOGDEBUG1) { + isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq); + } switch (rq->req_header.rqs_entry_type) { case RQSTYPE_REQUEST: isp_put_request(isp, rq, qep); @@ -822,7 +815,7 @@ mbxsync: } static void -isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle) +isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle) { struct isp_sbussoftc *sbs = (struct isp_sbussoftc *)isp; bus_dmamap_t *dp = &sbs->dmaps[isp_handle_index(handle)]; @@ -834,12 +827,10 @@ isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle) bus_dmamap_unload(sbs->dmat, *dp); } - static void isp_sbus_reset1(ispsoftc_t *isp) { - /* enable interrupts */ - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); } static void diff --git a/sys/dev/isp/isp_stds.h b/sys/dev/isp/isp_stds.h new file mode 100644 index 0000000..a25f774 --- /dev/null +++ b/sys/dev/isp/isp_stds.h @@ -0,0 +1,200 @@ +/* $FreeBSD$ */ +/*- + * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. + * + * Copyright (c) 1997-2006 by Matthew Jacob + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Structures that derive directly from public standards. + */ +#ifndef _ISP_STDS_H +#define _ISP_STDS_H + +/* + * FC Frame Header + * + * Source: dpANS-X3.xxx-199x, section 18 (AKA FC-PH-2) + * + */ +typedef struct { + uint8_t r_ctl; + uint8_t d_id[3]; + uint8_t cs_ctl; + uint8_t s_id[3]; + uint8_t type; + uint8_t f_ctl; + uint8_t seq_id; + uint8_t df_ctl; + uint16_t seq_cnt; + uint16_t ox_id; + uint16_t rx_id; + uint32_t parameter; +} fc_hdr_t; + +/* + * FCP_CMND_IU Payload + * + * Source: NICTS T10, Project 1144D, Revision 07a, Section 9 (AKA fcp2-r07a) + * + * Notes: + * When additional cdb length is defined in fcp_cmnd_alen_datadir, + * bits 2..7, the actual cdb length is 16 + ((fcp_cmnd_alen_datadir>>2)*4), + * with the datalength following in MSB format just after. + */ +typedef struct { + uint8_t fcp_cmnd_lun[8]; + uint8_t fcp_cmnd_crn; + uint8_t fcp_cmnd_task_attribute; + uint8_t fcp_cmnd_task_management; + uint8_t fcp_cmnd_alen_datadir; + union { + struct { + uint8_t fcp_cmnd_cdb[16]; + uint32_t fcp_cmnd_dl; + } sf; + struct { + uint8_t fcp_cmnd_cdb[1]; + } lf; + } cdb_dl; +} fcp_cmnd_iu_t; + + +#define FCP_CMND_TASK_ATTR_SIMPLE 0x00 +#define FCP_CMND_TASK_ATTR_HEAD 0x01 +#define FCP_CMND_TASK_ATTR_ORDERED 0x02 +#define FCP_CMND_TASK_ATTR_ACA 0x04 +#define FCP_CMND_TASK_ATTR_UNTAGGED 0x05 +#define FCP_CMND_TASK_ATTR_MASK 0x07 + +#define FCP_CMND_ADDTL_CDBLEN_SHIFT 2 + +#define FCP_CMND_DATA_WRITE 0x01 +#define FCP_CMND_DATA_READ 0x02 + +#define FCP_CMND_DATA_DIR_MASK 0x03 + +#define FCP_CMND_TMF_CLEAR_ACA 0x40 +#define FCP_CMND_TMF_TGT_RESET 0x20 +#define FCP_CMND_TMF_LUN_RESET 0x10 +#define FCP_CMND_TMF_CLEAR_TASK_SET 0x04 +#define FCP_CMND_TMF_ABORT_TASK_SET 0x02 + +/* + * Basic CT IU Header + * + * Source: X3.288-199x Generic Services 2 Rev 5.3 (FC-GS-2) Section 4.3.1 + */ + +typedef struct { + uint8_t ct_revision; + uint8_t ct_in_id[3]; + uint8_t ct_fcs_type; + uint8_t ct_fcs_subtype; + uint8_t ct_options; + uint8_t ct_reserved0; + uint16_t ct_cmd_resp; + uint16_t ct_bcnt_resid; + uint8_t ct_reserved1; + uint8_t ct_reason; + uint8_t ct_explanation; + uint8_t ct_vunique; +} ct_hdr_t; +#define CT_REVISION 1 +#define CT_FC_TYPE_FC 0xFC +#define CT_FC_SUBTYPE_NS 0x02 + +/* + * RFT_ID Requet CT_IU + * + * Source: INCITS xxx-200x Generic Services- 5 Rev 8.5 Section 5.2.5.30 + */ +typedef struct { + ct_hdr_t rftid_hdr; + uint8_t rftid_reserved; + uint8_t rftid_portid[3]; + uint32_t rftid_fc4types[8]; +} rft_id_t; + + +/* unconverted miscellany */ +/* + * Basic FC Link Service defines + */ +/* + * These are in the R_CTL field. + */ +#define ABTS 0x81 +#define BA_ACC 0x84 /* of ABORT SEQUENCE */ +#define BA_RJT 0x85 /* of ABORT SEQUENCE */ + +/* + * Link Service Accept/Reject + */ +#define LS_ACC 0x8002 +#define LS_RJT 0x8001 + +/* + * FC ELS Codes- bits 31-24 of the first payload word of an ELS frame. + */ +#define PLOGI 0x03 +#define FLOGI 0x04 +#define LOGO 0x05 +#define ABTX 0x06 +#define PRLI 0x20 +#define PRLO 0x21 +#define TPRLO 0x24 +#define RNC 0x53 + +/* + * FC4 defines + */ +#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP */ +#define FC4_SCSI 8 /* SCSI-3 via Fibre Channel Protocol (FCP) */ +#define FC4_FC_SVC 0x20 /* Fibre Channel Services */ + +#ifndef MSG_ABORT +#define MSG_ABORT 0x06 +#endif +#ifndef MSG_BUS_DEV_RESET +#define MSG_BUS_DEV_RESET 0x0c +#endif +#ifndef MSG_ABORT_TAG +#define MSG_ABORT_TAG 0x0d +#endif +#ifndef MSG_CLEAR_QUEUE +#define MSG_CLEAR_QUEUE 0x0e +#endif +#ifndef MSG_REL_RECOVERY +#define MSG_REL_RECOVERY 0x10 +#endif +#ifndef MSG_TERM_IO_PROC +#define MSG_TERM_IO_PROC 0x11 +#endif +#ifndef MSG_LUN_RESET +#define MSG_LUN_RESET 0x17 +#endif + +#endif /* _ISP_STDS_H */ diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index ebbd80b..a86b8ec 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -53,15 +53,17 @@ static const char atiocope[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset " "on bus %d"; static const char atior[] = - "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred " - "on bus %d"; + "ATIO returned on for lun %d on from loopid %d because a Bus Reset " + "occurred on bus %d"; static void isp_got_msg(ispsoftc_t *, in_entry_t *); static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *); +static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *); static void isp_handle_atio(ispsoftc_t *, at_entry_t *); static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *); static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *); static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); +static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *); /* * The Qlogic driver gets an interrupt to look at response queue entries. @@ -110,42 +112,57 @@ static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); */ int -isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) +isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) { - uint16_t status, seqid; + uint16_t status; + uint32_t seqid; union { at_entry_t *atiop; at2_entry_t *at2iop; at2e_entry_t *at2eiop; + at7_entry_t *at7iop; ct_entry_t *ctiop; ct2_entry_t *ct2iop; ct2e_entry_t *ct2eiop; + ct7_entry_t *ct7iop; lun_entry_t *lunenp; in_entry_t *inotp; in_fcentry_t *inot_fcp; in_fcentry_e_t *inote_fcp; + in_fcentry_24xx_t *inot_24xx; na_entry_t *nackp; na_fcentry_t *nack_fcp; na_fcentry_e_t *nacke_fcp; + na_fcentry_24xx_t *nack_24xx; isphdr_t *hp; + abts_t *abts; + abts_rsp_t *abts_rsp; + els_t *els; void * *vp; #define atiop unp.atiop #define at2iop unp.at2iop #define at2eiop unp.at2eiop +#define at7iop unp.at7iop #define ctiop unp.ctiop #define ct2iop unp.ct2iop #define ct2eiop unp.ct2eiop +#define ct7iop unp.ct7iop #define lunenp unp.lunenp #define inotp unp.inotp #define inot_fcp unp.inot_fcp #define inote_fcp unp.inote_fcp +#define inot_24xx unp.inot_24xx #define nackp unp.nackp #define nack_fcp unp.nack_fcp #define nacke_fcp unp.nacke_fcp +#define nack_24xx unp.nack_24xx +#define abts unp.abts +#define abts_rsp unp.abts_rsp +#define els unp.els #define hdrp unp.hp } unp; uint8_t local[QENTRY_LEN]; - int bus, type, rval = 1; + int bus, type, level, rval = 1; type = isp_get_response_type(isp, (isphdr_t *)vptr); unp.vp = vptr; @@ -154,30 +171,72 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) switch(type) { case RQSTYPE_ATIO: - isp_get_atio(isp, atiop, (at_entry_t *) local); - isp_handle_atio(isp, (at_entry_t *) local); + if (IS_24XX(isp)) { + int len; + + isp_get_atio7(isp, at7iop, (at7_entry_t *) local); + at7iop = (at7_entry_t *) local; + /* + * Check for and do something with commands whose IULEN + * extends past a singel queue entry. + */ + len = at7iop->at_ta_len & 0xfffff; + if (len > (QENTRY_LEN - 8)) { + len -= (QENTRY_LEN - 8); + isp_prt(isp, ISP_LOGINFO, + "long IU length (%d) ignored", len); + while (len > 0) { + *optrp = ISP_NXT_QENTRY(*optrp, + RESULT_QUEUE_LEN(isp)); + len -= QENTRY_LEN; + } + } + /* + * Check for a task management function + */ + if (at7iop->at_cmnd.fcp_cmnd_task_management) { + isp_got_tmf_24xx(isp, at7iop); + break; + } + /* + * Just go straight to outer layer for this one. + */ + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local); + } else { + isp_get_atio(isp, atiop, (at_entry_t *) local); + isp_handle_atio(isp, (at_entry_t *) local); + } break; + case RQSTYPE_CTIO: isp_get_ctio(isp, ctiop, (ct_entry_t *) local); isp_handle_ctio(isp, (ct_entry_t *) local); break; + case RQSTYPE_ATIO2: - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); } else { isp_get_atio2(isp, at2iop, (at2_entry_t *) local); - } + } isp_handle_atio2(isp, (at2_entry_t *) local); break; + case RQSTYPE_CTIO3: case RQSTYPE_CTIO2: - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); } else { isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); - } + } isp_handle_ctio2(isp, (ct2_entry_t *) local); break; + + case RQSTYPE_CTIO7: + isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local); + isp_handle_ctio7(isp, (ct7_entry_t *) local); + break; + case RQSTYPE_ENABLE_LUN: case RQSTYPE_MODIFY_LUN: isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local); @@ -193,8 +252,36 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) * (we set this initially in the Enable Lun entry). */ bus = 0; - if (IS_FC(isp)) { - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + isp_get_notify_24xx(isp, inot_24xx, + (in_fcentry_24xx_t *)local); + inot_24xx = (in_fcentry_24xx_t *) local; + status = inot_24xx->in_status; + seqid = inot_24xx->in_rxid; + isp_prt(isp, ISP_LOGTDEBUG0, + "Immediate Notify status=0x%x seqid=0x%x", + status, seqid); + switch (status) { + case IN24XX_LIP_RESET: + case IN24XX_LINK_RESET: + case IN24XX_PORT_LOGOUT: + case IN24XX_PORT_CHANGED: + case IN24XX_LINK_FAILED: + case IN24XX_SRR_RCVD: + case IN24XX_ELS_RCVD: + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, + &local); + break; + default: + isp_prt(isp, ISP_LOGINFO, + "isp_target_notify: unknown status (0x%x)", + status); + isp_notify_ack(isp, local); + break; + } + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_notify_fc_e(isp, inote_fcp, (in_fcentry_e_t *)local); } else { @@ -229,12 +316,28 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) } break; case IN_RSRC_UNAVAIL: - isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs"); + isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); isp_notify_ack(isp, local); break; case IN_RESET: - (void) isp_target_async(isp, 0, ASYNC_BUS_RESET); + { + /* + * We form the notify structure here because we need + * to mark it as needing a NOTIFY ACK on return. + */ + tmd_notify_t notify; + + MEMZERO(¬ify, sizeof (tmd_notify_t)); + notify.nt_hba = isp; + notify.nt_iid = INI_ANY; + /* nt_tgt set in outer layers */ + notify.nt_lun = LUN_ANY; + notify.nt_tagval = TAG_ANY; + notify.nt_ncode = NT_BUS_RESET; + notify.nt_need_ack = 1; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; + } case IN_PORT_LOGOUT: case IN_ABORT_TASK: case IN_PORT_CHANGED: @@ -242,8 +345,9 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); break; default: - isp_prt(isp, ISP_LOGERR, - "bad status (0x%x) in isp_target_notify", status); + isp_prt(isp, ISP_LOGINFO, + "isp_target_notify: unknown status (0x%x)", + status); isp_notify_ack(isp, local); break; } @@ -254,26 +358,68 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) * The ISP is acknowledging our acknowledgement of an * Immediate Notify entry for some asynchronous event. */ - if (IS_FC(isp)) { - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + isp_get_notify_ack_24xx(isp, nack_24xx, + (na_fcentry_24xx_t *) local); + nack_24xx = (na_fcentry_24xx_t *) local; + if (nack_24xx->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG1; + } + isp_prt(isp, level, + "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", + nack_24xx->na_status, nack_24xx->na_status_subcode, + nack_24xx->na_rxid); + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local); } else { isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local); - } + } nack_fcp = (na_fcentry_t *)local; - isp_prt(isp, ISP_LOGTDEBUG1, - "Notify Ack status=0x%x seqid 0x%x", + if (nack_fcp->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG1; + } + isp_prt(isp, level, + "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid); } else { isp_get_notify_ack(isp, nackp, (na_entry_t *)local); nackp = (na_entry_t *)local; - isp_prt(isp, ISP_LOGTDEBUG1, + if (nackp->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG1; + } + isp_prt(isp, level, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp->na_event, nackp->na_status, nackp->na_seqid); } break; + + case RQSTYPE_ABTS_RCVD: + isp_get_abts(isp, abts, (abts_t *)local); + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); + break; + case RQSTYPE_ABTS_RSP: + isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local); + abts_rsp = (abts_rsp_t *) local; + if (abts_rsp->abts_rsp_status) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG0; + } + isp_prt(isp, level, + "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", + abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status, + abts_rsp->abts_rsp_payload.rsp.subcode1, + abts_rsp->abts_rsp_payload.rsp.subcode2); + break; default: isp_prt(isp, ISP_LOGERR, "Unknown entry type 0x%x in isp_target_notify", type); @@ -283,16 +429,23 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) #undef atiop #undef at2iop #undef at2eiop +#undef at7iop #undef ctiop #undef ct2iop #undef ct2eiop +#undef ct7iop #undef lunenp #undef inotp #undef inot_fcp #undef inote_fcp +#undef inot_24xx #undef nackp #undef nack_fcp #undef nacke_fcp +#undef hack_24xx +#undef abts +#undef abts_rsp +#undef els #undef hdrp return (rval); } @@ -312,7 +465,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun, int cmd_cnt, int inot_cnt, uint32_t opaque) { lun_entry_t el; - uint16_t nxti, optr; + uint32_t nxti, optr; void *outp; @@ -344,7 +497,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun, if (IS_SCSI(isp)) { el.le_tgt = tgt; el.le_lun = lun; - } else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { + } else if (FCPARAM(isp)->isp_sccfw == 0) { el.le_lun = lun; } @@ -364,7 +517,7 @@ int isp_target_put_entry(ispsoftc_t *isp, void *ap) { void *outp; - uint16_t nxti, optr; + uint32_t nxti, optr; uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { @@ -377,28 +530,34 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap) isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); break; case RQSTYPE_ATIO2: - if (IS_2KLOGIN(isp)) { - isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp); - } else { - isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp); - } + if (FCPARAM(isp)->isp_2klogin) { + isp_put_atio2e(isp, (at2e_entry_t *) ap, + (at2e_entry_t *) outp); + } else { + isp_put_atio2(isp, (at2_entry_t *) ap, + (at2_entry_t *) outp); + } break; case RQSTYPE_CTIO: isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp); break; case RQSTYPE_CTIO2: - if (IS_2KLOGIN(isp)) { - isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp); - } else { - isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp); - } + if (FCPARAM(isp)->isp_2klogin) { + isp_put_ctio2e(isp, (ct2e_entry_t *) ap, + (ct2e_entry_t *) outp); + } else { + isp_put_ctio2(isp, (ct2_entry_t *) ap, + (ct2_entry_t *) outp); + } + break; + case RQSTYPE_CTIO7: + isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp); break; default: isp_prt(isp, ISP_LOGERR, "Unknown type 0x%x in isp_put_entry", etype); return (-1); } - ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap); ISP_ADD_REQUEST(isp, nxti); return (0); @@ -418,12 +577,12 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg) at2_entry_t *aep = arg; atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; atun._atio2.at_header.rqs_entry_count = 1; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - atun._atio2.at_scclun = (uint16_t) aep->at_scclun; + if (FCPARAM(isp)->isp_sccfw) { + atun._atio2.at_scclun = aep->at_scclun; } else { atun._atio2.at_lun = (uint8_t) aep->at_lun; } - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; } else { atun._atio2.at_iid = aep->at_iid; @@ -465,28 +624,56 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg) */ int -isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint16_t hdl) +isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl) { int sts; union { ct_entry_t _ctio; ct2_entry_t _ctio2; ct2e_entry_t _ctio2e; + ct7_entry_t _ctio7; } un; MEMZERO(&un, sizeof un); sts = code & 0xff; - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + at7_entry_t *aep = arg; + ct7_entry_t *cto = &un._ctio7; + + cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + cto->ct_header.rqs_entry_count = 1; +/* XXXX */ cto->ct_nphdl = aep->at_hdr.seq_id; + cto->ct_rxid = aep->at_rxid; + cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | + aep->at_hdr.s_id[2]; + cto->ct_iid_hi = aep->at_hdr.s_id[0]; + cto->ct_oxid = aep->at_hdr.ox_id; + cto->ct_scsi_status = sts; + cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS; + if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { + cto->rsp.m1.ct_resplen = 16; + cto->rsp.m1.ct_resp[0] = 0xf0; + cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; + cto->rsp.m1.ct_resp[7] = 8; + cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; + cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; + } + if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) { + cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl; + cto->ct_scsi_status |= CT2_DATA_UNDER; + } + cto->ct_syshandle = hdl; + } else if (IS_FC(isp)) { at2_entry_t *aep = arg; ct2_entry_t *cto = &un._ctio2; cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { + if (FCPARAM(isp)->isp_sccfw == 0) { cto->ct_lun = aep->at_lun; } - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; } else { cto->ct_iid = aep->at_iid; @@ -565,6 +752,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) notify.nt_ncode = NT_LINK_DOWN; (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; + case ASYNC_LIP_ERROR: case ASYNC_LIP_F8: case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_RESET: @@ -584,7 +772,13 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) { uint8_t storage[QENTRY_LEN]; memset(storage, 0, QENTRY_LEN); - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + ct7_entry_t *ct = (ct7_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + ct->ct_nphdl = CT7_OK; + ct->ct_syshandle = bus; + ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST; + } else if (IS_FC(isp)) { /* This should also suffice for 2K login code */ ct2_entry_t *ct = (ct2_entry_t *) storage; ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; @@ -599,7 +793,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) ct->ct_flags = CT_SENDSTATUS; } (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage); - return (0); + break; } default: isp_prt(isp, ISP_LOGERR, @@ -679,14 +873,14 @@ static void isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) { tmd_notify_t nt; - static const char f1[] = "%s from loop id %d lun %d seq 0x%x"; + static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x"; static const char f2[] = - "unknown %s 0x%x lun %d loop id %d task flags 0x%x seq 0x%x\n"; + "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n"; uint16_t seqid, loopid; MEMZERO(&nt, sizeof (tmd_notify_t)); nt.nt_hba = isp; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid; loopid = ((in_fcentry_e_t *)inp)->in_iid; seqid = ((in_fcentry_e_t *)inp)->in_seqid; @@ -696,12 +890,13 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) seqid = inp->in_seqid; } /* nt_tgt set in outer layers */ - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { nt.nt_lun = inp->in_scclun; } else { nt.nt_lun = inp->in_lun; } IN_FC_MAKE_TAGID(nt.nt_tagval, 0, seqid); + nt.nt_need_ack = 1; nt.nt_lreserved = inp; if (inp->in_status != IN_MSG_RECEIVED) { @@ -741,11 +936,69 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); } +static void +isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep) +{ + tmd_notify_t nt; + static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%x"; + static const char f2[] = + "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%x\n"; + uint32_t sid; + + MEMZERO(&nt, sizeof (tmd_notify_t)); + nt.nt_hba = isp; + nt.nt_iid = INI_ANY; + nt.nt_lun = + (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | + (aep->at_cmnd.fcp_cmnd_lun[1]); + nt.nt_tagval = aep->at_rxid; + nt.nt_lreserved = aep; + sid = + (aep->at_hdr.s_id[0] << 16) | + (aep->at_hdr.s_id[1] << 8) | + (aep->at_hdr.s_id[2]); + + if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_ABORT_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_ABORT_TASK_SET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_CLEAR_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_CLEAR_TASK_SET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_LUN_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_LUN_RESET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_TGT_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_TARGET_RESET; + nt.nt_lun = LUN_ANY; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_CLEAR_ACA) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_CLEAR_ACA; + } else { + isp_prt(isp, ISP_LOGWARN, f2, + aep->at_cmnd.fcp_cmnd_task_management, + nt.nt_lun, sid, nt.nt_tagval); + isp_endcmd(isp, aep, 0, 0); + return; + } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); +} + void isp_notify_ack(ispsoftc_t *isp, void *arg) { char storage[QENTRY_LEN]; - uint16_t nxti, optr; + uint32_t nxti, optr; void *outp; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { @@ -756,14 +1009,49 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) MEMZERO(storage, QENTRY_LEN); - if (IS_FC(isp)) { + if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) { + at7_entry_t *aep = arg; + isp_endcmd(isp, aep, 0, 0); + return; + } else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) { + abts_rsp_t *abts_rsp = (abts_rsp_t *) storage; + /* + * The caller will have set response values as appropriate + * in the ABTS structure just before calling us. + */ + MEMCPY(abts_rsp, arg, QENTRY_LEN); + isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp); + } else if (IS_24XX(isp)) { + na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage; + if (arg) { + in_fcentry_24xx_t *in = arg; + na->na_nphdl = in->in_nphdl; + na->na_status = in->in_status; + na->na_status_subcode = in->in_status_subcode; + na->na_rxid = in->in_rxid; + na->na_oxid = in->in_oxid; + if (in->in_status == IN24XX_SRR_RCVD) { + na->na_srr_rxid = in->in_srr_rxid; + na->na_srr_reloff_hi = in->in_srr_reloff_hi; + na->na_srr_reloff_lo = in->in_srr_reloff_lo; + na->na_srr_iu = in->in_srr_iu; + na->na_srr_flags = 1; + na->na_srr_reject_vunique = 0; + na->na_srr_reject_explanation = 1; + na->na_srr_reject_code = 1; + } + } + na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + na->na_header.rqs_entry_count = 1; + isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp); + } else if (IS_FC(isp)) { na_fcentry_t *na = (na_fcentry_t *) storage; int iid = 0; if (arg) { in_fcentry_t *inp = arg; MEMCPY(storage, arg, sizeof (isphdr_t)); - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid; iid = ((na_fcentry_e_t *)na)->na_iid; @@ -788,14 +1076,14 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) } na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; na->na_header.rqs_entry_count = 1; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp); } else { isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); } - isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u seqid %x flags " - "%x tflags %x response %x", iid, na->na_seqid, + isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x " + "flags %x tflags %x response %x", iid, na->na_seqid, na->na_flags, na->na_task_flags, na->na_response); } else { na_entry_t *na = (na_entry_t *) storage; @@ -815,8 +1103,8 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; na->na_header.rqs_entry_count = 1; isp_put_notify_ack(isp, na, (na_entry_t *)outp); - isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u lun %u tgt %u " - "seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, + isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt " + "%u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event); } ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage); @@ -897,7 +1185,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep) default: isp_prt(isp, ISP_LOGERR, - "Unknown ATIO status 0x%x from initiator %d for lun %d", + "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun); (void) isp_target_put_atio(isp, aep); break; @@ -909,13 +1197,13 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) { int lun, iid; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { lun = aep->at_scclun; } else { lun = aep->at_lun; } - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { iid = ((at2e_entry_t *)aep)->at_iid; } else { iid = aep->at_iid; @@ -986,7 +1274,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) default: isp_prt(isp, ISP_LOGERR, - "Unknown ATIO2 status 0x%x from initiator %d for lun %d", + "Unknown ATIO2 status 0x%x from loopid %d for lun %d", aep->at_status, iid, lun); (void) isp_target_put_atio(isp, aep); break; @@ -1002,8 +1290,9 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) if (ct->ct_syshandle) { xs = isp_find_xs_tgt(isp, ct->ct_syshandle); - if (xs == NULL) + if (xs == NULL) { pl = ISP_LOGALL; + } } else { xs = NULL; } @@ -1055,7 +1344,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) if (fmsg == NULL) fmsg = "ABORT TAG message sent by Initiator"; - isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg); + isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg); break; case CT_INVAL: @@ -1156,14 +1445,15 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) static void isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) { - XS_T *xs; + void *xs; int pl = ISP_LOGTDEBUG2; char *fmsg = NULL; if (ct->ct_syshandle) { xs = isp_find_xs_tgt(isp, ct->ct_syshandle); - if (xs == NULL) + if (xs == NULL) { pl = ISP_LOGALL; + } } else { xs = NULL; } @@ -1193,7 +1483,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) * status. These CTIOs are handled in that same way as * CT_ABORTED ones, so just fall through here. */ - fmsg = "TARGET RESET Task Management Function Received"; + fmsg = "TARGET RESET"; /*FALLTHROUGH*/ case CT_RESET: if (fmsg == NULL) @@ -1205,11 +1495,12 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) * Bus Free and returns all outstanding CTIOs with the status * set, then sends us an Immediate Notify entry. */ - if (fmsg == NULL) - fmsg = "ABORT Task Management Function Received"; + if (fmsg == NULL) { + fmsg = "ABORT"; + } - isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s: RX_ID=0x%x", - fmsg, ct->ct_rxid); + isp_prt(isp, ISP_LOGTDEBUG0, + "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); break; case CT_INVAL: @@ -1235,7 +1526,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) if (fmsg == NULL) fmsg = "Port Logout"; /*FALLTHROUGH*/ - case CT_PORTNOTAVAIL: + case CT_PORTUNAVAIL: if (fmsg == NULL) fmsg = "Port not available"; /*FALLTHROUGH*/ @@ -1246,7 +1537,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) case CT_NOACK: if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); + isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); break; case CT_INVRXID: @@ -1254,7 +1545,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) * CTIO rejected by the firmware because an invalid RX_ID. * Just print a message. */ - isp_prt(isp, ISP_LOGERR, + isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); break; @@ -1312,4 +1603,157 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) */ } } + +static void +isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct) +{ + void *xs; + int pl = ISP_LOGTDEBUG2; + char *fmsg = NULL; + + if (ct->ct_syshandle) { + xs = isp_find_xs_tgt(isp, ct->ct_syshandle); + if (xs == NULL) { + pl = ISP_LOGALL; + } + } else { + xs = NULL; + } + + switch(ct->ct_nphdl) { + case CT7_BUS_ERROR: + isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); + /* FALL Through */ + case CT7_DATA_OVER: + case CT7_DATA_UNDER: + case CT7_OK: + /* + * There are generally 2 possibilities as to why we'd get + * this condition: + * We sent or received data. + * We sent status & command complete. + */ + + break; + + case CT7_RESET: + if (fmsg == NULL) { + fmsg = "LIP Reset"; + } + /*FALLTHROUGH*/ + case CT7_ABORTED: + /* + * When an Abort message is received the firmware goes to + * Bus Free and returns all outstanding CTIOs with the status + * set, then sends us an Immediate Notify entry. + */ + if (fmsg == NULL) { + fmsg = "ABORT"; + } + isp_prt(isp, ISP_LOGTDEBUG0, + "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); + break; + + case CT7_TIMEOUT: + if (fmsg == NULL) { + fmsg = "command"; + } + isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); + break; + + case CT7_ERR: + fmsg = "Completed with Error"; + /*FALLTHROUGH*/ + case CT7_LOGOUT: + if (fmsg == NULL) { + fmsg = "Port Logout"; + } + /*FALLTHROUGH*/ + case CT7_PORTUNAVAIL: + if (fmsg == NULL) { + fmsg = "Port not available"; + } + /*FALLTHROUGH*/ + case CT7_PORTCHANGED: + if (fmsg == NULL) { + fmsg = "Port Changed"; + } + isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); + break; + + case CT7_INVRXID: + /* + * CTIO rejected by the firmware because an invalid RX_ID. + * Just print a message. + */ + isp_prt(isp, ISP_LOGWARN, + "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid); + break; + + case CT7_REASSY_ERR: + isp_prt(isp, ISP_LOGWARN, "reassembly error"); + break; + + case CT7_SRR: + isp_prt(isp, ISP_LOGWARN, "SRR received"); + break; + + default: + isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", + ct->ct_nphdl); + break; + } + + if (xs == NULL) { + /* + * There may be more than one CTIO for a data transfer, + * or this may be a status CTIO we're not monitoring. + * + * The assumption is that they'll all be returned in the + * order we got them. + */ + if (ct->ct_syshandle == 0) { + if (ct->ct_flags & CT7_TERMINATE) { + isp_prt(isp, ISP_LOGINFO, + "termination of 0x%x complete", + ct->ct_rxid); + } else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) { + isp_prt(isp, pl, + "intermediate CTIO completed ok"); + } else { + isp_prt(isp, pl, + "unmonitored CTIO completed ok"); + } + } else { + isp_prt(isp, pl, + "NO xs for CTIO (handle 0x%x) status 0x%x", + ct->ct_syshandle, ct->ct_nphdl); + } + } else { + if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { + ISP_DMAFREE(isp, xs, ct->ct_syshandle); + } + if (ct->ct_flags & CT2_SENDSTATUS) { + /* + * Sent status and command complete. + * + * We're now really done with this command, so we + * punt to the platform dependent layers because + * only there can we do the appropriate command + * complete thread synchronization. + */ + isp_prt(isp, pl, "status CTIO complete"); + } else { + /* + * Final CTIO completed. Release DMA resources and + * notify platform dependent layers. + */ + isp_prt(isp, pl, "data CTIO complete"); + } + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); + /* + * The platform layer will destroy the handle if appropriate. + */ + } +} #endif diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h index be03877..80bbe64 100644 --- a/sys/dev/isp/isp_target.h +++ b/sys/dev/isp/isp_target.h @@ -155,28 +155,48 @@ typedef struct { #define TASK_FLAGS_CLEAR_TASK_SET (1<<10) #define TASK_FLAGS_ABORT_TASK_SET (1<<9) -#ifndef MSG_ABORT -#define MSG_ABORT 0x06 -#endif -#ifndef MSG_BUS_DEV_RESET -#define MSG_BUS_DEV_RESET 0x0c -#endif -#ifndef MSG_ABORT_TAG -#define MSG_ABORT_TAG 0x0d -#endif -#ifndef MSG_CLEAR_QUEUE -#define MSG_CLEAR_QUEUE 0x0e -#endif -#ifndef MSG_REL_RECOVERY -#define MSG_REL_RECOVERY 0x10 -#endif -#ifndef MSG_TERM_IO_PROC -#define MSG_TERM_IO_PROC 0x11 -#endif -#ifndef MSG_LUN_RESET -#define MSG_LUN_RESET 0x17 -#endif - +/* + * ISP24XX Immediate Notify + */ +typedef struct { + isphdr_t in_header; + uint32_t in_reserved; + uint16_t in_nphdl; + uint16_t in_reserved1; + uint16_t in_flags; + uint16_t in_srr_rxid; + uint16_t in_status; + uint8_t in_status_subcode; + uint8_t in_reserved2; + uint32_t in_rxid; + uint16_t in_srr_reloff_lo; + uint16_t in_srr_reloff_hi; + uint16_t in_srr_iu; + uint16_t in_srr_oxid; + uint8_t in_reserved3[18]; + uint8_t in_reserved4; + uint8_t in_vpindex; + uint32_t in_reserved5; + uint16_t in_portid_lo; + uint8_t in_portid_hi; + uint8_t in_reserved6; + uint16_t in_reserved7; + uint16_t in_oxid; +} in_fcentry_24xx_t; + +#define IN24XX_FLAG_PUREX_IOCB 0x1 +#define IN24XX_FLAG_GLOBAL_LOGOUT 0x2 + +#define IN24XX_LIP_RESET 0x0E +#define IN24XX_LINK_RESET 0x0F +#define IN24XX_PORT_LOGOUT 0x29 +#define IN24XX_PORT_CHANGED 0x2A +#define IN24XX_LINK_FAILED 0x2E +#define IN24XX_SRR_RCVD 0x45 +#define IN24XX_ELS_RCVD 0x46 /* + * login-affectin ELS received- check + * subcode for specific opcode + */ /* * Notify Acknowledge Entry structure */ @@ -235,6 +255,36 @@ typedef struct { #define NAFC_TVALID 0x10 /* task mangement response code is valid */ /* + * ISP24XX Notify Acknowledge + */ + +typedef struct { + isphdr_t na_header; + uint32_t na_handle; + uint16_t na_nphdl; + uint16_t na_reserved1; + uint16_t na_flags; + uint16_t na_srr_rxid; + uint16_t na_status; + uint8_t na_status_subcode; + uint8_t na_reserved2; + uint32_t na_rxid; + uint16_t na_srr_reloff_lo; + uint16_t na_srr_reloff_hi; + uint16_t na_srr_iu; + uint16_t na_srr_flags; + uint8_t na_reserved3[18]; + uint8_t na_reserved4; + uint8_t na_vpindex; + uint8_t na_srr_reject_vunique; + uint8_t na_srr_reject_explanation; + uint8_t na_srr_reject_code; + uint8_t na_reserved5; + uint8_t na_reserved6[6]; + uint16_t na_oxid; +} na_fcentry_24xx_t; + +/* * Accept Target I/O Entry structure */ #define ATIO_CDBLEN 26 @@ -399,6 +449,32 @@ typedef struct { tid &= ~0xffff; \ tid |= (inst << 16) +/* + * 24XX ATIO Definition + * + * This is *quite* different from other entry types. + * First of all, it has its own queue it comes in on. + * + * Secondly, it doesn't have a normal header. + * + * Thirdly, it's just a passthru of the FCP CMND IU + * which is recorded in big endian mode. + */ +typedef struct { + uint8_t at_type; + uint8_t at_count; + /* + * Task attribute in high four bits, + * the rest is the FCP CMND IU Length. + * NB: the command can extend past the + * length for a single queue entry. + */ + uint16_t at_ta_len; + uint32_t at_rxid; + fc_hdr_t at_hdr; + fcp_cmnd_iu_t at_cmnd; +} at7_entry_t; + /* * Continue Target I/O Entry structure @@ -409,8 +485,7 @@ typedef struct { */ typedef struct { isphdr_t ct_header; - uint16_t ct_reserved; -#define ct_syshandle ct_reserved /* we use this */ + uint16_t ct_syshandle; uint16_t ct_fwhandle; /* required by f/w */ uint8_t ct_lun; /* lun */ uint8_t ct_iid; /* initiator id */ @@ -425,14 +500,7 @@ typedef struct { uint32_t ct_resid; /* residual length */ uint16_t ct_timeout; uint16_t ct_seg_count; - /* - * This is so we can share tag name space with - * CTIO{2,3,4} with the minimum of pain. - */ - union { - ispds_t ct_a[ISP_RQDSEG]; - } _u; -#define ct_dataseg _u.ct_a + ispds_t ct_dataseg[ISP_RQDSEG]; } ct_entry_t; /* @@ -481,10 +549,10 @@ typedef struct { #define CT_BUS_ERROR 0x10 /* (FC Only) DMA PCI Error */ #define CT_PANIC 0x13 /* Unrecoverable Error */ #define CT_PHASE_ERROR 0x14 /* Bus phase sequence error */ -#define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */ #define CT_DATA_UNDER 0x15 /* (FC only) Data Underrun */ +#define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */ #define CT_TERMINATED 0x19 /* due to Terminate Transfer mbox cmd */ -#define CT_PORTNOTAVAIL 0x28 /* port not available */ +#define CT_PORTUNAVAIL 0x28 /* port not available */ #define CT_LOGOUT 0x29 /* port logout */ #define CT_PORTCHANGED 0x2A /* port changed */ #define CT_IDE 0x33 /* Initiator Detected Error */ @@ -513,8 +581,7 @@ typedef struct { #define MAXRESPLEN 26 typedef struct { isphdr_t ct_header; - uint16_t ct_reserved; - uint16_t ct_fwhandle; /* just to match CTIO */ + uint32_t ct_syshandle; uint8_t ct_lun; /* lun */ uint8_t ct_iid; /* initiator id */ uint16_t ct_rxid; /* response ID */ @@ -544,13 +611,10 @@ typedef struct { uint16_t ct_scsi_status; uint32_t ct_xfrlen; union { - ispds_t ct_a[ISP_RQDSEG_T2]; /* CTIO2 */ - ispds64_t ct_b[ISP_RQDSEG_T3]; /* CTIO3 */ - ispdslist_t ct_c; /* CTIO4 */ - } _u; -#define ct_dataseg _u.ct_a -#define ct_dataseg64 _u.ct_b -#define ct_dslist _u.ct_c + ispds_t ct_dataseg[ISP_RQDSEG_T2]; + ispds64_t ct_dataseg64[ISP_RQDSEG_T3]; + ispdslist_t ct_dslist; + } u; } m0; struct { uint16_t _reserved; @@ -572,8 +636,7 @@ typedef struct { typedef struct { isphdr_t ct_header; - uint16_t ct_reserved; - uint16_t ct_fwhandle; /* just to match CTIO */ + uint32_t ct_syshandle; uint16_t ct_iid; /* initiator id */ uint16_t ct_rxid; /* response ID */ uint16_t ct_flags; @@ -589,10 +652,10 @@ typedef struct { uint16_t ct_scsi_status; uint32_t ct_xfrlen; union { - ispds_t ct_a[ISP_RQDSEG_T2]; /* CTIO2 */ - ispds64_t ct_b[ISP_RQDSEG_T3]; /* CTIO3 */ - ispdslist_t ct_c; /* CTIO4 */ - } _u; + ispds_t ct_dataseg[ISP_RQDSEG_T2]; + ispds64_t ct_dataseg64[ISP_RQDSEG_T3]; + ispdslist_t ct_dslist; + } u; } m0; struct { uint16_t _reserved; @@ -615,16 +678,17 @@ typedef struct { /* * ct_flags values for CTIO2 */ -#define CT2_FLAG_MMASK 0x0003 #define CT2_FLAG_MODE0 0x0000 #define CT2_FLAG_MODE1 0x0001 #define CT2_FLAG_MODE2 0x0002 -#define CT2_DATA_IN CT_DATA_IN -#define CT2_DATA_OUT CT_DATA_OUT -#define CT2_NO_DATA CT_NO_DATA -#define CT2_DATAMASK CT_DATAMASK +#define CT2_FLAG_MMASK 0x0003 +#define CT2_DATA_IN 0x0040 +#define CT2_DATA_OUT 0x0080 +#define CT2_NO_DATA 0x00C0 +#define CT2_DATAMASK 0x00C0 #define CT2_CCINCR 0x0100 #define CT2_FASTPOST 0x0200 +#define CT2_CONFIRM 0x2000 #define CT2_TERMINATE 0x4000 #define CT2_SENDSTATUS 0x8000 @@ -643,12 +707,190 @@ typedef struct { #define CT2_DATA_UNDER 0x0800 /* + * ISP24XX CTIO + */ +#define MAXRESPLEN_24XX 24 +typedef struct { + isphdr_t ct_header; + uint32_t ct_syshandle; + uint16_t ct_nphdl; /* status on returned CTIOs */ + uint16_t ct_timeout; + uint16_t ct_seg_count; + uint8_t ct_vpindex; + uint8_t ct_xflags; + uint16_t ct_iid_lo; /* low 16 bits of portid */ + uint8_t ct_iid_hi; /* hi 8 bits of portid */ + uint8_t ct_reserved; + uint32_t ct_rxid; + uint16_t ct_senselen; /* mode 0 only */ + uint16_t ct_flags; + int32_t ct_resid; /* residual length */ + uint16_t ct_oxid; + uint16_t ct_scsi_status; /* modes 0 && 1 only */ + union { + struct { + uint32_t reloff; + uint32_t reserved0; + uint32_t ct_xfrlen; + uint32_t reserved1; + ispds64_t ds; + } m0; + struct { + uint16_t ct_resplen; + uint16_t reserved; + uint8_t ct_resp[MAXRESPLEN_24XX]; + } m1; + struct { + uint32_t reserved0; + uint32_t ct_datalen; + uint32_t reserved1; + ispds64_t ct_fcp_rsp_iudata; + } m2; + } rsp; +} ct7_entry_t; + +/* + * ct_flags values for CTIO7 + */ +#define CT7_DATA_IN 0x0002 +#define CT7_DATA_OUT 0x0001 +#define CT7_NO_DATA 0x0000 +#define CT7_DATAMASK 0x003 +#define CT7_DSD_ENABLE 0x0004 +#define CT7_CONF_STSFD 0x0010 +#define CT7_EXPLCT_CONF 0x0020 +#define CT7_FLAG_MODE0 0x0000 +#define CT7_FLAG_MODE1 0x0040 +#define CT7_FLAG_MODE7 0x0080 +#define CT7_FLAG_MMASK 0x00C0 +#define CT7_FASTPOST 0x0100 +#define CT7_ATTR_MASK 0x1e00 /* task attributes from atio7 */ +#define CT7_CONFIRM 0x2000 +#define CT7_TERMINATE 0x4000 +#define CT7_SENDSTATUS 0x8000 + +/* + * Type 7 CTIO status codes + */ +#define CT7_OK 0x01 /* completed without error */ +#define CT7_ABORTED 0x02 /* aborted by host */ +#define CT7_ERR 0x04 /* see sense data for error */ +#define CT7_INVAL 0x06 /* request for disabled lun */ +#define CT7_INVRXID 0x08 /* (FC only) Invalid RX_ID */ +#define CT7_DATA_OVER 0x09 /* (FC only) Data Overrun */ +#define CT7_TIMEOUT 0x0B /* timed out */ +#define CT7_RESET 0x0E /* LIP Rset Received */ +#define CT7_BUS_ERROR 0x10 /* DMA PCI Error */ +#define CT7_REASSY_ERR 0x11 /* DMA reassembly error */ +#define CT7_DATA_UNDER 0x15 /* (FC only) Data Underrun */ +#define CT7_PORTUNAVAIL 0x28 /* port not available */ +#define CT7_LOGOUT 0x29 /* port logout */ +#define CT7_PORTCHANGED 0x2A /* port changed */ +#define CT7_SRR 0x45 /* SRR Received */ + +/* + * Other 24XX related target IOCBs + */ + +/* + * ABTS Received + */ +typedef struct { + isphdr_t abts_header; + uint8_t abts_reserved0[6]; + uint16_t abts_nphdl; + uint16_t abts_reserved1; + uint16_t abts_sof; + uint32_t abts_rxid_abts; + uint16_t abts_did_lo; + uint8_t abts_did_hi; + uint8_t abts_r_ctl; + uint16_t abts_sid_lo; + uint8_t abts_sid_hi; + uint8_t abts_cs_ctl; + uint16_t abts_fs_ctl; + uint8_t abts_f_ctl; + uint8_t abts_type; + uint16_t abts_seq_cnt; + uint8_t abts_df_ctl; + uint8_t abts_seq_id; + uint16_t abts_rx_id; + uint16_t abts_ox_id; + uint32_t abts_param; + uint8_t abts_reserved2[16]; + uint32_t abts_rxid_task; +} abts_t; + +typedef struct { + isphdr_t abts_rsp_header; + uint32_t abts_rsp_handle; + uint16_t abts_rsp_status; + uint16_t abts_rsp_nphdl; + uint16_t abts_rsp_ctl_flags; + uint16_t abts_rsp_sof; + uint32_t abts_rsp_rxid_abts; + uint16_t abts_rsp_did_lo; + uint8_t abts_rsp_did_hi; + uint8_t abts_rsp_r_ctl; + uint16_t abts_rsp_sid_lo; + uint8_t abts_rsp_sid_hi; + uint8_t abts_rsp_cs_ctl; + uint16_t abts_rsp_f_ctl_lo; + uint8_t abts_rsp_f_ctl_hi; + uint8_t abts_rsp_type; + uint16_t abts_rsp_seq_cnt; + uint8_t abts_rsp_df_ctl; + uint8_t abts_rsp_seq_id; + uint16_t abts_rsp_rx_id; + uint16_t abts_rsp_ox_id; + uint32_t abts_rsp_param; + union { + struct { + uint16_t reserved; + uint8_t last_seq_id; + uint8_t seq_id_valid; + uint16_t aborted_rx_id; + uint16_t aborted_ox_id; + uint16_t high_seq_cnt; + uint16_t low_seq_cnt; + uint8_t reserved2[4]; + } ba_acc; + struct { + uint8_t vendor_unique; + uint8_t explanation; + uint8_t reason; + uint8_t reserved; + uint8_t reserved2[12]; + } ba_rjt; + struct { + uint8_t reserved[8]; + uint32_t subcode1; + uint32_t subcode2; + } rsp; + uint8_t reserved[16]; + } abts_rsp_payload; + uint32_t abts_rsp_rxid_task; +} abts_rsp_t; + +/* terminate this ABTS exchange */ +#define ISP24XX_ABTS_RSP_TERMINATE 0x01 + +#define ISP24XX_ABTS_RSP_COMPLETE 0x00 +#define ISP24XX_ABTS_RSP_RESET 0x04 +#define ISP24XX_ABTS_RSP_ABORTED 0x05 +#define ISP24XX_ABTS_RSP_TIMEOUT 0x06 +#define ISP24XX_ABTS_RSP_INVXID 0x08 +#define ISP24XX_ABTS_RSP_LOGOUT 0x29 +#define ISP24XX_ABTS_RSP_SUBCODE 0x31 + +/* * Debug macros */ #define ISP_TDQE(isp, msg, idx, arg) \ if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg) +#ifndef ISP_TOOLS /* * The functions below are for the publicly available * target mode functions that are internal to the Qlogic driver. @@ -657,7 +899,7 @@ typedef struct { /* * This function handles new response queue entry appropriate for target mode. */ -int isp_target_notify(ispsoftc_t *, void *, uint16_t *); +int isp_target_notify(ispsoftc_t *, void *, uint32_t *); /* * This function externalizes the ability to acknowledge an Immediate Notify @@ -690,7 +932,7 @@ int isp_target_put_atio(ispsoftc_t *, void *); * General routine to send a final CTIO for a command- used mostly for * local responses. */ -int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t); +int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint32_t); #define ECMD_SVALID 0x100 /* @@ -699,5 +941,5 @@ int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t); * Return nonzero if the interrupt that generated this event has been dismissed. */ int isp_target_async(ispsoftc_t *, int, int); - +#endif #endif /* _ISP_TARGET_H */ diff --git a/sys/dev/isp/isp_tpublic.h b/sys/dev/isp/isp_tpublic.h index d1a0b3d..519a43b 100644 --- a/sys/dev/isp/isp_tpublic.h +++ b/sys/dev/isp/isp_tpublic.h @@ -71,14 +71,29 @@ typedef enum { * in, and the external module to call back with a QIN_HBA_REG that * passes back the corresponding information. */ -#define QR_VERSION 10 +#define QR_VERSION 13 typedef struct { void * r_identity; void (*r_action)(qact_e, void *); char r_name[8]; int r_inst; int r_version; - enum { R_FC, R_SCSI } r_type; + struct { + enum { + R_FC, + R_SCSI + } r_type; + union { + struct { + uint64_t r_wwnn; + uint64_t r_wwpn; + } fc; + struct { + int r_iid; + } scsi; + } r_id; + } r_info; + void * r_private; } hba_register_t; /* @@ -104,7 +119,8 @@ typedef struct tmd_notify { uint64_t nt_iid; /* inititator id */ uint64_t nt_tgt; /* target id */ uint16_t nt_lun; /* logical unit */ - uint16_t nt_padding; /* padding */ + uint16_t : 15, + nt_need_ack : 1; /* this notify needs an ACK */ uint32_t nt_tagval; /* tag value */ tmd_ncode_t nt_ncode; /* action */ void * nt_lreserved; @@ -251,7 +267,7 @@ typedef struct { #define TMD_SENSELEN 18 #endif #ifndef QCDS -#define QCDS 8 +#define QCDS (sizeof (void *)) #endif typedef struct tmd_cmd { @@ -279,7 +295,7 @@ typedef struct tmd_cmd { uint32_t longs[QCDS / sizeof (uint32_t)]; uint16_t shorts[QCDS / sizeof (uint16_t)]; uint8_t bytes[QCDS]; - } cd_lreserved[3], cd_hreserved[3]; + } cd_lreserved[4], cd_hreserved[4]; } tmd_cmd_t; /* defined tags */ diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index 2ef8d51..a4461c7 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -44,7 +44,7 @@ #define MBOX_ABOUT_FIRMWARE 0x0008 /* 9 */ /* a */ - /* b */ +#define MBOX_LOAD_RISC_RAM 0x000b /* c */ #define MBOX_WRITE_RAM_WORD_EXTENDED 0x000d #define MBOX_CHECK_FIRMWARE 0x000e @@ -123,6 +123,7 @@ #define MBOX_GET_FIRMWARE_OPTIONS 0x0028 #define MBOX_SET_FIRMWARE_OPTIONS 0x0038 #define MBOX_GET_RESOURCE_COUNT 0x0042 +#define MBOX_REQUEST_OFFLINE_MODE 0x0043 #define MBOX_ENHANCED_GET_PDB 0x0047 #define MBOX_EXEC_COMMAND_IOCB_A64 0x0054 #define MBOX_INIT_FIRMWARE 0x0060 @@ -148,12 +149,14 @@ #define MBOX_DRIVER_HEARTBEAT 0x005B #define MBOX_FW_HEARTBEAT 0x005C -#define MBOX_GET_SET_DATA_RATE 0x005D /* 23XX only */ -#define MBGSD_GET_RATE 0 -#define MBGSD_SET_RATE 1 +#define MBOX_GET_SET_DATA_RATE 0x005D /* 24XX/23XX only */ +#define MBGSD_GET_RATE 0 +#define MBGSD_SET_RATE 1 +#define MBGSD_SET_RATE_NOW 2 /* 24XX only */ #define MBGSD_ONEGB 0 #define MBGSD_TWOGB 1 #define MBGSD_AUTO 2 +#define MBGSD_FOURGB 3 /* 24XX only */ #define ISP2100_SET_PCI_PARAM 0x00ff @@ -173,6 +176,10 @@ #define MBOX_LOOP_ID_USED 0x4008 #define MBOX_ALL_IDS_USED 0x4009 #define MBOX_NOT_LOGGED_IN 0x400A +/* pseudo mailbox completion codes */ +#define MBOX_REGS_BUSY 0x6000 /* registers in use */ +#define MBOX_TIMEOUT 0x6001 /* command timed out */ + #define MBLOGALL 0x000f #define MBLOGNONE 0x0000 #define MBLOGMASK(x) ((x) & 0xf) @@ -199,6 +206,8 @@ #define ASYNC_PDB_CHANGED 0x8014 #define ASYNC_CHANGE_NOTIFY 0x8015 #define ASYNC_LIP_F8 0x8016 +#define ASYNC_LIP_ERROR 0x8017 +#define ASYNC_SECURITY_UPDATE 0x801B #define ASYNC_CMD_CMPLT 0x8020 #define ASYNC_CTIO_DONE 0x8021 #define ASYNC_IP_XMIT_DONE 0x8022 @@ -221,6 +230,8 @@ #define ISP_CONN_LOOPBACK 5 #define ASYNC_RIO_RESP 0x8040 #define ASYNC_RIO_COMP 0x8042 +#define ASYNC_RCV_ERR 0x8048 + /* * 2.01.31 2200 Only. Need Bit 13 in Mailbox 1 for Set Firmware Options * mailbox command to enable this. @@ -228,20 +239,14 @@ #define ASYNC_QFULL_SENT 0x8049 /* - * Mailbox Usages + * 24XX only */ +#define ASYNC_RJT_SENT 0x8049 -#define WRITE_REQUEST_QUEUE_IN_POINTER(isp, value) \ - ISP_WRITE(isp, isp->isp_rqstinrp, value) - -#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \ - ISP_READ(isp, isp->isp_rqstoutrp) - -#define READ_RESPONSE_QUEUE_IN_POINTER(isp) \ - ISP_READ(isp, isp->isp_respinrp) - -#define WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, value) \ - ISP_WRITE(isp, isp->isp_respoutrp, value) +/* + * All IOCB Queue entries are this size + */ +#define QENTRY_LEN 64 /* * Command Structure Definitions @@ -288,6 +293,7 @@ typedef struct { #define RQSFLAG_FULL 0x02 #define RQSFLAG_BADHEADER 0x04 #define RQSFLAG_BADPACKET 0x08 +#define RQSFLAG_MASK 0x0f /* RQS entry_type definitions */ #define RQSTYPE_REQUEST 0x01 @@ -307,11 +313,13 @@ typedef struct { #define RQSTYPE_CTIO1 0x0f /* Target Mode */ #define RQSTYPE_STATUS_CONT 0x10 #define RQSTYPE_T2RQS 0x11 +#define RQSTYPE_CTIO7 0x12 #define RQSTYPE_IP_XMIT 0x13 +#define RQSTYPE_TSK_MGMT 0x14 #define RQSTYPE_T4RQS 0x15 #define RQSTYPE_ATIO2 0x16 /* Target Mode */ #define RQSTYPE_CTIO2 0x17 /* Target Mode */ -#define RQSTYPE_CSET0 0x18 +#define RQSTYPE_T7RQS 0x18 #define RQSTYPE_T3RQS 0x19 #define RQSTYPE_IP_XMIT_64 0x1b #define RQSTYPE_CTIO4 0x1e /* Target Mode */ @@ -320,6 +328,12 @@ typedef struct { #define RQSTYPE_RIO2 0x22 #define RQSTYPE_IP_RECV 0x23 #define RQSTYPE_IP_RECV_CONT 0x24 +#define RQSTYPE_CT_PASSTHRU 0x29 +#define RQSTYPE_ABORT_IO 0x33 +#define RQSTYPE_T6RQS 0x48 +#define RQSTYPE_LOGIN 0x52 +#define RQSTYPE_ABTS_RCVD 0x54 /* 24XX only */ +#define RQSTYPE_ABTS_RSP 0x55 /* 24XX only */ #define ISP_RQDSEG 4 @@ -329,7 +343,6 @@ typedef struct { uint8_t req_lun_trn; uint8_t req_target; uint16_t req_cdblen; -#define req_modifier req_cdblen /* marker packet */ uint16_t req_flags; uint16_t req_reserved; uint16_t req_time; @@ -337,13 +350,33 @@ typedef struct { uint8_t req_cdb[12]; ispds_t req_dataseg[ISP_RQDSEG]; } ispreq_t; - -#define ispreq64_t ispreqt3_t /* same as.... */ #define ISP_RQDSEG_A64 2 -/* - * A request packet can also be a marker packet. - */ +typedef struct { + isphdr_t mrk_header; + uint32_t mrk_handle; + uint8_t mrk_reserved0; + uint8_t mrk_target; + uint16_t mrk_modifier; + uint16_t mrk_flags; + uint16_t mrk_lun; + uint8_t mrk_reserved1[48]; +} isp_marker_t; + +typedef struct { + isphdr_t mrk_header; + uint32_t mrk_handle; + uint16_t mrk_nphdl; + uint8_t mrk_modifier; + uint8_t mrk_reserved0; + uint8_t mrk_reserved1; + uint8_t mrk_vphdl; + uint16_t mrk_reserved2; + uint8_t mrk_lun[8]; + uint8_t mrk_reserved3[40]; +} isp_marker_24xx_t; + + #define SYNC_DEVICE 0 #define SYNC_TARGET 1 #define SYNC_ALL 2 @@ -357,7 +390,7 @@ typedef struct { uint8_t req_target; uint16_t req_scclun; uint16_t req_flags; - uint16_t _res2; + uint16_t req_reserved; uint16_t req_time; uint16_t req_seg_count; uint8_t req_cdb[16]; @@ -371,7 +404,7 @@ typedef struct { uint16_t req_target; uint16_t req_scclun; uint16_t req_flags; - uint16_t _res2; + uint16_t req_reserved; uint16_t req_time; uint16_t req_seg_count; uint8_t req_cdb[16]; @@ -387,13 +420,14 @@ typedef struct { uint8_t req_target; uint16_t req_scclun; uint16_t req_flags; - uint16_t _res2; + uint16_t req_reserved; uint16_t req_time; uint16_t req_seg_count; uint8_t req_cdb[16]; uint32_t req_totalcnt; ispds64_t req_dataseg[ISP_RQDSEG_T3]; } ispreqt3_t; +#define ispreq64_t ispreqt3_t /* same as.... */ typedef struct { isphdr_t req_header; @@ -401,7 +435,7 @@ typedef struct { uint16_t req_target; uint16_t req_scclun; uint16_t req_flags; - uint16_t _res2; + uint16_t req_reserved; uint16_t req_time; uint16_t req_seg_count; uint8_t req_cdb[16]; @@ -437,16 +471,86 @@ typedef struct { uint8_t req_target; uint16_t req_cdblen; uint16_t req_flags; - uint16_t _res1; + uint16_t req_reserved; uint16_t req_time; uint16_t req_seg_count; uint8_t req_cdb[44]; } ispextreq_t; +/* 24XX only */ +typedef struct { + uint16_t fcd_length; + uint16_t fcd_a1500; + uint16_t fcd_a3116; + uint16_t fcd_a4732; + uint16_t fcd_a6348; +} fcp_cmnd_ds_t; + +typedef struct { + isphdr_t req_header; + uint32_t req_handle; + uint16_t req_nphdl; + uint16_t req_time; + uint16_t req_seg_count; + uint16_t req_fc_rsp_dsd_length; + uint8_t req_lun[8]; + uint16_t req_flags; + uint16_t req_fc_cmnd_dsd_length; + uint16_t req_fc_cmnd_dsd_a1500; + uint16_t req_fc_cmnd_dsd_a3116; + uint16_t req_fc_cmnd_dsd_a4732; + uint16_t req_fc_cmnd_dsd_a6348; + uint16_t req_fc_rsp_dsd_a1500; + uint16_t req_fc_rsp_dsd_a3116; + uint16_t req_fc_rsp_dsd_a4732; + uint16_t req_fc_rsp_dsd_a6348; + uint32_t req_totalcnt; + uint16_t req_tidlo; + uint8_t req_tidhi; + uint8_t req_vpidx; + ispds64_t req_dataseg; +} ispreqt6_t; + +typedef struct { + isphdr_t req_header; + uint32_t req_handle; + uint16_t req_nphdl; + uint16_t req_time; + uint16_t req_seg_count; + uint16_t req_reserved; + uint8_t req_lun[8]; + uint8_t req_alen_datadir; + uint8_t req_task_management; + uint8_t req_task_attribute; + uint8_t req_crn; + uint8_t req_cdb[16]; + uint32_t req_dl; + uint16_t req_tidlo; + uint8_t req_tidhi; + uint8_t req_vpidx; + ispds64_t req_dataseg; +} ispreqt7_t; + +/* I/O Abort Structure */ +typedef struct { + isphdr_t abrt_header; + uint32_t abrt_handle; + uint16_t abrt_nphdl; + uint16_t abrt_options; + uint32_t abrt_cmd_handle; + uint8_t abrt_reserved[32]; + uint16_t abrt_tidlo; + uint8_t abrt_tidhi; + uint8_t abrt_vpidx; + uint8_t abrt_reserved1[12]; +} isp24xx_abrt_t; +#define ISP24XX_ABRT_NO_ABTS 0x01 /* don't actually send an ABTS */ +#define ISP24XX_ABRT_ENXIO 0x31 /* in nphdl on return */ + #define ISP_CDSEG 7 typedef struct { isphdr_t req_header; - uint32_t _res1; + uint32_t req_reserved; ispds_t req_dataseg[ISP_CDSEG]; } ispcontreq_t; @@ -471,11 +575,33 @@ typedef struct { uint8_t req_sense_data[32]; } ispstatusreq_t; +/* + * Status Continuation + */ typedef struct { isphdr_t req_header; uint8_t req_sense_data[60]; } ispstatus_cont_t; +/* + * 24XX Type 0 status + */ +typedef struct { + isphdr_t req_header; + uint32_t req_handle; + uint16_t req_completion_status; + uint16_t req_oxid; + uint32_t req_resid; + uint16_t req_reserved0; + uint16_t req_state_flags; + uint16_t req_reserved1; + uint16_t req_scsi_status; + uint32_t req_fcp_residual; + uint32_t req_sense_len; + uint32_t req_response_len; + uint8_t req_rsp_sense[28]; +} isp24xx_statusreq_t; + /* * For Qlogic 2X00, the high order byte of SCSI status has * additional meaning. @@ -486,6 +612,25 @@ typedef struct { #define RQCS_SV 0x200 /* Sense Length Valid */ #define RQCS_RV 0x100 /* FCP Response Length Valid */ +/* + * CT Passthru IOCB + */ +typedef struct { + isphdr_t ctp_header; + uint32_t ctp_handle; + uint16_t ctp_status; + uint16_t ctp_nphdl; /* n-port handle */ + uint16_t ctp_cmd_cnt; /* Command DSD count */ + uint16_t ctp_vpidx; /* low 8 bits */ + uint16_t ctp_time; + uint16_t ctp_reserved0; + uint16_t ctp_rsp_cnt; /* Response DSD count */ + uint16_t ctp_reserved1[5]; + uint32_t ctp_rsp_bcnt; /* Response byte count */ + uint32_t ctp_cmd_bcnt; /* Command byte count */ + ispds64_t ctp_dataseg[2]; +} isp_ct_pt_t; + /* * Completion Status Codes. */ @@ -530,6 +675,13 @@ typedef struct { #define RQCS_PORT_CHANGED 0x002A #define RQCS_PORT_BUSY 0x002B +/* 24XX Only Completion Codes */ +#define RQCS_24XX_DRE 0x0011 /* data reassembly error */ +#define RQCS_24XX_TABORT 0x0013 /* aborted by target */ +#define RQCS_24XX_ENOMEM 0x002C /* f/w resource unavailable */ +#define RQCS_24XX_TMO 0x0030 /* task management overrun */ + + /* * 1X00 specific State Flags */ @@ -587,6 +739,7 @@ typedef struct { /* * About Firmware returns an 'attribute' word in mailbox 6. + * These attributes are for 2200 and 2300. */ #define ISP_FW_ATTR_TMODE 0x01 #define ISP_FW_ATTR_SCCLUN 0x02 @@ -598,8 +751,14 @@ typedef struct { #define ISP_FW_ATTR_VI_SOLARIS 0x80 #define ISP_FW_ATTR_2KLOGINS 0x100 /* XXX: just a guess */ -#define IS_2KLOGIN(isp) \ - (IS_FC(isp) && (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS)) +/* and these are for the 2400 */ +#define ISP2400_FW_ATTR_CLASS2 (1 << 0) +#define ISP2400_FW_ATTR_IP (1 << 1) +#define ISP2400_FW_ATTR_MULTIID (1 << 2) +#define ISP2400_FW_ATTR_SB2 (1 << 3) +#define ISP2400_FW_ATTR_T10CRC (1 << 4) +#define ISP2400_FW_ATTR_VI (1 << 5) +#define ISP2400_FW_ATTR_EXPFW (1 << 13) /* * Reduced Interrupt Operation Response Queue Entreis @@ -616,7 +775,7 @@ typedef struct { } isp_rio2_t; /* - * FC (ISP2100) specific data structures + * FC (ISP2100/ISP2200/ISP2300/ISP2400) specific data structures */ /* @@ -624,9 +783,9 @@ typedef struct { * * Version One (prime) format. */ -typedef struct isp_icb { +typedef struct { uint8_t icb_version; - uint8_t _reserved0; + uint8_t icb_reserved0; uint16_t icb_fwoptions; uint16_t icb_maxfrmlen; uint16_t icb_maxalloc; @@ -648,42 +807,48 @@ typedef struct isp_icb { uint8_t icb_ccnt; uint8_t icb_icnt; uint16_t icb_lunetimeout; - uint16_t _reserved1; + uint16_t icb_reserved1; uint16_t icb_xfwoptions; uint8_t icb_racctimer; uint8_t icb_idelaytimer; uint16_t icb_zfwoptions; - uint16_t _reserved2[13]; + uint16_t icb_reserved2[13]; } isp_icb_t; + #define ICB_VERSION1 1 -#define ICBOPT_HARD_ADDRESS 0x0001 -#define ICBOPT_FAIRNESS 0x0002 -#define ICBOPT_FULL_DUPLEX 0x0004 -#define ICBOPT_FAST_POST 0x0008 -#define ICBOPT_TGT_ENABLE 0x0010 -#define ICBOPT_INI_DISABLE 0x0020 -#define ICBOPT_INI_ADISC 0x0040 -#define ICBOPT_INI_TGTTYPE 0x0080 -#define ICBOPT_PDBCHANGE_AE 0x0100 -#define ICBOPT_NOLIP 0x0200 -#define ICBOPT_SRCHDOWN 0x0400 -#define ICBOPT_PREVLOOP 0x0800 -#define ICBOPT_STOP_ON_QFULL 0x1000 -#define ICBOPT_FULL_LOGIN 0x2000 -#define ICBOPT_BOTH_WWNS 0x4000 #define ICBOPT_EXTENDED 0x8000 +#define ICBOPT_BOTH_WWNS 0x4000 +#define ICBOPT_FULL_LOGIN 0x2000 +#define ICBOPT_STOP_ON_QFULL 0x1000 /* 2200/2100 only */ +#define ICBOPT_PREVLOOP 0x0800 +#define ICBOPT_SRCHDOWN 0x0400 +#define ICBOPT_NOLIP 0x0200 +#define ICBOPT_PDBCHANGE_AE 0x0100 +#define ICBOPT_INI_TGTTYPE 0x0080 +#define ICBOPT_INI_ADISC 0x0040 +#define ICBOPT_INI_DISABLE 0x0020 +#define ICBOPT_TGT_ENABLE 0x0010 +#define ICBOPT_FAST_POST 0x0008 +#define ICBOPT_FULL_DUPLEX 0x0004 +#define ICBOPT_FAIRNESS 0x0002 +#define ICBOPT_HARD_ADDRESS 0x0001 +#define ICBXOPT_NO_LOGOUT 0x8000 /* no logout on link failure */ +#define ICBXOPT_FCTAPE_CCQ 0x4000 /* FC-Tape Command Queueing */ +#define ICBXOPT_FCTAPE_CONFIRM 0x2000 +#define ICBXOPT_FCTAPE 0x1000 #define ICBXOPT_CLASS2_ACK0 0x0200 #define ICBXOPT_CLASS2 0x0100 -#define ICBXOPT_LOOP_ONLY (0 << 4) -#define ICBXOPT_PTP_ONLY (1 << 4) -#define ICBXOPT_LOOP_2_PTP (2 << 4) -#define ICBXOPT_PTP_2_LOOP (3 << 4) - +#define ICBXOPT_NO_PLAY 0x0080 /* don't play if can't get hard addr */ +#define ICBXOPT_TOPO_MASK 0x0070 +#define ICBXOPT_LOOP_ONLY 0x0000 +#define ICBXOPT_PTP_ONLY 0x0010 +#define ICBXOPT_LOOP_2_PTP 0x0020 +#define ICBXOPT_PTP_2_LOOP 0x0030 /* * The lower 4 bits of the xfwoptions field are the OPERATION MODE bits. - * RIO is not defined for the 23XX cards + * RIO is not defined for the 23XX cards (just 2200) */ #define ICBXOPT_RIO_OFF 0 #define ICBXOPT_RIO_16BIT 1 @@ -693,14 +858,60 @@ typedef struct isp_icb { #define ICBXOPT_ZIO 5 #define ICBXOPT_TIMER_MASK 0x7 -#define ICBZOPT_ENA_RDXFR_RDY 0x01 -#define ICBZOPT_ENA_OOF (1 << 6) /* out of order frame handling */ -#define ICBZOPT_50_OHM 0x0200 -/* These 3 only apply to the 2300 */ -#define ICBZOPT_RATE_ONEGB (MBGSD_ONEGB << 14) -#define ICBZOPT_RATE_TWOGB (MBGSD_TWOGB << 14) -#define ICBZOPT_RATE_AUTO (MBGSD_AUTO << 14) - +#define ICBZOPT_RATE_MASK 0xC000 +#define ICBZOPT_RATE_ONEGB 0x0000 +#define ICBZOPT_RATE_AUTO 0x8000 +#define ICBZOPT_RATE_TWOGB 0x4000 +#define ICBZOPT_50_OHM 0x2000 +#define ICBZOPT_ENA_OOF 0x0040 /* out of order frame handling */ +#define ICBZOPT_RSPSZ_MASK 0x0030 +#define ICBZOPT_RSPSZ_24 0x0000 +#define ICBZOPT_RSPSZ_12 0x0010 +#define ICBZOPT_RSPSZ_24A 0x0020 +#define ICBZOPT_RSPSZ_32 0x0030 +#define ICBZOPT_SOFTID 0x0002 +#define ICBZOPT_ENA_RDXFR_RDY 0x0001 + +/* 2400 F/W options */ +#define ICB2400_OPT1_BOTH_WWNS 0x00004000 +#define ICB2400_OPT1_FULL_LOGIN 0x00002000 +#define ICB2400_OPT1_PREVLOOP 0x00000800 +#define ICB2400_OPT1_SRCHDOWN 0x00000400 +#define ICB2400_OPT1_NOLIP 0x00000200 +#define ICB2400_OPT1_INI_DISABLE 0x00000020 +#define ICB2400_OPT1_TGT_ENABLE 0x00000010 +#define ICB2400_OPT1_FULL_DUPLEX 0x00000004 +#define ICB2400_OPT1_FAIRNESS 0x00000002 +#define ICB2400_OPT1_HARD_ADDRESS 0x00000001 + +#define ICB2400_OPT2_FCTAPE 0x00001000 +#define ICB2400_OPT2_CLASS2_ACK0 0x00000200 +#define ICB2400_OPT2_CLASS2 0x00000100 +#define ICB2400_OPT2_NO_PLAY 0x00000080 +#define ICB2400_OPT2_TOPO_MASK 0x00000070 +#define ICB2400_OPT2_LOOP_ONLY 0x00000000 +#define ICB2400_OPT2_PTP_ONLY 0x00000010 +#define ICB2400_OPT2_LOOP_2_PTP 0x00000020 +#define ICB2400_OPT2_PTP_2_LOOP 0x00000030 +#define ICB2400_OPT2_TIMER_MASK 0x00000007 +#define ICB2400_OPT2_ZIO 0x00000005 +#define ICB2400_OPT2_ZIO1 0x00000006 + +#define ICB2400_OPT3_75_OHM 0x00010000 +#define ICB2400_OPT3_RATE_MASK 0x0000E000 +#define ICB2400_OPT3_RATE_ONEGB 0x00000000 +#define ICB2400_OPT3_RATE_TWOGB 0x00002000 +#define ICB2400_OPT3_RATE_AUTO 0x00004000 +#define ICB2400_OPT3_RATE_FOURGB 0x00006000 +#define ICB2400_OPT3_ENA_OOF_XFRDY 0x00000200 +#define ICB2400_OPT3_NO_LOCAL_PLOGI 0x00000080 +#define ICB2400_OPT3_ENA_OOF 0x00000040 +/* note that a response size flag of zero is reserved! */ +#define ICB2400_OPT3_RSPSZ_MASK 0x00000030 +#define ICB2400_OPT3_RSPSZ_12 0x00000010 +#define ICB2400_OPT3_RSPSZ_24 0x00000020 +#define ICB2400_OPT3_RSPSZ_32 0x00000030 +#define ICB2400_OPT3_SOFTID 0x00000002 #define ICB_MIN_FRMLEN 256 #define ICB_MAX_FRMLEN 2112 @@ -714,6 +925,41 @@ typedef struct isp_icb { #define ICB_LUN_ENABLE_TOV 180 +/* + * And somebody at QLogic had a great idea that you could just change + * the structure *and* keep the version number the same as the other cards. + */ +typedef struct { + uint16_t icb_version; + uint16_t icb_reserved0; + uint16_t icb_maxfrmlen; + uint16_t icb_execthrottle; + uint16_t icb_xchgcnt; + uint16_t icb_hardaddr; + uint8_t icb_portname[8]; + uint8_t icb_nodename[8]; + uint16_t icb_rspnsin; + uint16_t icb_rqstout; + uint16_t icb_retry_count; + uint16_t icb_priout; + uint16_t icb_rsltqlen; + uint16_t icb_rqstqlen; + uint16_t icb_ldn_nols; + uint16_t icb_prqstqlen; + uint16_t icb_rqstaddr[4]; + uint16_t icb_respaddr[4]; + uint16_t icb_priaddr[4]; + uint16_t icb_reserved1[4]; + uint16_t icb_atio_in; + uint16_t icb_atioqlen; + uint16_t icb_atioqaddr[4]; + uint16_t icb_idelaytimer; + uint16_t icb_logintime; + uint32_t icb_fwoptions1; + uint32_t icb_fwoptions2; + uint32_t icb_fwoptions3; + uint16_t icb_reserved2[12]; +} isp_icb_2400_t; #define RQRSP_ADDR0015 0 #define RQRSP_ADDR1631 1 @@ -751,22 +997,6 @@ typedef struct isp_icb { ((uint64_t) array[ICB_NNM7] << 56) /* - * FC-AL Position Map - * - * This is an at most 128 byte map that returns either - * the LILP or Firmware generated list of ports. - * - * We deviate a bit from the returned qlogic format to - * use an extra bit to say whether this was a LILP or - * f/w generated map. - */ -typedef struct { - uint8_t fwmap : 1, - count : 7; - uint8_t map[127]; -} fcpos_map_t; - -/* * Port Data Base Element */ @@ -774,7 +1004,6 @@ typedef struct { uint16_t pdb_options; uint8_t pdb_mstate; uint8_t pdb_sstate; -#define BITS2WORD(x) ((x)[0] << 16 | (x)[3] << 8 | (x)[2]) uint8_t pdb_hardaddr_bits[4]; uint8_t pdb_portid_bits[4]; uint8_t pdb_nodename[8]; @@ -810,7 +1039,7 @@ typedef struct { uint16_t pdb_loopid; uint16_t pdb_il_ptr; uint16_t pdb_sl_ptr; -} isp_pdb_t; +} isp_pdb_21xx_t; #define PDB_OPTIONS_XMITTING (1<<11) #define PDB_OPTIONS_LNKXMIT (1<<10) @@ -835,35 +1064,109 @@ typedef struct { #define SVC3_ROLE_MASK 0x30 #define SVC3_ROLE_SHIFT 4 +#define BITS2WORD(x) ((x)[0] << 16 | (x)[3] << 8 | (x)[2]) +#define BITS2WORD_24XX(x) ((x)[0] << 16 | (x)[1] << 8 | (x)[2]) + /* - * CT definition - * - * This is as the QLogic f/w documentations defines it- which is just opposite, - * bit wise, from what the specification defines it as. Additionally, the - * ct_response and ct_resid (really from FC-GS-2) need to be byte swapped. - */ - -typedef struct { - uint8_t ct_revision; - uint8_t ct_portid[3]; - uint8_t ct_fcs_type; - uint8_t ct_fcs_subtype; - uint8_t ct_options; - uint8_t ct_res0; - uint16_t ct_response; - uint16_t ct_resid; - uint8_t ct_res1; - uint8_t ct_reason; - uint8_t ct_explanation; - uint8_t ct_vunique; -} ct_hdr_t; -#define FS_ACC 0x8002 -#define FS_RJT 0x8001 - -#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP "Out of Order Delivery" */ -#define FC4_SCSI 8 /* SCSI-3 via Fivre Channel Protocol (FCP) */ -#define FC4_FC_SVC 0x20 /* Fibre Channel Services */ + * Port Data Base Element- 24XX cards + */ +typedef struct { + uint16_t pdb_flags; + uint8_t pdb_curstate; + uint8_t pdb_laststate; + uint8_t pdb_hardaddr_bits[4]; + uint8_t pdb_portid_bits[4]; +#define pdb_nxt_seqid_2400 pdb_portid_bits[3] + uint16_t pdb_retry_timer; + uint16_t pdb_handle; + uint16_t pdb_rcv_dsize; + uint16_t pdb_reserved0; + uint16_t pdb_prli_svc0; + uint16_t pdb_prli_svc3; + uint8_t pdb_portname[8]; + uint8_t pdb_nodename[8]; + uint8_t pdb_reserved1[24]; +} isp_pdb_24xx_t; + +#define PDB2400_TID_SUPPORTED 0x4000 +#define PDB2400_FC_TAPE 0x0080 +#define PDB2400_CLASS2_ACK0 0x0040 +#define PDB2400_FCP_CONF 0x0020 +#define PDB2400_CLASS2 0x0010 +#define PDB2400_ADDR_VALID 0x0002 +/* + * Common elements from the above two structures that are actually useful to us. + */ +typedef struct { + uint16_t handle; + uint16_t reserved; + uint32_t s3_role : 8, + portid : 24; + uint8_t portname[8]; + uint8_t nodename[8]; +} isp_pdb_t; + +/* + * ISP24XX- Login/Logout Port IOCB + */ +typedef struct { + isphdr_t plogx_header; + uint32_t plogx_handle; + uint16_t plogx_status; + uint16_t plogx_nphdl; + uint16_t plogx_flags; + uint16_t plogx_vphdl; /* low 8 bits */ + uint16_t plogx_portlo; /* low 16 bits */ + uint16_t plogx_rspsz_porthi; + struct { + uint16_t lo16; + uint16_t hi16; + } plogx_ioparm[11]; +} isp_plogx_t; + +#define PLOGX_STATUS_OK 0x00 +#define PLOGX_STATUS_UNAVAIL 0x28 +#define PLOGX_STATUS_LOGOUT 0x29 +#define PLOGX_STATUS_IOCBERR 0x31 + +#define PLOGX_IOCBERR_NOLINK 0x01 +#define PLOGX_IOCBERR_NOIOCB 0x02 +#define PLOGX_IOCBERR_NOXGHG 0x03 +#define PLOGX_IOCBERR_FAILED 0x04 /* further info in IOPARM 1 */ +#define PLOGX_IOCBERR_NOFABRIC 0x05 +#define PLOGX_IOCBERR_NOTREADY 0x07 +#define PLOGX_IOCBERR_NOLOGIN 0x08 /* further info in IOPARM 1 */ +#define PLOGX_IOCBERR_NOPCB 0x0a +#define PLOGX_IOCBERR_REJECT 0x18 /* further info in IOPARM 1 */ +#define PLOGX_IOCBERR_EINVAL 0x19 /* further info in IOPARM 1 */ +#define PLOGX_IOCBERR_PORTUSED 0x1a /* further info in IOPARM 1 */ +#define PLOGX_IOCBERR_HNDLUSED 0x1b /* further info in IOPARM 1 */ +#define PLOGX_IOCBERR_NOHANDLE 0x1c +#define PLOGX_IOCBERR_NOFLOGI 0x1f /* further info in IOPARM 1 */ + +#define PLOGX_FLG_CMD_MASK 0xf +#define PLOGX_FLG_CMD_PLOGI 0 +#define PLOGX_FLG_CMD_PRLI 1 +#define PLOGX_FLG_CMD_PDISC 2 +#define PLOGX_FLG_CMD_LOGO 8 +#define PLOGX_FLG_CMD_PRLO 9 +#define PLOGX_FLG_CMD_TPRLO 10 + +#define PLOGX_FLG_COND_PLOGI 0x10 /* if with PLOGI */ +#define PLOGX_FLG_IMPLICIT 0x10 /* if with LOGO, PRLO, TPRLO */ +#define PLOGX_FLG_SKIP_PRLI 0x20 /* if with PLOGI */ +#define PLOGX_FLG_IMPLICIT_LOGO_ALL 0x20 /* if with LOGO */ +#define PLOGX_FLG_EXPLICIT_LOGO 0x40 /* if with LOGO */ +#define PLOGX_FLG_COMMON_FEATURES 0x80 /* if with PLOGI */ +#define PLOGX_FLG_FREE_NPHDL 0x80 /* if with with LOGO */ + +#define PLOGX_FLG_CLASS2 0x100 /* if with PLOGI */ +#define PLOGX_FLG_FCP2_OVERRIDE 0x200 /* if with PRLOG, PRLI */ + +/* + * Simple Name Server Data Structures + */ #define SNS_GA_NXT 0x100 #define SNS_GPN_ID 0x112 #define SNS_GNN_ID 0x113 @@ -872,61 +1175,61 @@ typedef struct { #define SNS_RFT_ID 0x217 typedef struct { uint16_t snscb_rblen; /* response buffer length (words) */ - uint16_t snscb_res0; + uint16_t snscb_reserved0; uint16_t snscb_addr[4]; /* response buffer address */ uint16_t snscb_sblen; /* subcommand buffer length (words) */ - uint16_t snscb_res1; + uint16_t snscb_reserved1; uint16_t snscb_data[1]; /* variable data */ } sns_screq_t; /* Subcommand Request Structure */ typedef struct { uint16_t snscb_rblen; /* response buffer length (words) */ - uint16_t snscb_res0; + uint16_t snscb_reserved0; uint16_t snscb_addr[4]; /* response buffer address */ uint16_t snscb_sblen; /* subcommand buffer length (words) */ - uint16_t snscb_res1; + uint16_t snscb_reserved1; uint16_t snscb_cmd; - uint16_t snscb_res2; - uint32_t snscb_res3; + uint16_t snscb_reserved2; + uint32_t snscb_reserved3; uint32_t snscb_port; } sns_ga_nxt_req_t; #define SNS_GA_NXT_REQ_SIZE (sizeof (sns_ga_nxt_req_t)) typedef struct { uint16_t snscb_rblen; /* response buffer length (words) */ - uint16_t snscb_res0; + uint16_t snscb_reserved0; uint16_t snscb_addr[4]; /* response buffer address */ uint16_t snscb_sblen; /* subcommand buffer length (words) */ - uint16_t snscb_res1; + uint16_t snscb_reserved1; uint16_t snscb_cmd; - uint16_t snscb_res2; - uint32_t snscb_res3; + uint16_t snscb_reserved2; + uint32_t snscb_reserved3; uint32_t snscb_portid; } sns_gxn_id_req_t; #define SNS_GXN_ID_REQ_SIZE (sizeof (sns_gxn_id_req_t)) typedef struct { uint16_t snscb_rblen; /* response buffer length (words) */ - uint16_t snscb_res0; + uint16_t snscb_reserved0; uint16_t snscb_addr[4]; /* response buffer address */ uint16_t snscb_sblen; /* subcommand buffer length (words) */ - uint16_t snscb_res1; + uint16_t snscb_reserved1; uint16_t snscb_cmd; uint16_t snscb_mword_div_2; - uint32_t snscb_res3; + uint32_t snscb_reserved3; uint32_t snscb_fc4_type; } sns_gid_ft_req_t; #define SNS_GID_FT_REQ_SIZE (sizeof (sns_gid_ft_req_t)) typedef struct { uint16_t snscb_rblen; /* response buffer length (words) */ - uint16_t snscb_res0; + uint16_t snscb_reserved0; uint16_t snscb_addr[4]; /* response buffer address */ uint16_t snscb_sblen; /* subcommand buffer length (words) */ - uint16_t snscb_res1; + uint16_t snscb_reserved1; uint16_t snscb_cmd; - uint16_t snscb_res2; - uint32_t snscb_res3; + uint16_t snscb_reserved2; + uint32_t snscb_reserved3; uint32_t snscb_port; uint32_t snscb_fc4_types[8]; } sns_rft_id_req_t; @@ -980,7 +1283,68 @@ typedef struct { } snscb_ports[1]; } sns_gid_ft_rsp_t; #define SNS_GID_FT_RESP_SIZE(x) ((sizeof (sns_gid_ft_rsp_t)) + ((x - 1) << 2)) - #define SNS_RFT_ID_RESP_SIZE (sizeof (ct_hdr_t)) +/* + * Other Misc Structures + */ + +/* ELS Pass Through */ +typedef struct { + isphdr_t els_hdr; + uint32_t els_handle; + uint16_t els_status; + uint16_t els_nphdl; + uint16_t els_xmit_dsd_count; /* outgoing only */ + uint8_t els_vphdl; + uint8_t els_sof; + uint32_t els_rxid; + uint16_t els_recv_dsd_count; /* outgoing only */ + uint8_t els_opcode; + uint8_t els_reserved1; + uint8_t els_did_lo; + uint8_t els_did_mid; + uint8_t els_did_hi; + uint8_t els_reserved2; + uint16_t els_reserved3; + uint16_t els_ctl_flags; + union { + struct { + uint32_t _els_bytecnt; + uint32_t _els_subcode1; + uint32_t _els_subcode2; + uint8_t _els_reserved4[20]; + } in; + struct { + uint32_t _els_recv_bytecnt; + uint32_t _els_xmit_bytecnt; + uint32_t _els_xmit_dsd_length; + uint16_t _els_xmit_dsd_a1500; + uint16_t _els_xmit_dsd_a3116; + uint16_t _els_xmit_dsd_a4732; + uint16_t _els_xmit_dsd_a6348; + uint32_t _els_recv_dsd_length; + uint16_t _els_recv_dsd_a1500; + uint16_t _els_recv_dsd_a3116; + uint16_t _els_recv_dsd_a4732; + uint16_t _els_recv_dsd_a6348; + } out; + } inout; +#define els_bytecnt inout.in._els_bytecnt +#define els_subcode1 inout.in._els_subcode1 +#define els_subcode2 inout.in._els_subcode2 +#define els_reserved4 inout.in._els_reserved4 +#define els_recv_bytecnt inout.out._els_recv_bytecnt +#define els_xmit_bytecnt inout.out._els_xmit_bytecnt +#define els_xmit_dsd_length inout.out._els_xmit_dsd_length +#define els_xmit_dsd_a1500 inout.out._els_xmit_dsd_a1500 +#define els_xmit_dsd_a3116 inout.out._els_xmit_dsd_a3116 +#define els_xmit_dsd_a4732 inout.out._els_xmit_dsd_a4732 +#define els_xmit_dsd_a6348 inout.out._els_xmit_dsd_a6348 +#define els_recv_dsd_length inout.out._els_recv_dsd_length +#define els_recv_dsd_a1500 inout.out._els_recv_dsd_a1500 +#define els_recv_dsd_a3116 inout.out._els_recv_dsd_a3116 +#define els_recv_dsd_a4732 inout.out._els_recv_dsd_a4732 +#define els_recv_dsd_a6348 inout.out._els_recv_dsd_a6348 +} els_t; #endif /* _ISPMBOX_H */ diff --git a/sys/dev/isp/ispreg.h b/sys/dev/isp/ispreg.h index 8c5e5d4..57b5877 100644 --- a/sys/dev/isp/ispreg.h +++ b/sys/dev/isp/ispreg.h @@ -64,6 +64,7 @@ #define PCI_MBOX_REGS_OFF 0x70 #define PCI_MBOX_REGS2100_OFF 0x10 #define PCI_MBOX_REGS2300_OFF 0x40 +#define PCI_MBOX_REGS2400_OFF 0x80 #define SBUS_MBOX_REGS_OFF 0x80 #define PCI_SXP_REGS_OFF 0x80 @@ -110,12 +111,6 @@ #define BIU_NVRAM (BIU_BLOCK+0xE) /* RW : Bus NVRAM */ /* * These are specific to the 2300. - * - * They *claim* you can read BIU_R2HSTSLO with a full 32 bit access - * and get both registers, but I'm a bit dubious about that. But the - * point here is that the top 16 bits are firmware defined bits that - * the RISC processor uses to inform the host about something- usually - * something which was nominally in a mailbox register. */ #define BIU_REQINP (BIU_BLOCK+0x10) /* Request Queue In */ #define BIU_REQOUTP (BIU_BLOCK+0x12) /* Request Queue Out */ @@ -139,6 +134,7 @@ #define ISPR2HST_FPOST 0x16 /* Low 16 bits fast post */ #define ISPR2HST_FPOST_CTIO 0x17 /* Low 16 bits fast post ctio */ +/* fifo command stuff- mostly for SPI */ #define DFIFO_COMMAND (BIU_BLOCK+0x60) /* RW : Command FIFO Port */ #define RDMA2100_CONTROL DFIFO_COMMAND #define DFIFO_DATA (BIU_BLOCK+0x62) /* RW : Data FIFO Port */ @@ -219,6 +215,8 @@ #define BIU_ICR_ENABLE_ALL_INTS 0x0002 /* Global enable all inter */ #define BIU_ICR_SOFT_RESET 0x0001 /* Soft Reset of ISP */ +#define BIU_IMASK (BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS) + #define BIU2100_ICR_ENABLE_ALL_INTS 0x8000 #define BIU2100_ICR_ENA_FPM_INT 0x0020 #define BIU2100_ICR_ENA_FB_INT 0x0010 @@ -228,16 +226,7 @@ #define BIU2100_ICR_ENABLE_TXDMA_INT 0x0001 #define BIU2100_ICR_DISABLE_ALL_INTS 0x0000 -#define ENABLE_INTS(isp) (IS_SCSI(isp))? \ - ISP_WRITE(isp, BIU_ICR, BIU_ICR_ENABLE_RISC_INT | BIU_ICR_ENABLE_ALL_INTS) : \ - ISP_WRITE(isp, BIU_ICR, BIU2100_ICR_ENA_RISC_INT | BIU2100_ICR_ENABLE_ALL_INTS) - -#define INTS_ENABLED(isp) ((IS_SCSI(isp))? \ - (ISP_READ(isp, BIU_ICR) & (BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS)) :\ - (ISP_READ(isp, BIU_ICR) & \ - (BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS))) - -#define DISABLE_INTS(isp) ISP_WRITE(isp, BIU_ICR, 0) +#define BIU2100_IMASK (BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS) /* BUS STATUS REGISTER */ #define BIU_ISR_DMA_INT 0x0020 /* DMA interrupt pending */ @@ -254,11 +243,14 @@ #define BIU2100_ISR_RXDMA_INT_PENDING 0x0002 /* Global interrupt pending */ #define BIU2100_ISR_TXDMA_INT_PENDING 0x0001 /* Global interrupt pending */ -#define INT_PENDING(isp, isr) (IS_FC(isp)? \ - ((isr & BIU2100_ISR_RISC_INT) != 0) : ((isr & BIU_ISR_RISC_INT) != 0)) +#define INT_PENDING(isp, isr) \ + IS_FC(isp)? \ + (IS_24XX(isp)? (isr & BIU2400_ISR_RISC_INT) : (isr & BIU2100_ISR_RISC_INT)) :\ + (isr & BIU_ISR_RISC_INT) #define INT_PENDING_MASK(isp) \ - (IS_FC(isp)? BIU2100_ISR_RISC_INT: BIU_ISR_RISC_INT) + (IS_FC(isp)? (IS_24XX(isp)? BIU2400_ISR_RISC_INT : BIU2100_ISR_RISC_INT) : \ + (BIU_ISR_RISC_INT)) /* BUS SEMAPHORE REGISTER */ #define BIU_SEMA_STATUS 0x0002 /* Semaphore Status Bit */ @@ -352,6 +344,86 @@ #define DMA_FIFO_PCI_COUNT_MASK 0x00FF /* FIFO Byte count mask */ /* + * 2400 Interface Offsets and Register Definitions + * + * The 2400 looks quite different in terms of registers from other QLogic cards. + * It is getting to be a genuine pain and challenge to keep the same model + * for all. + */ +#define BIU2400_FLASH_ADDR (BIU_BLOCK+0x00) +#define BIU2400_FLASH_DATA (BIU_BLOCK+0x04) +#define BIU2400_CSR (BIU_BLOCK+0x08) +#define BIU2400_ICR (BIU_BLOCK+0x0C) +#define BIU2400_ISR (BIU_BLOCK+0x10) + +#define BIU2400_REQINP (BIU_BLOCK+0x1C) /* Request Queue In */ +#define BIU2400_REQOUTP (BIU_BLOCK+0x20) /* Request Queue Out */ +#define BIU2400_RSPINP (BIU_BLOCK+0x24) /* Response Queue In */ +#define BIU2400_RSPOUTP (BIU_BLOCK+0x28) /* Response Queue Out */ +#define BIU2400_PRI_RQINP (BIU_BLOCK+0x2C) /* Priority Request Q In */ +#define BIU2400_PRI_RSPINP (BIU_BLOCK+0x30) /* Priority Request Q Out */ + +#define BIU2400_ATIO_RSPINP (BIU_BLOCK+0x3C) /* ATIO Queue In */ +#define BIU2400_ATIO_REQINP (BIU_BLOCK+0x40) /* ATIO Queue Out */ + +#define BIU2400_R2HSTSLO (BIU_BLOCK+0x44) +#define BIU2400_R2HSTSHI (BIU_BLOCK+0x46) + +#define BIU2400_HCCR (BIU_BLOCK+0x48) +#define BIU2400_GPIOD (BIU_BLOCK+0x4C) +#define BIU2400_GPIOE (BIU_BLOCK+0x50) +#define BIU2400_HSEMA (BIU_BLOCK+0x58) + +/* BIU2400_FLASH_ADDR definitions */ +#define BIU2400_FLASH_DFLAG (1 << 30) + +/* BIU2400_CSR definitions */ +#define BIU2400_NVERR (1 << 18) +#define BIU2400_DMA_ACTIVE (1 << 17) /* RO */ +#define BIU2400_DMA_STOP (1 << 16) +#define BIU2400_FUNCTION (1 << 15) /* RO */ +#define BIU2400_PCIX_MODE(x) (((x) >> 8) & 0xf) /* RO */ +#define BIU2400_CSR_64BIT (1 << 2) /* RO */ +#define BIU2400_FLASH_ENABLE (1 << 1) +#define BIU2400_SOFT_RESET (1 << 0) + +/* BIU2400_ICR definitions */ +#define BIU2400_ICR_ENA_RISC_INT 0x8 +#define BIU2400_IMASK (BIU2400_ICR_ENA_RISC_INT) + +/* BIU2400_ISR definitions */ +#define BIU2400_ISR_RISC_INT 0x8 + +#define BIU2400_R2HST_INTR BIU_R2HST_INTR +#define BIU2400_R2HST_PAUSED BIU_R2HST_PAUSED +#define BIU2400_R2HST_ISTAT_MASK 0x1f +/* interrupt status meanings */ +#define ISP2400R2HST_ROM_MBX_OK 0x1 /* ROM mailbox cmd done ok */ +#define ISP2400R2HST_ROM_MBX_FAIL 0x2 /* ROM mailbox cmd done fail */ +#define ISP2400R2HST_MBX_OK 0x10 /* mailbox cmd done ok */ +#define ISP2400R2HST_MBX_FAIL 0x11 /* mailbox cmd done fail */ +#define ISP2400R2HST_ASYNC_EVENT 0x12 /* Async Event */ +#define ISP2400R2HST_RSPQ_UPDATE 0x13 /* Response Queue Update */ +#define ISP2400R2HST_ATIO_RSPQ_UPDATE 0x1C /* ATIO Response Queue Update */ +#define ISP2400R2HST_ATIO_RQST_UPDATE 0x1D /* ATIO Request Queue Update */ + +/* BIU2400_HCCR definitions */ + +#define HCCR_2400_CMD_NOP (0x0 << 28) +#define HCCR_2400_CMD_RESET (0x1 << 28) +#define HCCR_2400_CMD_CLEAR_RESET (0x2 << 28) +#define HCCR_2400_CMD_PAUSE (0x3 << 28) +#define HCCR_2400_CMD_RELEASE (0x4 << 28) +#define HCCR_2400_CMD_SET_HOST_INT (0x5 << 28) +#define HCCR_2400_CMD_CLEAR_HOST_INT (0x6 << 28) +#define HCCR_2400_CMD_CLEAR_RISC_INT (0xA << 28) + +#define HCCR_2400_RISC_ERR(x) (((x) >> 12) & 0x7) /* RO */ +#define HCCR_2400_RISC2HOST_INT (1 << 6) /* RO */ +#define HCCR_2400_RISC_RESET (1 << 5) /* RO */ + + +/* * Mailbox Block Register Offsets */ @@ -377,7 +449,7 @@ * Strictly speaking, it's * SCSI && 2100 : 8 MBOX registers * 2200: 24 MBOX registers - * 2300: 32 MBOX registers + * 2300/2400: 32 MBOX registers */ #define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1)) #define NMBOX(isp) \ @@ -389,9 +461,15 @@ #define MAX_MAILBOX(isp) ((IS_FC(isp))? 12 : 8) #define MAILBOX_STORAGE 12 +/* if timeout == 0, then default timeout is picked */ +#define MBCMD_DEFAULT_TIMEOUT 100000 /* 100 ms */ typedef struct { uint16_t param[MAILBOX_STORAGE]; - uint16_t ibits, obits; + uint16_t ibits; + uint16_t obits; + uint32_t : 28, + logval : 4; + uint32_t timeout; } mbreg_t; /* @@ -672,6 +750,7 @@ typedef struct { #define PCI_HCCR_CMD_PARITY_ERR 0xE000 /* Generate parity error */ #define HCCR_CMD_TEST_MODE 0xF000 /* Set Test Mode */ + #define ISP2100_HCCR_PARITY_ENABLE_2 0x0400 #define ISP2100_HCCR_PARITY_ENABLE_1 0x0200 #define ISP2100_HCCR_PARITY_ENABLE_0 0x0100 @@ -688,6 +767,25 @@ typedef struct { #define PCI_HCCR_BIOS 0x0001 /* W : BIOS enable */ /* + * Defines for Interrupts + */ +#define ISP_INTS_ENABLED(isp) \ + ((IS_SCSI(isp))? \ + (ISP_READ(isp, BIU_ICR) & BIU_IMASK) : \ + (IS_24XX(isp)? (ISP_READ(isp, BIU2400_ICR) & BIU2400_IMASK) : \ + (ISP_READ(isp, BIU_ICR) & BIU2100_IMASK))) + +#define ISP_ENABLE_INTS(isp) \ + (IS_SCSI(isp) ? \ + ISP_WRITE(isp, BIU_ICR, BIU_IMASK) : \ + (IS_24XX(isp) ? \ + (ISP_WRITE(isp, BIU2400_ICR, BIU2400_IMASK)) : \ + (ISP_WRITE(isp, BIU_ICR, BIU2100_IMASK)))) + +#define ISP_DISABLE_INTS(isp) \ + IS_24XX(isp)? ISP_WRITE(isp, BIU2400_ICR, 0) : ISP_WRITE(isp, BIU_ICR, 0) + +/* * NVRAM Definitions (PCI cards only) */ @@ -736,9 +834,9 @@ typedef struct { #define ISP_NVRAM_FAST_MTTR_ENABLE(c) ISPBSMX(c, 22, 0, 0x01) #define ISP_NVRAM_TARGOFF 28 -#define ISP_NVARM_TARGSIZE 6 +#define ISP_NVRAM_TARGSIZE 6 #define _IxT(tgt, tidx) \ - (ISP_NVRAM_TARGOFF + (ISP_NVARM_TARGSIZE * (tgt)) + (tidx)) + (ISP_NVRAM_TARGOFF + (ISP_NVRAM_TARGSIZE * (tgt)) + (tidx)) #define ISP_NVRAM_TGT_RENEG(c, t) ISPBSMX(c, _IxT(t, 0), 0, 0x01) #define ISP_NVRAM_TGT_QFRZ(c, t) ISPBSMX(c, _IxT(t, 0), 1, 0x01) #define ISP_NVRAM_TGT_ARQ(c, t) ISPBSMX(c, _IxT(t, 0), 2, 0x01) @@ -937,7 +1035,7 @@ typedef struct { ISPBSMX(c, _IxT16(t, 4, (b)), 7, 0x01) /* - * Qlogic 2XXX NVRAM is an array of 256 bytes. + * Qlogic 2100 thru 2300 NVRAM is an array of 256 bytes. * * Some portion of the front of this is for general RISC engine parameters, * mostly reflecting the state of the last INITIALIZE FIRMWARE mailbox command. @@ -1012,6 +1110,51 @@ typedef struct { #define ISP2100_HBA_FEATURES(c) ((c)[232] | ((c)[233] << 8)) /* + * Qlogic 2400 NVRAM is an array of 512 bytes with a 32 bit checksum. + */ +#define ISP2400_NVRAM_PORT0_ADDR 0x80 +#define ISP2400_NVRAM_PORT1_ADDR 0x180 +#define ISP2400_NVRAM_SIZE 512 + +#define ISP2400_NVRAM_VERSION(c) ((c)[4] | ((c)[5] << 8)) +#define ISP2400_NVRAM_MAXFRAMELENGTH(c) (((c)[12]) | ((c)[13] << 8)) +#define ISP2400_NVRAM_EXECUTION_THROTTLE(c) (((c)[14]) | ((c)[15] << 8)) +#define ISP2400_NVRAM_EXCHANGE_COUNT(c) (((c)[16]) | ((c)[17] << 8)) +#define ISP2400_NVRAM_HARDLOOPID(c) ((c)[18] | ((c)[19] << 8)) + +#define ISP2400_NVRAM_PORT_NAME(c) (\ + (((uint64_t)(c)[20]) << 56) | \ + (((uint64_t)(c)[21]) << 48) | \ + (((uint64_t)(c)[22]) << 40) | \ + (((uint64_t)(c)[23]) << 32) | \ + (((uint64_t)(c)[24]) << 24) | \ + (((uint64_t)(c)[25]) << 16) | \ + (((uint64_t)(c)[26]) << 8) | \ + (((uint64_t)(c)[27]) << 0)) + +#define ISP2400_NVRAM_NODE_NAME(c) (\ + (((uint64_t)(c)[28]) << 56) | \ + (((uint64_t)(c)[29]) << 48) | \ + (((uint64_t)(c)[30]) << 40) | \ + (((uint64_t)(c)[31]) << 32) | \ + (((uint64_t)(c)[32]) << 24) | \ + (((uint64_t)(c)[33]) << 16) | \ + (((uint64_t)(c)[34]) << 8) | \ + (((uint64_t)(c)[35]) << 0)) + +#define ISP2400_NVRAM_LOGIN_RETRY_CNT(c) ((c)[36] | ((c)[37] << 8)) +#define ISP2400_NVRAM_LINK_DOWN_ON_NOS(c) ((c)[38] | ((c)[39] << 8)) +#define ISP2400_NVRAM_INTERRUPT_DELAY(c) ((c)[40] | ((c)[41] << 8)) +#define ISP2400_NVRAM_LOGIN_TIMEOUT(c) ((c)[42] | ((c)[43] << 8)) + +#define ISP2400_NVRAM_FIRMWARE_OPTIONS1(c) \ + ((c)[44] | ((c)[45] << 8) | ((c)[46] << 16) | ((c)[47] << 24)) +#define ISP2400_NVRAM_FIRMWARE_OPTIONS2(c) \ + ((c)[48] | ((c)[49] << 8) | ((c)[50] << 16) | ((c)[51] << 24)) +#define ISP2400_NVRAM_FIRMWARE_OPTIONS3(c) \ + ((c)[52] | ((c)[53] << 8) | ((c)[54] << 16) | ((c)[55] << 24)) + +/* * Firmware Crash Dump * * QLogic needs specific information format when they look at firmware crashes. diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 5ea8e8a..fec8423 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -31,20 +31,24 @@ #define _ISPVAR_H #if defined(__NetBSD__) || defined(__OpenBSD__) +#include <dev/ic/isp_stds.h> #include <dev/ic/ispmbox.h> #endif #ifdef __FreeBSD__ +#include <dev/isp/isp_stds.h> #include <dev/isp/ispmbox.h> #endif #ifdef __linux__ +#include "isp_stds.h" #include "ispmbox.h" #endif #ifdef __svr4__ +#include "isp_stds.h" #include "ispmbox.h" #endif -#define ISP_CORE_VERSION_MAJOR 2 -#define ISP_CORE_VERSION_MINOR 11 +#define ISP_CORE_VERSION_MAJOR 3 +#define ISP_CORE_VERSION_MINOR 0 /* * Vector for bus specific code to provide specific services. @@ -52,17 +56,17 @@ typedef struct ispsoftc ispsoftc_t; struct ispmdvec { int (*dv_rd_isr) - (ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); - uint16_t (*dv_rd_reg) (ispsoftc_t *, int); - void (*dv_wr_reg) (ispsoftc_t *, int, uint16_t); + (ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); + uint32_t (*dv_rd_reg) (ispsoftc_t *, int); + void (*dv_wr_reg) (ispsoftc_t *, int, uint32_t); int (*dv_mbxdma) (ispsoftc_t *); int (*dv_dmaset) - (ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t); - void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint16_t); + (ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t); + void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint32_t); void (*dv_reset0) (ispsoftc_t *); void (*dv_reset1) (ispsoftc_t *); void (*dv_dregs) (ispsoftc_t *, const char *); - uint16_t *dv_ispfw; /* ptr to f/w */ + void * dv_ispfw; /* ptr to f/w */ uint16_t dv_conf1; uint16_t dv_clock; /* clock frequency */ }; @@ -122,6 +126,7 @@ struct ispmdvec { #define SYNC_SFORDEV 2 /* scratch, sync for ISP */ #define SYNC_SFORCPU 3 /* scratch, sync for CPU */ #define SYNC_REG 4 /* for registers */ +#define SYNC_ATIOQ 5 /* atio result queue (24xx) */ /* * Request/Response Queue defines and macros. @@ -148,7 +153,7 @@ struct ispmdvec { #define ISP_ADD_REQUEST(isp, nxti) \ MEMORYBARRIER(isp, SYNC_REQUEST, isp->isp_reqidx, QENTRY_LEN); \ - WRITE_REQUEST_QUEUE_IN_POINTER(isp, nxti); \ + ISP_WRITE(isp, isp->isp_rqstinrp, nxti); \ isp->isp_reqidx = nxti /* @@ -161,6 +166,7 @@ typedef struct { isp_cmd_dma_burst_enable: 1, isp_data_dma_burst_enabl: 1, isp_fifo_threshold : 3, + isp_ptisp : 1, isp_ultramode : 1, isp_diffmode : 1, isp_lvdmode : 1, @@ -222,32 +228,125 @@ typedef struct { /* * Fibre Channel Specifics */ -#define FL_PORT_ID 0x7e /* FL_Port Special ID */ -#define FC_PORT_ID 0x7f /* Fabric Controller Special ID */ -#define FC_SNS_ID 0x80 /* SNS Server Special ID */ +/* These are for 2100/2200/2300 cards */ +#define FL_ID 0x7e /* FL_Port Special ID */ +#define SNS_ID 0x80 /* SNS Server Special ID */ +#define NPH_MAX 0xfe + +/* These are for 24XX cards */ +#define NPH_RESERVED 0x7F0 /* begin of reserved N-port handles */ +#define NPH_MGT_ID 0x7FA /* Management Server Special ID */ +#define NPH_SNS_ID 0x7FC /* SNS Server Special ID */ +#define NPH_FL_ID 0x7FE /* FL Port Special ID */ +#define NPH_MAX_24XX 0x800 -/* #define ISP_USE_GA_NXT 1 */ /* Use GA_NXT with switches */ -#ifndef GA_NXT_MAX -#define GA_NXT_MAX 256 -#endif +/* + * Limit for devices on an arbitrated loop. + */ +#define LOCAL_LOOP_LIM 126 + +/* + * Special Port IDs + */ +#define MANAGEMENT_PORT_ID 0xFFFFFA +#define SNS_PORT_ID 0xFFFFFC +#define FABRIC_PORT_ID 0xFFFFFE + +/* + * FC Port Database entry. + * + * It has a handle that the f/w uses to address commands to a device. + * This handle's value may be assigned by the firmware (e.g., for local loop + * devices) or by the driver (e.g., for fabric devices). + * + * It has a state. If the state if VALID, that means that we've logged into + * the device. We also *may* have a initiator map index entry. This is a value + * from 0..MAX_FC_TARG that is used to index into the isp_ini_map array. If + * the value therein is non-zero, then that value minus one is used to index + * into the Port Database to find the handle for forming commands. There is + * back-index minus one value within to Port Database entry that tells us + * which entry in isp_ini_map points to us (to avoid searching). + * + * Local loop devices the firmware automatically performs PLOGI on for us + * (which is why that handle is imposed upon us). Fabric devices we assign + * a handle to and perform the PLOGI on. + * + * When a PORT DATABASE CHANGED asynchronous event occurs, we mark all VALID + * entries as PROBATIONAL. This allows us, if policy says to, just keep track + * of devices whose handles change but are otherwise the same device (and + * thus keep 'target' constant). + * + * In any case, we search all possible local loop handles. For each one that + * has a port database entity returned, we search for any PROBATIONAL entry + * that matches it and update as appropriate. Otherwise, as a new entry, we + * find room for it in the Port Database. We *try* and use the handle as the + * index to put it into the Database, but that's just an optimization. We mark + * the entry VALID and make sure that the target index is updated and correct. + * + * When we get done searching the local loop, we then search similarily for + * a list of devices we've gotten from the fabric name controller (if we're + * on a fabric). VALID marking is also done similarily. + * + * When all of this is done, we can march through the database and clean up + * any entry that is still PROBATIONAL (these represent devices which have + * departed). Then we're done and can resume normal operations. + * + * Negative invariants that we try and test for are: + * + * + There can never be two non-NIL entries with the same { Port, Node } WWN + * duples. + * + * + There can never be two non-NIL entries with the same handle. + * + * + There can never be two non-NIL entries which have the same ini_map_idx + * value. + */ +typedef struct { + uint16_t handle; + uint16_t ini_map_idx : 12, + autologin : 1, /* F/W does PLOGI/PLOGO */ + state : 3; + uint32_t : 6, + roles : 2, + portid : 24; + uint32_t : 6, + new_roles : 2, + new_portid : 24; + uint64_t node_wwn; + uint64_t port_wwn; +} fcportdb_t; + +#define FC_PORTDB_STATE_NIL 0 +#define FC_PORTDB_STATE_PROBATIONAL 1 +#define FC_PORTDB_STATE_DEAD 2 +#define FC_PORTDB_STATE_CHANGED 3 +#define FC_PORTDB_STATE_NEW 4 +#define FC_PORTDB_STATE_PENDING_VALID 5 +#define FC_PORTDB_STATE_VALID 7 + +/* + * FC card specific information + */ typedef struct { - uint32_t : 13, + uint32_t : 10, + isp_tmode : 1, + isp_2klogin : 1, + isp_sccfw : 1, isp_gbspeed : 3, : 1, - isp_iid_set : 1, - loop_seen_once : 1, + : 1, + : 1, isp_loopstate : 4, /* Current Loop State */ isp_fwstate : 4, /* ISP F/W state */ isp_gotdparms : 1, isp_topo : 3, - isp_onfabric : 1; + loop_seen_once : 1; uint32_t : 8, isp_portid : 24; /* S_ID */ uint16_t isp_fwoptions; uint16_t isp_xfwoptions; uint16_t isp_zfwoptions; - uint16_t isp_iid; /* 'initiator' id */ uint16_t isp_loopid; /* hard loop id */ uint16_t isp_fwattr; /* firmware attributes */ uint16_t isp_execthrottle; @@ -258,34 +357,8 @@ typedef struct { uint16_t isp_maxfrmlen; uint64_t isp_nodewwn; uint64_t isp_portwwn; - /* - * Port Data Base. This is indexed by 'target', which is invariate. - * However, elements within can move around due to loop changes, - * so the actual loop ID passed to the F/W is in this structure. - * The first time the loop is seen up, loopid will match the index - * (except for fabric nodes which are above mapped above FC_SNS_ID - * and are completely virtual), but subsequent LIPs can cause things - * to move around. - */ - struct lportdb { - uint32_t loopid : 16, - : 2, - fc4_type : 4, - last_fabric_dev : 1, - relogin : 1, - force_logout : 1, - was_fabric_dev : 1, - fabric_dev : 1, - loggedin : 1, - roles : 2, - tvalid : 1, - valid : 1; - uint32_t port_type : 8, - portid : 24; - uint64_t node_wwn; - uint64_t port_wwn; - } portdb[MAX_FC_TARG], tport[FC_PORT_ID]; - + fcportdb_t portdb[MAX_FC_TARG]; + uint16_t isp_ini_map[MAX_FC_TARG]; /* * Scratch DMA mapped in area to fetch Port Database stuff, etc. */ @@ -308,10 +381,10 @@ typedef struct { #define LOOP_NIL 0 #define LOOP_LIP_RCVD 1 #define LOOP_PDB_RCVD 2 -#define LOOP_SCANNING_FABRIC 3 -#define LOOP_FSCAN_DONE 4 -#define LOOP_SCANNING_LOOP 5 -#define LOOP_LSCAN_DONE 6 +#define LOOP_SCANNING_LOOP 3 +#define LOOP_LSCAN_DONE 4 +#define LOOP_SCANNING_FABRIC 5 +#define LOOP_FSCAN_DONE 6 #define LOOP_SYNCING_PDB 7 #define LOOP_READY 8 @@ -350,7 +423,7 @@ struct ispsoftc { uint32_t isp_clock : 8, /* input clock */ : 4, - isp_port : 1, /* 23XX only */ + isp_port : 1, /* 23XX/24XX only */ isp_failed : 1, /* board failed */ isp_open : 1, /* opened (ioctl) */ isp_touched : 1, /* board ever seen? */ @@ -361,10 +434,12 @@ struct ispsoftc { uint32_t isp_confopts; /* config options */ - uint16_t isp_rqstinrp; /* register for REQINP */ - uint16_t isp_rqstoutrp; /* register for REQOUTP */ - uint16_t isp_respinrp; /* register for RESINP */ - uint16_t isp_respoutrp; /* register for RESOUTP */ + uint32_t isp_rqstinrp; /* register for REQINP */ + uint32_t isp_rqstoutrp; /* register for REQOUTP */ + uint32_t isp_respinrp; /* register for RESINP */ + uint32_t isp_respoutrp; /* register for RESOUTP */ + uint32_t isp_atioinrp; /* register for ATIOINP */ + uint32_t isp_atiooutrp; /* register for ATIOOUTP */ /* * Instrumentation @@ -388,13 +463,13 @@ struct ispsoftc { isp_sendmarker : 2, /* send a marker entry */ isp_update : 2, /* update parameters */ isp_nactive : 16; /* how many commands active */ - volatile uint16_t isp_reqodx; /* index of last ISP pickup */ - volatile uint16_t isp_reqidx; /* index of next request */ - volatile uint16_t isp_residx; /* index of next result */ - volatile uint16_t isp_resodx; /* index of next result */ - volatile uint16_t isp_rspbsy; - volatile uint16_t isp_lasthdls; /* last handle seed */ - volatile uint16_t isp_obits; /* mailbox command output */ + volatile uint32_t isp_reqodx; /* index of last ISP pickup */ + volatile uint32_t isp_reqidx; /* index of next request */ + volatile uint32_t isp_residx; /* index of next result */ + volatile uint32_t isp_resodx; /* index of next result */ + volatile uint32_t isp_rspbsy; + volatile uint32_t isp_lasthdls; /* last handle seed */ + volatile uint32_t isp_obits; /* mailbox command output */ volatile uint16_t isp_mboxtmp[MAILBOX_STORAGE]; volatile uint16_t isp_lastmbxcmd; /* last mbox command sent */ volatile uint16_t isp_mbxwrk0; @@ -422,6 +497,11 @@ struct ispsoftc { void * isp_result; XS_DMA_ADDR_T isp_rquest_dma; XS_DMA_ADDR_T isp_result_dma; +#ifdef ISP_TARGET_MODE + /* for 24XX only */ + void * isp_atioq; + XS_DMA_ADDR_T isp_atioq_dma; +#endif }; #define SDPARAM(isp) ((sdparam *) (isp)->isp_param) @@ -454,6 +534,7 @@ struct ispsoftc { #define ISP_CFG_OWNFSZ 0x400 /* override NVRAM frame size */ #define ISP_CFG_OWNLOOPID 0x800 /* override NVRAM loopid */ #define ISP_CFG_OWNEXCTHROTTLE 0x1000 /* override NVRAM execution throttle */ +#define ISP_CFG_FOURGB 0x2000 /* force 4GB connection (24XX only) */ /* * Prior to calling isp_reset for the first time, the outer layer @@ -491,6 +572,7 @@ struct ispsoftc { */ #define ISP_CODE_ORG 0x1000 /* default f/w code start */ #define ISP_CODE_ORG_2300 0x0800 /* ..except for 2300s */ +#define ISP_CODE_ORG_2400 0x100000 /* ..and 2400s */ #define ISP_FW_REV(maj, min, mic) ((maj << 24) | (min << 16) | mic) #define ISP_FW_MAJOR(code) ((code >> 24) & 0xff) #define ISP_FW_MINOR(code) ((code >> 16) & 0xff) @@ -501,6 +583,8 @@ struct ispsoftc { #define ISP_FW_MICROX(xp) (xp[2]) #define ISP_FW_NEWER_THAN(i, major, minor, micro) \ (ISP_FW_REVX((i)->isp_fwrev) > ISP_FW_REV(major, minor, micro)) +#define ISP_FW_OLDER_THAN(i, major, minor, micro) \ + (ISP_FW_REVX((i)->isp_fwrev) < ISP_FW_REV(major, minor, micro)) /* * Bus (implementation) types @@ -539,7 +623,6 @@ struct ispsoftc { #define ISP_HA_FC_2312 0x40 #define ISP_HA_FC_2322 0x50 #define ISP_HA_FC_2400 0x60 -#define ISP_HA_FC_2422 0x61 #define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI) #define IS_1240(isp) (isp->isp_type == ISP_HA_SCSI_1240) @@ -557,8 +640,8 @@ struct ispsoftc { #define IS_FC(isp) ((isp)->isp_type & ISP_HA_FC) #define IS_2100(isp) ((isp)->isp_type == ISP_HA_FC_2100) #define IS_2200(isp) ((isp)->isp_type == ISP_HA_FC_2200) -#define IS_23XX(isp) \ - ((isp)->isp_type >= ISP_HA_FC_2300 && (isp)->isp_type < ISP_HA_FC_2400) +#define IS_23XX(isp) ((isp)->isp_type >= ISP_HA_FC_2300 && \ + (isp)->isp_type < ISP_HA_FC_2400) #define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300) #define IS_2312(isp) ((isp)->isp_type == ISP_HA_FC_2312) #define IS_2322(isp) ((isp)->isp_type == ISP_HA_FC_2322) @@ -567,10 +650,10 @@ struct ispsoftc { /* * DMA related macros */ -#define DMA_WD3(x) ((((uint64_t)x) >> 48) & 0xffff) -#define DMA_WD2(x) ((((uint64_t)x) >> 32) & 0xffff) -#define DMA_WD1(x) (((x) >> 16) & 0xffff) -#define DMA_WD0(x) (((x) & 0xffff)) +#define DMA_WD3(x) (((uint16_t)(((uint64_t)x) >> 48)) & 0xffff) +#define DMA_WD2(x) (((uint16_t)(((uint64_t)x) >> 32)) & 0xffff) +#define DMA_WD1(x) ((uint16_t)((x) >> 16) & 0xffff) +#define DMA_WD0(x) ((uint16_t)((x) & 0xffff)) #define DMA_LO32(x) ((uint32_t) (x)) #define DMA_HI32(x) ((uint32_t)(((uint64_t)x) >> 32)) @@ -609,7 +692,7 @@ void isp_fw_dump(ispsoftc_t *isp); * semaphore register and first mailbox register (if appropriate). This also * means that most spurious/bogus interrupts not for us can be filtered first. */ -void isp_intr(ispsoftc_t *, uint16_t, uint16_t, uint16_t); +void isp_intr(ispsoftc_t *, uint32_t, uint16_t, uint16_t); /* @@ -672,7 +755,7 @@ typedef enum { ISPCTL_SCAN_LOOP, /* (Re)scan Local Loop */ ISPCTL_PDB_SYNC, /* Synchronize Port Database */ ISPCTL_SEND_LIP, /* Send a LIP */ - ISPCTL_GET_POSMAP, /* Get FC-AL position map */ + ISPCTL_GET_PORTNAME, /* get portname from an N-port handle */ ISPCTL_RUN_MBOXCMD, /* run a mailbox command */ ISPCTL_TOGGLE_TMODE, /* toggle target mode */ ISPCTL_GET_PDB /* get a single port database entry */ @@ -728,8 +811,10 @@ typedef enum { ISPASYNC_LIP, /* LIP Received */ ISPASYNC_LOOP_RESET, /* Loop Reset Received */ ISPASYNC_CHANGE_NOTIFY, /* FC Change Notification */ - ISPASYNC_FABRIC_DEV, /* FC Fabric Device Arrival */ - ISPASYNC_PROMENADE, /* FC Objects coming && going */ + ISPASYNC_DEV_ARRIVED, /* FC Device Arrival */ + ISPASYNC_DEV_CHANGED, /* FC Device Change */ + ISPASYNC_DEV_STAYED, /* FC Device Stayed the Same */ + ISPASYNC_DEV_GONE, /* FC Device Depart */ ISPASYNC_TARGET_NOTIFY, /* target asynchronous notification event */ ISPASYNC_TARGET_ACTION, /* target action requested */ ISPASYNC_CONF_CHANGE, /* Platform Configuration Change */ @@ -804,7 +889,7 @@ int isp_async(ispsoftc_t *, ispasync_t, void *); * of the same object is consistent. * * MBOX_ACQUIRE(ispsoftc_t *) acquire lock on mailbox regs - * MBOX_WAIT_COMPLETE(ispsoftc_t *) wait for mailbox cmd to be done + * MBOX_WAIT_COMPLETE(ispsoftc_t *, mbreg_t *) wait for cmd to be done * MBOX_NOTIFY_COMPLETE(ispsoftc_t *) notification of mbox cmd donee * MBOX_RELEASE(ispsoftc_t *) release lock on mailbox regs * |