summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2006-07-03 08:24:09 +0000
committermjacob <mjacob@FreeBSD.org>2006-07-03 08:24:09 +0000
commitfa2514423bf205fcd4d5d552ebe38852f9457594 (patch)
tree58604d0a86cb16b7926e21a19d97952de8549f42
parent617ea887dfddbc7da18e9cf29e731789481560ed (diff)
downloadFreeBSD-src-fa2514423bf205fcd4d5d552ebe38852f9457594.zip
FreeBSD-src-fa2514423bf205fcd4d5d552ebe38852f9457594.tar.gz
Do various fixes to support firmware loading for the 2322
(and by extension, the 2422). One peculiar thing I've found with the 2322 is that if you don't force it to do Hard LoopID acquisition, the firmware crashes. This took a while to figure out. While we're at it, fix various bugs having to do with NVRAM reading and option setting with respect to pieces of NVRAM.
-rw-r--r--sys/dev/isp/isp.c351
-rw-r--r--sys/dev/isp/isp_pci.c24
-rw-r--r--sys/dev/isp/ispmbox.h4
-rw-r--r--sys/dev/isp/ispreg.h25
-rw-r--r--sys/dev/isp/ispvar.h18
5 files changed, 280 insertions, 142 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 8fcb134..99c52db 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -100,7 +100,7 @@ static const char topology[] =
static const char swrej[] =
"Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";
static const char finmsg[] =
- "(%d.%d.%d): FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";
+ "%d.%d.%d: FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";
static const char sc0[] =
"%s CHAN %d FTHRSH %d IID %d RESETD %d RETRYC %d RETRYD %d ASD 0x%x";
static const char sc1[] =
@@ -129,7 +129,7 @@ static int isp_getmap(ispsoftc_t *, fcpos_map_t *);
static int isp_getpdb(ispsoftc_t *, int, isp_pdb_t *);
static uint64_t isp_get_portname(ispsoftc_t *, int, int);
static int isp_fclink_test(ispsoftc_t *, int);
-static char *isp2100_fw_statename(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 *);
@@ -639,18 +639,20 @@ again:
dodnld = 0;
}
- if (IS_23XX(isp))
+ if (IS_23XX(isp)) {
code_org = ISP_CODE_ORG_2300;
- else
+ } else {
code_org = ISP_CODE_ORG;
-
+ }
if (dodnld) {
- isp->isp_mbxworkp = (void *) &isp->isp_mdvec->dv_ispfw[1];
- isp->isp_mbxwrk0 = isp->isp_mdvec->dv_ispfw[3] - 1;
+ uint16_t *ptr = isp->isp_mdvec->dv_ispfw;
+
+ isp->isp_mbxworkp = &ptr[1];
+ isp->isp_mbxwrk0 = ptr[3] - 1;
isp->isp_mbxwrk1 = code_org + 1;
mbs.param[0] = MBOX_WRITE_RAM_WORD;
mbs.param[1] = code_org;
- mbs.param[2] = isp->isp_mdvec->dv_ispfw[0];
+ mbs.param[2] = ptr[0];
isp_mboxcmd(isp, &mbs, MBLOGNONE);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGERR,
@@ -659,6 +661,7 @@ again:
dodnld = 0;
goto again;
}
+
/*
* Verify that it downloaded correctly.
*/
@@ -669,6 +672,49 @@ again:
isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure");
return;
}
+
+ /*
+ * If we're a 2322 or 2422, 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.
+ */
+ if (IS_2322(isp)) {
+
+ ptr = &ptr[ptr[3]];
+ isp->isp_mbxworkp = &ptr[1];
+ isp->isp_mbxwrk0 = ptr[3] - 1;
+ isp->isp_mbxwrk1 = ptr[5] + 1;
+ isp->isp_mbxwrk8 = ptr[4];
+ mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED;
+ mbs.param[8] = ptr[4];
+ mbs.param[1] = ptr[5];
+ mbs.param[2] = ptr[0];
+ isp_mboxcmd(isp, &mbs, MBLOGNONE);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR,
+ "Receive Sequencer F/W Load Failed");
+ return;
+ }
+
+ ptr = &ptr[ptr[3]];
+ isp->isp_mbxworkp = &ptr[1];
+ isp->isp_mbxwrk0 = ptr[3] - 1;
+ isp->isp_mbxwrk1 = ptr[5] + 1;
+ isp->isp_mbxwrk8 = ptr[4];
+ mbs.param[0] = MBOX_WRITE_RAM_WORD_EXTENDED;
+ mbs.param[8] = ptr[4];
+ mbs.param[1] = ptr[5];
+ mbs.param[2] = ptr[0];
+ isp_mboxcmd(isp, &mbs, MBLOGNONE);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR,
+ "Transmit Sequencer F/W Load Failed");
+ return;
+ }
+ }
+
isp->isp_loaded_fw = 1;
} else {
isp->isp_loaded_fw = 0;
@@ -687,9 +733,9 @@ again:
mbs.param[1] = code_org;
if (IS_2322(isp) || IS_24XX(isp)) {
if (isp->isp_loaded_fw) {
- mbs.param[2] = 1;
- } else {
mbs.param[2] = 0;
+ } else {
+ mbs.param[2] = 1;
}
mbs.obits |= 2;
}
@@ -1032,11 +1078,9 @@ isp_scsi_init(ispsoftc_t *isp)
if (IS_ULTRA2(isp) || IS_1240(isp))
mbs.param[1] |= FW_FEATURE_RIO_16BIT;
#else
-#ifndef ISP_NO_FASTPOST
if (IS_ULTRA2(isp) || IS_1240(isp))
mbs.param[1] |= FW_FEATURE_FAST_POST;
#endif
-#endif
if (mbs.param[1] != 0) {
uint16_t sfeat = mbs.param[1];
isp_mboxcmd(isp, &mbs, MBLOGALL);
@@ -1273,7 +1317,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;
- if (icbp->icb_hardaddr >= 125) {
+ if (icbp->icb_hardaddr > 125) {
/*
* We end up with these Loop IDs for F-Port topologies
*/
@@ -1284,6 +1328,11 @@ isp_fibre_init(ispsoftc_t *isp)
}
icbp->icb_hardaddr = 0;
}
+
+ if (IS_2322(isp) || IS_24XX(isp)) {
+ icbp->icb_fwoptions |= ICBOPT_HARD_ADDRESS;
+ }
+
/*
* Right now we just set extended options to prefer point-to-point
* over loop based upon some soft config options.
@@ -1309,38 +1358,26 @@ isp_fibre_init(ispsoftc_t *isp)
icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP;
break;
}
- if (IS_23XX(isp)) {
+ if (IS_2200(isp)) {
+ if (ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
+ icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
+ icbp->icb_racctimer = 4;
+ icbp->icb_idelaytimer = 8;
+ }
+ icbp->icb_fwoptions |= ICBOPT_FAST_POST;
+ } else {
/*
* QLogic recommends that FAST Posting be turned
* off for 23XX cards and instead allow the HBA
* to write response queue entries and interrupt
* after a delay (ZIO).
- *
- * If we set ZIO, it will disable fast posting,
- * so we don't need to clear it in fwoptions.
- *
- * Depending on the role we're selecting, we
- * chose fast posting or not as it still is
- * a win for target mode.
*/
-#ifndef ISP_NO_ZIO
- if (isp->isp_role == ISP_ROLE_TARGET) {
- icbp->icb_fwoptions |= ICBOPT_FAST_POST;
- } else {
+ icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
+ if ((fcp->isp_xfwoptions & ICBXOPT_TIMER_MASK) ==
+ ICBXOPT_ZIO) {
icbp->icb_xfwoptions |= ICBXOPT_ZIO;
+ icbp->icb_idelaytimer = 10;
}
-#else
- icbp->icb_fwoptions |= ICBOPT_FAST_POST;
-#endif
-#if 0
- /*
- * Values, in 100us increments. The default
- * is 2 (200us) if a value 0 (default) is
- * selected.
- */
- icbp->icb_idelaytimer = 2;
-#endif
-
if (isp->isp_confopts & ISP_CFG_ONEGB) {
icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB;
} else if (isp->isp_confopts & ISP_CFG_TWOGB) {
@@ -1348,30 +1385,12 @@ isp_fibre_init(ispsoftc_t *isp)
} else {
icbp->icb_zfwoptions |= ICBZOPT_RATE_AUTO;
}
+ if (fcp->isp_zfwoptions & ICBZOPT_50_OHM) {
+ icbp->icb_zfwoptions |= ICBZOPT_50_OHM;
+ }
}
}
-#ifndef ISP_NO_RIO_FC
- /*
- * RIO seems to be enabled in 2100s for fw >= 1.17.0.
- *
- * I've had some questionable problems with RIO on 2200.
- * More specifically, on a 2204 I had problems with RIO
- * on a Linux system where I was dropping commands right
- * and left. It's not clear to me what the actual problem
- * was.
- *
- * 23XX Cards do not support RIO. Instead they support ZIO.
- */
-#if 0
- if (!IS_23XX(isp) && ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
- icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
- icbp->icb_racctimer = 4;
- icbp->icb_idelaytimer = 8;
- }
-#endif
-#endif
-
MEMZERO(&mbs, sizeof (mbs));
/*
@@ -1432,6 +1451,7 @@ isp_fibre_init(ispsoftc_t *isp)
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);
+
isp_prt(isp, ISP_LOGDEBUG0,
"isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x",
icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions);
@@ -1560,18 +1580,20 @@ isp_get_portname(ispsoftc_t *isp, int loopid, int nodename)
mbs.param[0] = MBOX_GET_PORT_NAME;
if (IS_2KLOGIN(isp)) {
mbs.param[1] = loopid;
- if (nodename)
- mbs.param[10] = 1;
mbs.obits |= (1 << 10);
+ if (nodename) {
+ mbs.param[10] = 1;
+ }
} else {
mbs.param[1] = loopid << 8;
- if (nodename)
+ if (nodename) {
mbs.param[1] |= 1;
+ }
}
isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
wwn =
- (((uint64_t)(mbs.param[2] & 0xff)) << 56) |
+ (((uint64_t)(mbs.param[2] & 0xff)) << 56) |
(((uint64_t)(mbs.param[2] >> 8)) << 48) |
(((uint64_t)(mbs.param[3] & 0xff)) << 40) |
(((uint64_t)(mbs.param[3] >> 8)) << 32) |
@@ -1606,6 +1628,8 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
fcp = isp->isp_param;
+ isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Entry");
+
/*
* XXX: Here is where we would start a 'loop dead' timeout
*/
@@ -1689,7 +1713,11 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return (-1);
}
- fcp->isp_loopid = mbs.param[1];
+ if (IS_2KLOGIN(isp)) {
+ 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) {
@@ -1840,10 +1868,11 @@ not_on_fabric:
lp->loggedin = lp->valid = 1;
count = fcp->isp_iid;
(void) isp_async(isp, ISPASYNC_PROMENADE, &count);
+ isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Complete");
return (0);
}
-static char *
+static const char *
isp2100_fw_statename(int state)
{
switch(state) {
@@ -2209,11 +2238,15 @@ isp_scan_loop(ispsoftc_t *isp)
hival = FC_PORT_ID;
break;
default:
+ isp_prt(isp, ISP_LOGDEBUG0, "no loop scasn\n");
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);
+
+
/*
* make sure the temp port database is clean...
*/
@@ -2233,30 +2266,30 @@ isp_scan_loop(ispsoftc_t *isp)
/*
* Don't even try for ourselves...
*/
- if (loopid == fcp->isp_loopid)
+ if (loopid == fcp->isp_loopid) {
continue;
+ }
- lp->node_wwn = isp_get_portname(isp, loopid, 1);
- if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
- return (-1);
- if (lp->node_wwn == 0)
- continue;
- lp->port_wwn = isp_get_portname(isp, loopid, 0);
- if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
- return (-1);
- if (lp->port_wwn == 0) {
- lp->node_wwn = 0;
- continue;
+ if (IS_2100(isp) || IS_2200(isp)) {
+ lp->node_wwn = isp_get_portname(isp, loopid, 1);
+ if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
+ return (-1);
+ }
+ if (lp->node_wwn == 0) {
+ continue;
+ }
}
/*
* Get an entry....
*/
if (isp_getpdb(isp, loopid, &pdb) != 0) {
- if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
+ if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
return (-1);
+ }
continue;
}
+
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
return (-1);
}
@@ -2523,6 +2556,8 @@ isp_scan_fabric(ispsoftc_t *isp, int ftype)
return (0);
}
+ isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GA_NXT)");
+
FC_SCRATCH_ACQUIRE(isp);
/*
@@ -2689,6 +2724,8 @@ isp_scan_fabric(ispsoftc_t *isp, int ftype)
return (0);
}
+ isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT)");
+
FC_SCRATCH_ACQUIRE(isp);
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
@@ -3425,11 +3462,13 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
if (IS_SCSI(isp)) {
mbs.param[1] =
((sdparam *) isp->isp_param)->isp_bus_reset_delay;
- if (mbs.param[1] < 2)
+ if (mbs.param[1] < 2) {
mbs.param[1] = 2;
+ }
bus = *((int *) arg);
- if (IS_DUALBUS(isp))
+ if (IS_DUALBUS(isp)) {
mbs.param[2] = bus;
+ }
} else {
mbs.param[1] = 10;
bus = 0;
@@ -3549,6 +3588,9 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
if (IS_FC(isp)) {
mbs.param[0] = MBOX_INIT_LIP;
+ if (IS_2KLOGIN(isp)) {
+ mbs.obits |= (1 << 10);
+ }
isp_mboxcmd(isp, &mbs, MBLOGALL);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
return (0);
@@ -3966,8 +4008,9 @@ again:
}
}
isp_prt(isp, ISP_LOGDEBUG2,
- "asked for %ld got resid %ld", (long) XS_XFRLEN(xs),
- (long) sp->req_resid);
+ "asked for %ld got raw resid %ld settled for %ld",
+ (long) XS_XFRLEN(xs), (long) sp->req_resid,
+ (long) XS_RESID(xs));
break;
case RQSTYPE_REQUEST:
if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
@@ -4085,6 +4128,20 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
isp_async(isp, ISPASYNC_BUS_RESET, &bus);
break;
case ASYNC_SYSTEM_ERROR:
+ isp->isp_state = ISP_CRASHED;
+ if (IS_FC(isp)) {
+ FCPARAM(isp)->isp_loopstate = LOOP_NIL;
+ FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+ }
+ /*
+ * Were we waiting for a mailbox command to complete?
+ * If so, it's dead, so wake up the waiter.
+ */
+ if (isp->isp_mboxbsy) {
+ isp->isp_obits = 1;
+ isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
+ MBOX_NOTIFY_COMPLETE(isp);
+ }
#ifdef ISP_FW_CRASH_DUMP
/*
* If we have crash dumps enabled, it's up to the handler
@@ -4810,6 +4867,9 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs)
mbreg_t mbs;
MEMZERO(&mbs, sizeof (mbs));
mbs.param[0] = MBOX_INIT_LIP;
+ if (IS_2KLOGIN(isp)) {
+ mbs.obits |= (1 << 10);
+ }
isp_mboxcmd_qnw(isp, &mbs, 1);
}
@@ -4893,6 +4953,7 @@ isp_mbox_continue(ispsoftc_t *isp)
switch (isp->isp_lastmbxcmd) {
case MBOX_WRITE_RAM_WORD:
case MBOX_READ_RAM_WORD:
+ case MBOX_WRITE_RAM_WORD_EXTENDED:
case MBOX_READ_RAM_WORD_EXTENDED:
break;
default:
@@ -4919,10 +4980,25 @@ isp_mbox_continue(ispsoftc_t *isp)
mbs.param[2] = *ptr++;
mbs.param[1] = isp->isp_mbxwrk1++;
break;
+ case MBOX_WRITE_RAM_WORD_EXTENDED:
+ mbs.param[2] = *ptr++;
+ mbs.param[1] = isp->isp_mbxwrk1++;
+ if (isp->isp_mbxwrk1 == 0) {
+ isp->isp_mbxwrk8++;
+ }
+ mbs.param[8] = isp->isp_mbxwrk8;
+ break;
case MBOX_READ_RAM_WORD:
+ *ptr++ = isp->isp_mboxtmp[2];
+ mbs.param[1] = isp->isp_mbxwrk1++;
+ break;
case MBOX_READ_RAM_WORD_EXTENDED:
*ptr++ = isp->isp_mboxtmp[2];
mbs.param[1] = isp->isp_mbxwrk1++;
+ if (isp->isp_mbxwrk1 == 0) {
+ isp->isp_mbxwrk8++;
+ }
+ mbs.param[8] = isp->isp_mbxwrk8;
break;
}
isp->isp_mbxworkp = ptr;
@@ -5146,9 +5222,9 @@ static const uint32_t mbpfc[] = {
ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
ISPOPMAP(0x00, 0x00), /* 0x0b: */
ISPOPMAP(0x00, 0x00), /* 0x0c: */
- ISPOPMAP(0x00, 0x00), /* 0x0d: */
+ ISPOPMAP(0x13, 0x01), /* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED) */
ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
- ISPOPMAP(0x03, 0x07), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED(1) */
+ ISPOPMAP(0x13, 0x05), /* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
@@ -5266,7 +5342,8 @@ static const uint32_t mbpfc[] = {
*
* (1): this sets bits 21..16 in mailbox register #8, which we nominally
* do not access at this time in the core driver. The caller is
- * responsible for setting this register first (Gross!).
+ * responsible for setting this register first (Gross!). The assumption
+ * is that we won't overflow.
*/
#ifndef ISP_STRIPPED
@@ -5282,7 +5359,7 @@ static char *fc_mbcmd_names[] = {
"ABOUT FIRMWARE",
"LOAD RAM",
"DUMP RAM",
- NULL,
+ "WRITE RAM WORD EXTENDED",
NULL,
"READ RAM WORD EXTENDED",
"CHECK FIRMWARE",
@@ -5342,7 +5419,7 @@ static char *fc_mbcmd_names[] = {
NULL,
NULL,
NULL,
- "GET PORT DATABASE,, ENHANCED",
+ "GET PORT DATABASE ENHANCED",
NULL,
NULL,
NULL,
@@ -5465,6 +5542,9 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
ibits = HIWRD(mcp[opcode]) & NMBOX_BMASK(isp);
obits = LOWRD(mcp[opcode]) & NMBOX_BMASK(isp);
+ /*
+ * Pick up any additional bits that the caller might have set.
+ */
ibits |= mbp->ibits;
obits |= mbp->obits;
@@ -5504,10 +5584,10 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp, int logmask)
*/
MBOX_WAIT_COMPLETE(isp);
+ /*
+ * Did the command time out?
+ */
if (isp->isp_mboxbsy) {
- /*
- * Command timed out.
- */
isp->isp_mboxbsy = 0;
MBOX_RELEASE(isp);
return;
@@ -5773,9 +5853,7 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
-#ifndef ISP_NO_FASTPOST_FC
fcp->isp_fwoptions |= ICBOPT_FAST_POST;
-#endif
if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
@@ -5791,8 +5869,9 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
*/
if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
nvfail = isp_read_nvram(isp);
- if (nvfail)
+ if (nvfail) {
isp->isp_confopts |= ISP_CFG_NONVRAM;
+ }
} else {
nvfail = 1;
}
@@ -5816,6 +5895,11 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
* from NVRAM or our platform default.
*/
ISP_NODEWWN(isp) = fcp->isp_nodewwn;
+ if (fcp->isp_nodewwn == 0) {
+ isp_prt(isp, ISP_LOGCONFIG,
+ "bad WWNN- using default\n");
+ ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
+ }
}
if (isp->isp_confopts & ISP_CFG_OWNWWPN) {
isp_prt(isp, ISP_LOGCONFIG, "Using Port WWN 0x%08x%08x",
@@ -5828,6 +5912,11 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
* from NVRAM or our platform default.
*/
ISP_PORTWWN(isp) = fcp->isp_portwwn;
+ if (fcp->isp_portwwn == 0) {
+ isp_prt(isp, ISP_LOGCONFIG,
+ "bad WWPN- using default\n");
+ ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
+ }
}
return;
}
@@ -6019,7 +6108,7 @@ isp_reinit(ispsoftc_t *isp)
static int
isp_read_nvram(ispsoftc_t *isp)
{
- int i, amt;
+ int i, amt, retval;
uint8_t csum, minversion;
union {
uint8_t _x[ISP2100_NVRAM_SIZE];
@@ -6053,7 +6142,8 @@ isp_read_nvram(ispsoftc_t *isp)
isp_prt(isp, ISP_LOGDEBUG0, "%x %x %x",
nvram_data[0], nvram_data[1], nvram_data[2]);
}
- return (-1);
+ retval = -1;
+ goto out;
}
for (i = 2; i < amt>>1; i++) {
isp_rdnvram_word(isp, i, &nvram_words[i]);
@@ -6063,12 +6153,14 @@ isp_read_nvram(ispsoftc_t *isp)
}
if (csum != 0) {
isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
- return (-1);
+ 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));
- return (-1);
+ retval = -1;
+ goto out;
}
if (IS_ULTRA3(isp)) {
@@ -6085,7 +6177,9 @@ isp_read_nvram(ispsoftc_t *isp)
} else {
isp_parse_nvram_2100(isp, nvram_data);
}
- return (0);
+ retval = 0;
+out:
+ return (retval);
#undef nvram_data
#undef nvram_words
}
@@ -6094,15 +6188,15 @@ static void
isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
{
int i, cbits;
- uint16_t bit, rqst;
+ uint16_t bit, rqst, junk;
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
- USEC_DELAY(2);
+ USEC_DELAY(10);
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
- USEC_DELAY(2);
+ USEC_DELAY(10);
if (IS_FC(isp)) {
- wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
+ wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
if (IS_2312(isp) && isp->isp_port) {
wo += 128;
}
@@ -6128,11 +6222,14 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
bit = BIU_NVRAM_SELECT;
}
ISP_WRITE(isp, BIU_NVRAM, bit);
- USEC_DELAY(2);
+ USEC_DELAY(10);
+ junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK);
- USEC_DELAY(2);
+ USEC_DELAY(10);
+ junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
ISP_WRITE(isp, BIU_NVRAM, bit);
- USEC_DELAY(2);
+ USEC_DELAY(10);
+ junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
}
/*
* Now read the result back in (bits come back in MSB format).
@@ -6142,17 +6239,19 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
uint16_t rv;
*rp <<= 1;
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
- USEC_DELAY(2);
+ USEC_DELAY(10);
rv = ISP_READ(isp, BIU_NVRAM);
if (rv & BIU_NVRAM_DATAIN) {
*rp |= 1;
}
- USEC_DELAY(2);
+ USEC_DELAY(10);
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
- USEC_DELAY(2);
+ USEC_DELAY(10);
+ junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
}
ISP_WRITE(isp, BIU_NVRAM, 0);
- USEC_DELAY(2);
+ USEC_DELAY(10);
+ junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
ISP_SWIZZLE_NVRAM_WORD(isp, rp);
}
@@ -6492,7 +6591,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
}
fcp->isp_portwwn = wwn;
if (IS_2200(isp) || IS_23XX(isp)) {
- wwn = ISP2200_NVRAM_NODE_NAME(nvram_data);
+ wwn = ISP2100_NVRAM_NODE_NAME(nvram_data);
if (wwn) {
isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
(uint32_t) (wwn >> 32),
@@ -6532,13 +6631,6 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
}
}
- isp_prt(isp, ISP_LOGDEBUG0,
- "NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x loopid %x",
- ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data),
- ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data),
- ISP2100_NVRAM_OPTIONS(nvram_data),
- ISP2100_NVRAM_HARDLOOPID(nvram_data));
-
fcp->isp_maxalloc =
ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0)
@@ -6555,6 +6647,23 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
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",
+ (uint32_t) (fcp->isp_nodewwn >> 32), (uint32_t) fcp->isp_nodewwn,
+ (uint32_t) (fcp->isp_portwwn >> 32), (uint32_t) fcp->isp_portwwn,
+ ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data),
+ ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data));
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "execthrottle %d fwoptions 0x%x hardloop %d tov %d",
+ ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data),
+ ISP2100_NVRAM_OPTIONS(nvram_data),
+ ISP2100_NVRAM_HARDLOOPID(nvram_data),
+ ISP2100_NVRAM_TOV(nvram_data));
+ fcp->isp_xfwoptions = ISP2100_XFW_OPTIONS(nvram_data);
+ fcp->isp_zfwoptions = ISP2100_ZFW_OPTIONS(nvram_data);
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "xfwoptions 0x%x zfw options 0x%x",
+ ISP2100_XFW_OPTIONS(nvram_data), ISP2100_ZFW_OPTIONS(nvram_data));
}
#ifdef ISP_FW_CRASH_DUMP
@@ -6844,19 +6953,13 @@ isp2300_fw_dump(ispsoftc_t *isp)
}
ptr = isp->isp_mbxworkp; /* finish fetch of final word */
*ptr++ = isp->isp_mboxtmp[2];
-
- /*
- * We don't have access to mailbox registers 8.. onward
- * in our 'common' device model- so we have to set it
- * here and hope it stays the same!
- */
- ISP_WRITE(isp, PCI_MBOX_REGS2300_OFF + (8 << 1), 0x1);
-
mbs.param[0] = MBOX_READ_RAM_WORD_EXTENDED;
mbs.param[1] = 0;
+ mbs.param[8] = 1;
isp->isp_mbxworkp = (void *) ptr;
isp->isp_mbxwrk0 = 0xffff; /* continuation count */
isp->isp_mbxwrk1 = 0x1; /* next SRAM address */
+ isp->isp_mbxwrk8 = 0x1;
isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGWARN,
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 09e05bb..1186cce 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -165,6 +165,9 @@ static struct ispmdvec mdvec_2300 = {
#ifndef PCIM_CMD_SEREN
#define PCIM_CMD_SEREN 0x0100
#endif
+#ifndef PCIM_CMD_INTX_DISABLE
+#define PCIM_CMD_INTX_DISABLE 0x0400
+#endif
#ifndef PCIR_COMMAND
#define PCIR_COMMAND 0x04
@@ -874,10 +877,7 @@ isp_pci_attach(device_t dev)
* Try and find firmware for this device.
*/
- /*
- * Don't even attempt to get firmware for the 2322/2422 (yet)
- */
- if (IS_2322(isp) == 0 && IS_24XX(isp) == 0 && isp_get_firmware_p) {
+ if (isp_get_firmware_p) {
int device = (int) pci_get_device(dev);
#ifdef ISP_TARGET_MODE
(*isp_get_firmware_p)(0, 1, device, &mdvp->dv_ispfw);
@@ -902,6 +902,11 @@ isp_pci_attach(device_t dev)
isp->isp_touched = 1;
}
+
+ if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) {
+ cmd &= ~PCIM_CMD_INTX_DISABLE;
+ }
+
pci_write_config(dev, PCIR_COMMAND, cmd, 2);
/*
@@ -1114,6 +1119,7 @@ isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp,
uint16_t *semap, uint16_t *mbox0p)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
+ uint16_t hccr;
uint32_t r2hisr;
if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) {
@@ -1158,6 +1164,16 @@ isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp,
*semap = 0;
return (1);
default:
+ hccr = ISP_READ(isp, HCCR);
+ if (hccr & HCCR_PAUSE) {
+ ISP_WRITE(isp, HCCR, HCCR_RESET);
+ isp_prt(isp, ISP_LOGERR,
+ "RISC paused at interrupt (%x->%x\n", hccr,
+ ISP_READ(isp, HCCR));
+ } else {
+ isp_prt(isp, ISP_LOGERR, "unknown interrerupt 0x%x\n",
+ r2hisr);
+ }
return (0);
}
}
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index e79efa2..2ef8d51 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -46,7 +46,7 @@
/* a */
/* b */
/* c */
- /* d */
+#define MBOX_WRITE_RAM_WORD_EXTENDED 0x000d
#define MBOX_CHECK_FIRMWARE 0x000e
#define MBOX_READ_RAM_WORD_EXTENDED 0x000f
#define MBOX_INIT_REQ_QUEUE 0x0010
@@ -691,9 +691,11 @@ typedef struct isp_icb {
#define ICBXOPT_RIO_16BIT_IOCB 3
#define ICBXOPT_RIO_32BIT_IOCB 4
#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)
diff --git a/sys/dev/isp/ispreg.h b/sys/dev/isp/ispreg.h
index a53751f..8c5e5d4 100644
--- a/sys/dev/isp/ispreg.h
+++ b/sys/dev/isp/ispreg.h
@@ -204,7 +204,8 @@
#define BIU2100_FB_REGS (1 << 4) /* FrameBuffer Regs */
#define BIU2100_FPM0_REGS (2 << 4) /* FPM 0 Regs */
#define BIU2100_FPM1_REGS (3 << 4) /* FPM 1 Regs */
-#define BIU2100_PCI64 0x04 /* R: 64 Bit PCI slot */
+#define BIU2100_NVRAM_OFFSET (1 << 14)
+#define BIU2100_FLASH_UPPER_64K 0x04 /* RW: Upper 64K Bank Select */
#define BIU2100_FLASH_ENABLE 0x02 /* RW: Enable Flash RAM */
#define BIU2100_SOFT_RESET 0x01
/* SOFT RESET FOR ISP2100 is same bit, but in this register, not ICR */
@@ -268,6 +269,7 @@
#define BIU_NVRAM_SELECT 0x0002
#define BIU_NVRAM_DATAOUT 0x0004
#define BIU_NVRAM_DATAIN 0x0008
+#define BIU_NVRAM_BUSY 0x0080 /* 2322/24xx only */
#define ISP_NVRAM_READ 6
/* COMNMAND && DATA DMA CONFIGURATION REGISTER */
@@ -947,7 +949,7 @@ typedef struct {
#define ISP2100_NVRAM_SIZE 256
/* ISP_NVRAM_VERSION is in same overall place */
#define ISP2100_NVRAM_RISCVER(c) (c)[6]
-#define ISP2100_NVRAM_OPTIONS(c) (c)[8]
+#define ISP2100_NVRAM_OPTIONS(c) ((c)[8] | ((c)[9] << 8))
#define ISP2100_NVRAM_MAXFRAMELENGTH(c) (((c)[10]) | ((c)[11] << 8))
#define ISP2100_NVRAM_MAXIOCBALLOCATION(c) (((c)[12]) | ((c)[13] << 8))
#define ISP2100_NVRAM_EXECUTION_THROTTLE(c) (((c)[14]) | ((c)[15] << 8))
@@ -964,9 +966,10 @@ typedef struct {
(((uint64_t)(c)[24]) << 8) | \
(((uint64_t)(c)[25]) << 0))
-#define ISP2100_NVRAM_HARDLOOPID(c) (c)[26]
+#define ISP2100_NVRAM_HARDLOOPID(c) ((c)[26] | ((c)[27] << 8))
+#define ISP2100_NVRAM_TOV(c) ((c)[29])
-#define ISP2200_NVRAM_NODE_NAME(c) (\
+#define ISP2100_NVRAM_NODE_NAME(c) (\
(((uint64_t)(c)[30]) << 56) | \
(((uint64_t)(c)[31]) << 48) | \
(((uint64_t)(c)[32]) << 40) | \
@@ -976,7 +979,16 @@ typedef struct {
(((uint64_t)(c)[36]) << 8) | \
(((uint64_t)(c)[37]) << 0))
-#define ISP2100_NVRAM_HBA_OPTIONS(c) (c)[70]
+#define ISP2100_XFW_OPTIONS(c) ((c)[38] | ((c)[39] << 8))
+
+#define ISP2100_RACC_TIMER(c) (c)[40]
+#define ISP2100_IDELAY_TIMER(c) (c)[41]
+
+#define ISP2100_ZFW_OPTIONS(c) ((c)[42] | ((c)[43] << 8))
+
+#define ISP2100_SERIAL_LINK(c) ((c)[68] | ((c)[69] << 8))
+
+#define ISP2100_NVRAM_HBA_OPTIONS(c) ((c)[70] | ((c)[71] << 8))
#define ISP2100_NVRAM_HBA_DISABLE(c) ISPBSMX(c, 70, 0, 0x01)
#define ISP2100_NVRAM_BIOS_DISABLE(c) ISPBSMX(c, 70, 1, 0x01)
#define ISP2100_NVRAM_LUN_DISABLE(c) ISPBSMX(c, 70, 2, 0x01)
@@ -995,8 +1007,9 @@ typedef struct {
(((uint64_t)(c)[79]) << 0))
#define ISP2100_NVRAM_BOOT_LUN(c) (c)[80]
+#define ISP2100_RESET_DELAY(c) (c)[81]
-#define ISP2200_HBA_FEATURES(c) (c)[232] | ((c)[233] << 8)
+#define ISP2100_HBA_FEATURES(c) ((c)[232] | ((c)[233] << 8))
/*
* Firmware Crash Dump
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 3b0ef8d..59a7cd0 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -234,17 +234,19 @@ typedef struct {
typedef struct {
uint32_t : 13,
isp_gbspeed : 3,
- : 2,
+ : 1,
isp_iid_set : 1,
loop_seen_once : 1,
isp_loopstate : 4, /* Current Loop State */
- isp_fwstate : 3, /* ISP F/W state */
+ isp_fwstate : 4, /* ISP F/W state */
isp_gotdparms : 1,
isp_topo : 3,
isp_onfabric : 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 */
@@ -380,8 +382,7 @@ struct ispsoftc {
* Volatile state
*/
- volatile uint32_t
- isp_obits : 8, /* mailbox command output */
+ volatile uint32_t : 8,
isp_mboxbsy : 1, /* mailbox command active */
isp_state : 3,
isp_sendmarker : 2, /* send a marker entry */
@@ -393,11 +394,13 @@ struct ispsoftc {
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 uint16_t isp_mboxtmp[MAILBOX_STORAGE];
volatile uint16_t isp_lastmbxcmd; /* last mbox command sent */
volatile uint16_t isp_mbxwrk0;
volatile uint16_t isp_mbxwrk1;
volatile uint16_t isp_mbxwrk2;
+ volatile uint16_t isp_mbxwrk8;
void * isp_mbxworkp;
/*
@@ -428,9 +431,10 @@ struct ispsoftc {
* ISP Driver Run States
*/
#define ISP_NILSTATE 0
-#define ISP_RESETSTATE 1
-#define ISP_INITSTATE 2
-#define ISP_RUNSTATE 3
+#define ISP_CRASHED 1
+#define ISP_RESETSTATE 2
+#define ISP_INITSTATE 3
+#define ISP_RUNSTATE 4
/*
* ISP Configuration Options
OpenPOWER on IntegriCloud