summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2006-11-02 03:21:32 +0000
committermjacob <mjacob@FreeBSD.org>2006-11-02 03:21:32 +0000
commit120271c1a6f4c81a9b617be188799604cfca7bdd (patch)
tree51750d8ca50a883d32c721be30cbb55cbe2c28c8 /sys/dev/isp
parent2904312753a5ab37478b957ab4ad51612d8a6dd9 (diff)
downloadFreeBSD-src-120271c1a6f4c81a9b617be188799604cfca7bdd.zip
FreeBSD-src-120271c1a6f4c81a9b617be188799604cfca7bdd.tar.gz
Add 4Gb (24XX) support and lay the foundation for a lot of new stuff.
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp.c4774
-rw-r--r--sys/dev/isp/isp_freebsd.c475
-rw-r--r--sys/dev/isp/isp_freebsd.h141
-rw-r--r--sys/dev/isp/isp_library.c2623
-rw-r--r--sys/dev/isp/isp_library.h89
-rw-r--r--sys/dev/isp/isp_pci.c518
-rw-r--r--sys/dev/isp/isp_sbus.c103
-rw-r--r--sys/dev/isp/isp_stds.h200
-rw-r--r--sys/dev/isp/isp_target.c592
-rw-r--r--sys/dev/isp/isp_target.h356
-rw-r--r--sys/dev/isp/isp_tpublic.h26
-rw-r--r--sys/dev/isp/ispmbox.h620
-rw-r--r--sys/dev/isp/ispreg.h191
-rw-r--r--sys/dev/isp/ispvar.h239
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, &reg) == 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, &reg) == 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(&notify, 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, &notify);
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, &notify);
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
*
OpenPOWER on IntegriCloud