summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>1999-11-21 03:18:22 +0000
committermjacob <mjacob@FreeBSD.org>1999-11-21 03:18:22 +0000
commit0d75a5b4eba342471dab7a58b0b0c2174f6e341b (patch)
treea6dff8dbe2b38abe4e075e90258dcc7155545506
parent1a6884ad3f584d66a116f9c5cddd835db47113b4 (diff)
downloadFreeBSD-src-0d75a5b4eba342471dab7a58b0b0c2174f6e341b.zip
FreeBSD-src-0d75a5b4eba342471dab7a58b0b0c2174f6e341b.tar.gz
Clean up stupidity in the isp_handle_other_response function- indexes
of queue entries have to be at least 16 bits now! If we're running a 2100 less than rev 5, turn off loop fairness (per Qlogic errata). Fix typo in checking against 2200 F/W revision. Slightly fix/reorder fabric login stuff. Change to usage of isp_getrqentry for code clarity. Add some defensive dual bus assumptions. Various cleanups, etc...
-rw-r--r--sys/dev/isp/isp.c288
1 files changed, 169 insertions, 119 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index f268ab5..6f7dc07 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -70,7 +70,7 @@
*/
static int isp_parse_async __P((struct ispsoftc *, int));
static int isp_handle_other_response
-__P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *));
+__P((struct ispsoftc *, ispstatusreq_t *, u_int16_t *));
static void isp_parse_status
__P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *));
static void isp_fastpost_complete __P((struct ispsoftc *, u_int32_t));
@@ -133,7 +133,7 @@ isp_reset(isp)
* case, we don't really use this yet, but we may in
* the future.
*/
- if (isp->isp_used == 0) {
+ if (isp->isp_touched == 0) {
/*
* Just in case it was paused...
*/
@@ -149,7 +149,7 @@ isp_reset(isp)
isp->isp_romfw_rev[1] = mbs.param[2];
isp->isp_romfw_rev[2] = mbs.param[3];
}
- isp->isp_used = 1;
+ isp->isp_touched = 1;
}
DISABLE_INTS(isp);
@@ -959,7 +959,14 @@ isp_fibre_init(isp)
#else
fcp->isp_fwoptions = 0;
#endif
+
fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
+ /*
+ * 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;
+ }
fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
/*
@@ -1076,12 +1083,6 @@ isp_fibre_init(isp)
* Whatever happens, we're now committed to being here.
*/
isp->isp_state = ISP_INITSTATE;
-
-#ifdef ISP_TARGET_MODE
- if (isp_modify_lun(isp, 0, 1, 1)) {
- PRINTF("%s: failed to enable target mode\n", isp->isp_name);
- }
-#endif
}
/*
@@ -1234,7 +1235,7 @@ isp_fclink_test(isp, waitdelay)
return (-1);
}
fcp->isp_loopid = mbs.param[1];
- if (isp->isp_type == ISP_HA_FC_2100) {
+ if (isp->isp_type == ISP_HA_FC_2200) {
if (ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(2, 0, 14)) {
topo = (int) mbs.param[6];
}
@@ -1345,11 +1346,11 @@ isp_pdb_sync(isp, target)
* FL_PORT_ID times).
*/
tport = fcp->tport;
+ /*
+ * make sure the temp port database is clean...
+ */
MEMZERO((void *) tport, sizeof (tport));
for (lim = loopid = 0; loopid < FL_PORT_ID; loopid++) {
- /*
- * make sure the temp port database is clean...
- */
lp = &tport[loopid];
lp->node_wwn = isp_get_portname(isp, loopid, 1);
if (lp->node_wwn == 0)
@@ -1372,7 +1373,7 @@ isp_pdb_sync(isp, target)
* asked for, restart the process entirely (up to a point...).
*/
if (pdb.pdb_loopid != loopid) {
- IDPRINTF(0, ("%s: wankage (%d != %d)\n",
+ IDPRINTF(1, ("%s: wankage (%d != %d)\n",
isp->isp_name, pdb.pdb_loopid, loopid));
loopid = 0;
if (lim++ < FL_PORT_ID) {
@@ -1575,7 +1576,7 @@ isp_pdb_sync(isp, target)
continue;
/*
- * Tell the outside world we've gone away;
+ * Tell the outside world we've gone away.
*/
loopid = lp - fcp->portdb;
(void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid);
@@ -1619,48 +1620,94 @@ isp_pdb_sync(isp, target)
mbs.param[2] = lp->portid >> 16;
mbs.param[3] = lp->portid & 0xffff;
isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
- lp->valid = 1;
- lp->fabdev = 1;
- if (isp_getpdb(isp, loopid, &pdb) != 0) {
- /*
- * Be kind...
- */
- lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
- PRINTF("%s: Faked PortID 0x%x into LoopID %d\n",
- isp->isp_name, lp->portid, lp->loopid);
- } else if (pdb.pdb_loopid != lp->loopid) {
- lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
- PRINTF("%s: Wanked PortID 0x%x to LoopID %d\n",
- isp->isp_name, lp->portid, lp->loopid);
- } else {
- 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->node_wwn =
- (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
- (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
- (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
- (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
- (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
- (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
- (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
- (((u_int64_t)pdb.pdb_nodename[7]));
- lp->port_wwn =
- (((u_int64_t)pdb.pdb_portname[0]) << 56) |
- (((u_int64_t)pdb.pdb_portname[1]) << 48) |
- (((u_int64_t)pdb.pdb_portname[2]) << 40) |
- (((u_int64_t)pdb.pdb_portname[3]) << 32) |
- (((u_int64_t)pdb.pdb_portname[4]) << 24) |
- (((u_int64_t)pdb.pdb_portname[5]) << 16) |
- (((u_int64_t)pdb.pdb_portname[6]) << 8) |
- (((u_int64_t)pdb.pdb_portname[7]));
- (void) isp_async(isp, ISPASYNC_PDB_CHANGED,
- &loopid);
+ switch (mbs.param[0]) {
+ case MBOX_COMMAND_COMPLETE:
+ break;
+ case MBOX_COMMAND_ERROR:
+ switch (mbs.param[1]) {
+ case 1:
+ PRINTF("%s: no loop\n", isp->isp_name);
+ break;
+ case 2:
+ PRINTF("%s: IOCB buffer could not be alloced\n",
+ isp->isp_name);
+ break;
+ case 3:
+ PRINTF("%s: could not alloc xchange resource\n",
+ isp->isp_name);
+ break;
+ case 4:
+ PRINTF("%s: ELS timeout\n", isp->isp_name);
+ break;
+ case 5:
+ PRINTF("%s: no fabric port\n", isp->isp_name);
+ break;
+ case 6:
+ PRINTF("%s: remote device cannot be a target\n",
+ isp->isp_name);
+ break;
+ default:
+ break;
}
+ continue;
+ default:
+ continue;
+ }
+
+ lp->valid = 1;
+ lp->fabdev = 1;
+ if (isp_getpdb(isp, loopid, &pdb) != 0) {
+ /*
+ * Be kind...
+ */
+ lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
+ PRINTF("%s: Faked PortID 0x%x into LoopID %d\n",
+ isp->isp_name, lp->portid, lp->loopid);
+ continue;
+ }
+ if (pdb.pdb_loopid != lp->loopid) {
+ lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
+ PRINTF("%s: Wanked PortID 0x%x to LoopID %d\n",
+ isp->isp_name, lp->portid, lp->loopid);
+ continue;
}
+ lp->roles =
+ (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
+ lp->portid = BITS2WORD(pdb.pdb_portid_bits);
+ lp->loopid = loopid;
+ lp->node_wwn =
+ (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
+ (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
+ (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
+ (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
+ (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
+ (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
+ (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
+ (((u_int64_t)pdb.pdb_nodename[7]));
+ lp->port_wwn =
+ (((u_int64_t)pdb.pdb_portname[0]) << 56) |
+ (((u_int64_t)pdb.pdb_portname[1]) << 48) |
+ (((u_int64_t)pdb.pdb_portname[2]) << 40) |
+ (((u_int64_t)pdb.pdb_portname[3]) << 32) |
+ (((u_int64_t)pdb.pdb_portname[4]) << 24) |
+ (((u_int64_t)pdb.pdb_portname[5]) << 16) |
+ (((u_int64_t)pdb.pdb_portname[6]) << 8) |
+ (((u_int64_t)pdb.pdb_portname[7]));
+ /*
+ * Check to make sure this all makes sense.
+ */
+ if (lp->node_wwn && lp->port_wwn) {
+ (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid);
+ continue;
+ }
+ lp->fabdev = lp->valid = 0;
+ PRINTF("%s: Target %d (Loop 0x%x) Port ID 0x%x lost its WWN\n",
+ isp->isp_name, loopid, lp->loopid, lp->portid);
+ mbs.param[0] = MBOX_FABRIC_LOGOUT;
+ mbs.param[1] = lp->loopid << 8;
+ mbs.param[2] = 0;
+ mbs.param[3] = 0;
+ isp_mboxcmd(isp, &mbs);
}
#endif
return (0);
@@ -1734,7 +1781,7 @@ ispscsicmd(xs)
ISP_SCSI_XFER_T *xs;
{
struct ispsoftc *isp;
- u_int8_t iptr, optr;
+ u_int16_t iptr, optr;
union {
ispreq_t *_reqp;
ispreqt2_t *_t2reqp;
@@ -1823,7 +1870,8 @@ ispscsicmd(xs)
/*
* 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
+ * we have to go off and (re)synchronize our port
+ * database.
*/
if (fcp->isp_loopstate == LOOP_PDB_RCVD) {
if (isp_pdb_sync(isp, target)) {
@@ -1860,13 +1908,8 @@ ispscsicmd(xs)
isp_update(isp);
}
- optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
- iptr = isp->isp_reqidx;
-
- reqp = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
- if (iptr == optr) {
- IDPRINTF(0, ("%s: Request Queue Overflow\n", isp->isp_name));
+ if (isp_getrqentry(isp, &iptr, &optr, (void **) &reqp)) {
+ IDPRINTF(1, ("%s: Request Queue Overflow\n", isp->isp_name));
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
}
@@ -1877,7 +1920,7 @@ ispscsicmd(xs)
* than which we got here to send a command to.
*/
if (isp->isp_sendmarker) {
- u_int8_t niptr, n = (IS_12X0(isp)? 2: 1);
+ u_int8_t n = (IS_12X0(isp)? 2: 1);
/*
* Check ports to send markers for...
*/
@@ -1891,23 +1934,15 @@ ispscsicmd(xs)
reqp->req_modifier = SYNC_ALL;
reqp->req_target = i << 7; /* insert bus number */
ISP_SWIZZLE_REQUEST(isp, reqp);
+ MemoryBarrier();
+ ISP_ADD_REQUEST(isp, iptr);
- /*
- * Unconditionally update the input pointer anyway.
- */
- ISP_WRITE(isp, INMAILBOX4, iptr);
- isp->isp_reqidx = iptr;
-
- niptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
- if (niptr == optr) {
- IDPRINTF(0, ("%s: Request Queue Overflow+\n",
+ if (isp_getrqentry(isp, &iptr, &optr, (void **)&reqp)) {
+ IDPRINTF(1, ("%s: Request Queue Overflow+\n",
isp->isp_name));
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
}
- reqp = (ispreq_t *)
- ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = niptr;
}
}
@@ -1993,8 +2028,7 @@ ispscsicmd(xs)
isp->isp_name, XS_CHANNEL(xs), target, XS_LUN(xs),
reqp->req_cdb[0], XS_XFRLEN(xs)));
MemoryBarrier();
- ISP_WRITE(isp, INMAILBOX4, iptr);
- isp->isp_reqidx = iptr;
+ ISP_ADD_REQUEST(isp, iptr);
isp->isp_nactive++;
if (isp->isp_sendmarker)
isp->isp_sendmarker = 0;
@@ -2110,6 +2144,13 @@ isp_control(isp, ctl, arg)
case ISPCTL_FCLINK_TEST:
return (isp_fclink_test(isp, FC_FW_READY_DELAY));
+#ifdef ISP_TARGET_MODE
+ case ISPCTL_ENABLE_LUN:
+ return (isp_modify_lun, 1, arg));
+
+ case ISPCTL_MODIFY_LUN:
+ return (isp_modify_lun, 0, arg));
+#endif
}
return (-1);
}
@@ -2127,7 +2168,7 @@ isp_intr(arg)
{
ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs;
struct ispsoftc *isp = arg;
- u_int8_t iptr, optr;
+ u_int16_t iptr, optr;
u_int16_t isr, isrb, sema;
int i, nlooked = 0, ndone = 0;
@@ -2190,7 +2231,7 @@ isp_intr(arg)
while (optr != iptr) {
ispstatusreq_t *sp;
- u_int8_t oop;
+ u_int16_t oop;
int buddaboom = 0;
sp = (ispstatusreq_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);
@@ -2402,26 +2443,30 @@ isp_parse_async(isp, mbox)
struct ispsoftc *isp;
int mbox;
{
+ int bus;
u_int32_t fast_post_handle = 0;
+ /*
+ * It is not documented anywhere that bus is always in OUTMAILBOX6
+ * for dual bus cards- and we don't have the h/w to prove it either,
+ * So we'll just assume......
+ */
+ if (IS_1080(isp) || IS_12X0(isp)) {
+ bus = ISP_READ(isp, OUTMAILBOX6);
+ } else {
+ bus = 0;
+ }
+
switch (mbox) {
case MBOX_COMMAND_COMPLETE: /* sometimes these show up */
break;
case ASYNC_BUS_RESET:
- {
- int bus;
- if (IS_1080(isp) || IS_12X0(isp)) {
- bus = ISP_READ(isp, OUTMAILBOX6);
- } else {
- bus = 0;
- }
isp->isp_sendmarker = (1 << bus);
- isp_async(isp, ISPASYNC_BUS_RESET, &bus);
#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
+ isp_target_async(isp, bus, ASYNC_BUS_RESET);
#endif
+ isp_async(isp, ISPASYNC_BUS_RESET, &bus);
break;
- }
case ASYNC_SYSTEM_ERROR:
mbox = ISP_READ(isp, OUTMAILBOX1);
PRINTF("%s: Internal FW Error @ RISC Addr 0x%x\n",
@@ -2439,26 +2484,28 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_QWAKEUP:
- /* don't need to be chatty */
+ /*
+ * We've just been notified that the Queue has woken up.
+ * We don't need to be chatty about this- just unlatch things
+ * and move on.
+ */
mbox = ISP_READ(isp, OUTMAILBOX4);
break;
case ASYNC_TIMEOUT_RESET:
- PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name);
- isp->isp_sendmarker = 1;
+ PRINTF("%s: timeout initiated SCSI bus reset of bus %d\n",
+ isp->isp_name, bus);
+ isp->isp_sendmarker = (1 << bus);
#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
+ isp_target_async(isp, bus, ASYNC_TIMEOUT_RESET);
#endif
break;
case ASYNC_DEVICE_RESET:
- /*
- * XXX: WHICH BUS?
- */
- isp->isp_sendmarker = 1;
- PRINTF("%s: device reset\n", isp->isp_name);
+ PRINTF("%s: device reset on bus %d\n", isp->isp_name, bus);
+ isp->isp_sendmarker = 1 << bus;
#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
+ isp_target_async(isp, bus, ASYNC_DEVICE_RESET);
#endif
break;
@@ -2482,9 +2529,6 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_BUS_TRANSIT:
- /*
- * XXX: WHICH BUS?
- */
mbox = ISP_READ(isp, OUTMAILBOX2);
switch (mbox & 0x1c00) {
case SXP_PINS_LVD_MODE:
@@ -2516,7 +2560,7 @@ isp_parse_async(isp, mbox)
* XXX: Set up to renegotiate again!
*/
/* Can only be for a 1080... */
- isp->isp_sendmarker = (1 << ISP_READ(isp, OUTMAILBOX6));
+ isp->isp_sendmarker = (1 << bus);
break;
case ASYNC_CMD_CMPLT:
@@ -2558,13 +2602,13 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_LOOP_RESET:
- isp->isp_sendmarker = 1;
+ isp->isp_sendmarker = 1 << bus;
((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL;
isp_mark_getpdb_all(isp);
PRINTF("%s: Loop RESET\n", isp->isp_name);
#ifdef ISP_TARGET_MODE
- isp_notify_ack(isp, NULL);
+ isp_target_async(isp, bus, ASYNC_LOOP_RESET);
#endif
break;
@@ -2591,11 +2635,17 @@ isp_parse_async(isp, mbox)
return (fast_post_handle);
}
+/*
+ * Handle other response entries. A pointer to the request queue output
+ * index is here in case we want to eat several entries at once, although
+ * this is not used currently.
+ */
+
static int
isp_handle_other_response(isp, sp, optrp)
struct ispsoftc *isp;
ispstatusreq_t *sp;
- u_int8_t *optrp;
+ u_int16_t *optrp;
{
switch (sp->req_header.rqs_entry_type) {
case RQSTYPE_ATIO:
@@ -2609,12 +2659,14 @@ isp_handle_other_response(isp, sp, optrp)
case RQSTYPE_CTIO2:
case RQSTYPE_CTIO3:
#ifdef ISP_TARGET_MODE
- return(isp_target_notify(isp, sp, optrp));
+ return (isp_target_entry(isp, sp));
#else
/* FALLTHROUGH */
#endif
case RQSTYPE_REQUEST:
default:
+ PRINTF("%s: unhandled response type 0x%x\n", isp->isp_name,
+ sp->req_header.rqs_entry_type);
return (-1);
}
}
@@ -3023,7 +3075,7 @@ static u_int8_t mbpcnt[] = {
MAKNIB(8, 1), /* 0x6b: MBOX_GET_LINK_STATUS */
MAKNIB(4, 4), /* 0x6c: MBOX_INIT_LIP_RESET */
MAKNIB(0, 0), /* 0x6d: */
- MAKNIB(8, 1), /* 0x6e: MBOX_SEND_SNS */
+ MAKNIB(8, 2), /* 0x6e: MBOX_SEND_SNS */
MAKNIB(4, 3), /* 0x6f: MBOX_FABRIC_LOGIN */
MAKNIB(2, 1), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
MAKNIB(2, 1), /* 0x71: MBOX_FABRIC_LOGOUT */
@@ -3484,7 +3536,7 @@ again:
mbs.param[0] = MBOX_GET_FW_STATE;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- IDPRINTF(0, ("%s: isp_fw_state 0x%x\n", isp->isp_name,
+ IDPRINTF(1, ("%s: isp_fw_state 0x%x\n", isp->isp_name,
mbs.param[0]));
switch (mbs.param[0]) {
case ASYNC_PDB_CHANGED:
@@ -3657,17 +3709,15 @@ isp_setdfltparm(isp, channel)
/* Platform specific.... */
fcp->isp_loopid = DEFAULT_LOOPID(isp);
fcp->isp_nodewwn = DEFAULT_WWN(isp);
- fcp->isp_portwwn = DEFAULT_WWN(isp);
+ fcp->isp_portwwn = 0;
/*
* Now try and read NVRAM
*/
- if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
- if (isp_read_nvram(isp)) {
- PRINTF("%s: using default WWN 0x%08x%08x\n",
- isp->isp_name,
- (u_int32_t)(fcp->isp_portwwn >> 32),
- (u_int32_t)(fcp->isp_portwwn & 0xffffffff));
- }
+ if ((isp->isp_confopts & (ISP_CFG_NONVRAM|ISP_CFG_OWNWWN)) ||
+ (isp_read_nvram(isp))) {
+ PRINTF("%s: using Node WWN 0x%08x%08x\n",
+ isp->isp_name, (u_int32_t)(fcp->isp_nodewwn >> 32),
+ (u_int32_t)(fcp->isp_nodewwn & 0xffffffff));
}
return;
}
OpenPOWER on IntegriCloud