summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormjacob <mjacob@cvs.openbsd.org>2000-07-06 05:31:50 +0000
committermjacob <mjacob@cvs.openbsd.org>2000-07-06 05:31:50 +0000
commit31aac79a59ca445d1cf6c71e52787efe67800919 (patch)
treedf9cb3676c3dcd5f0bcfe507da8441f709ab1d21
parent6e19cd57aab2214eed0c07bd2f244840f212184b (diff)
Resync with FreeBSD/NetBSD. Salient features are that the mailbox command
routines are not necessarily polled now- this should cut down on some of the spurious lost commands that have occurred. Also, we now watchdog each command and make sure that command constipation doesn't occur (which it has been documented to do on the QLA2100 cards).
-rw-r--r--sys/dev/ic/isp.c1337
-rw-r--r--sys/dev/ic/isp_inline.h75
-rw-r--r--sys/dev/ic/isp_openbsd.c193
-rw-r--r--sys/dev/ic/isp_openbsd.h71
-rw-r--r--sys/dev/ic/isp_target.c74
-rw-r--r--sys/dev/ic/isp_target.h11
-rw-r--r--sys/dev/ic/isp_tpublic.h54
-rw-r--r--sys/dev/ic/ispmbox.h5
-rw-r--r--sys/dev/ic/ispreg.h57
-rw-r--r--sys/dev/ic/ispvar.h35
10 files changed, 1071 insertions, 841 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c
index e7daced056f..23e0c6af910 100644
--- a/sys/dev/ic/isp.c
+++ b/sys/dev/ic/isp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp.c,v 1.15 2000/04/06 05:50:43 mjacob Exp $ */
+/* $OpenBSD: isp.c,v 1.16 2000/07/06 05:31:48 mjacob Exp $ */
/*
* Machine and OS Independent (well, as best as possible)
* code for the Qlogic ISP SCSI adapters.
@@ -113,7 +113,7 @@ isp_reset(isp)
struct ispsoftc *isp;
{
mbreg_t mbs;
- int loops, i, dodnld = 1;
+ int loops, i, touched, dodnld = 1;
char *revname;
isp->isp_state = ISP_NILSTATE;
@@ -138,7 +138,7 @@ isp_reset(isp)
* case, we don't really use this yet, but we may in
* the future.
*/
- if (isp->isp_touched == 0) {
+ if ((touched = isp->isp_touched) == 0) {
/*
* Just in case it was paused...
*/
@@ -576,6 +576,8 @@ again:
else
mbs.param[1] = 0x1000;
isp_mboxcmd(isp, &mbs);
+ /* give it a chance to start */
+ SYS_DELAY(500);
if (IS_SCSI(isp)) {
/*
@@ -636,6 +638,46 @@ again:
return;
}
isp->isp_state = ISP_RESETSTATE;
+
+ /*
+ * Okay- now that we have new firmware running, we now (re)set our
+ * notion of how many luns we support. This is somewhat tricky because
+ * if we haven't loaded firmware, we don't have an easy way of telling
+ * how many luns we support.
+ *
+ * We'll make a simplifying assumption- if we loaded firmware, we
+ * are running with expanded lun firmware, otherwise not.
+ *
+ * Expanded lun firmware gives you 32 luns for SCSI cards and
+ * 65536 luns for Fibre Channel cards.
+ *
+ * Because the lun is in a a different position in the Request Queue
+ * Entry structure for Fibre Channel with expanded lun firmware, we
+ * can only support one lun (lun zero) when we don't know what kind
+ * of firmware we're running.
+ *
+ * Note that we only do this once (the first time thru isp_reset)
+ * because we may be called again after firmware has been loaded once
+ * and released.
+ */
+ if (touched == 0) {
+ if (dodnld) {
+ if (IS_SCSI(isp)) {
+ isp->isp_maxluns = 32;
+ } else {
+ isp->isp_maxluns = 65536;
+ }
+ } else {
+ if (IS_SCSI(isp)) {
+ isp->isp_maxluns = 8;
+ } else {
+ PRINTF("%s: WARNING- cannot determine Expanded "
+ "LUN capability- limiting to one LUN\n",
+ isp->isp_name);
+ isp->isp_maxluns = 1;
+ }
+ }
+ }
}
/*
@@ -861,11 +903,11 @@ isp_scsi_channel_init(isp, channel)
* Set current per-target parameters to a safe minimum.
*/
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
- int maxlun, lun;
+ int lun;
u_int16_t sdf;
if (sdp->isp_devparam[tgt].dev_enable == 0) {
- IDPRINTF(1, ("%s: skipping target %d bus %d settings\n",
+ IDPRINTF(2, ("%s: skipping target %d bus %d settings\n",
isp->isp_name, tgt, channel));
continue;
}
@@ -952,13 +994,7 @@ isp_scsi_channel_init(isp, channel)
* seen yet.
*/
sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING;
- if ((ISP_FW_REV(4, 55, 0) <= ISP_FW_REVX(isp->isp_fwrev) &&
- (ISP_FW_REV(5, 0, 0) > ISP_FW_REVX(isp->isp_fwrev))) ||
- (ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(7, 55, 0)))
- maxlun = 32;
- else
- maxlun = 8;
- for (lun = 0; lun < maxlun; lun++) {
+ for (lun = 0; lun < isp->isp_maxluns; lun++) {
mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
mbs.param[1] = (channel << 15) | (tgt << 8) | lun;
mbs.param[2] = sdp->isp_max_queue_depth;
@@ -1025,7 +1061,7 @@ isp_fibre_init(isp)
/*
* We have to use FULL LOGIN even though it resets the loop too much
* because otherwise port database entries don't get updated after
- * a LIP- this is a known f/w bug.
+ * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0.
*/
if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) {
fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
@@ -1079,26 +1115,8 @@ isp_fibre_init(isp)
icbp->icb_logintime = 60; /* 60 second login timeout */
if (fcp->isp_nodewwn) {
- u_int64_t pn;
MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_nodewwn);
- if (fcp->isp_portwwn) {
- pn = fcp->isp_portwwn;
- } else {
- pn = fcp->isp_nodewwn |
- (((u_int64_t)(isp->isp_unit+1)) << 56);
- }
- /*
- * If the top nibble is 2, we can construct a port name
- * from the node name by setting a nonzero instance in
- * bits 56..59. Otherwise, we need to make it identical
- * to Node name...
- */
- if ((fcp->isp_nodewwn >> 60) == 2) {
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pn);
- } else {
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname,
- fcp->isp_nodewwn);
- }
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_portwwn);
} else {
fcp->isp_fwoptions &= ~(ICBOPT_USE_PORTNAME|ICBOPT_FULL_LOGIN);
}
@@ -1253,7 +1271,8 @@ isp_fclink_test(isp, waitdelay)
"Private Loop",
"FL Port",
"N-Port to N-Port",
- "F Port"
+ "F Port",
+ "F Port (no FLOGI_ACC response)"
};
mbreg_t mbs;
int count;
@@ -1300,54 +1319,74 @@ isp_fclink_test(isp, waitdelay)
}
fcp->isp_loopid = mbs.param[1];
if (IS_2200(isp)) {
- count = (int) mbs.param[6];
- if (count < TOPO_NL_PORT || count > TOPO_PTP_STUB)
- count = TOPO_PTP_STUB;
- fcp->isp_topo = count;
+ int topo = (int) mbs.param[6];
+ if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
+ topo = TOPO_PTP_STUB;
+ fcp->isp_topo = topo;
} else {
fcp->isp_topo = TOPO_NL_PORT;
}
-
- /*
- * If we're not on a fabric, the low 8 bits will be our AL_PA.
- * If we're on a fabric, the low 8 bits will still be our AL_PA.
- */
fcp->isp_alpa = mbs.param[2];
+
#if defined(ISP2100_FABRIC)
fcp->isp_onfabric = 0;
- if (isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) {
-
- if (IS_2100(isp))
+ if (fcp->isp_topo != TOPO_N_PORT &&
+ isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) {
+ struct lportdb *lp;
+ if (IS_2100(isp)) {
fcp->isp_topo = TOPO_FL_PORT;
-
+ }
fcp->isp_portid = mbs.param[2] | (((int)mbs.param[3]) << 16);
fcp->isp_onfabric = 1;
- CFGPRINTF("%s: Loop ID %d, AL_PA 0x%x, Port ID 0x%x Loop State "
- "0x%x topology '%s'\n", isp->isp_name, fcp->isp_loopid,
- fcp->isp_alpa, fcp->isp_portid, fcp->isp_loopstate,
- toponames[fcp->isp_topo]);
/*
- * Make sure we're logged out of all fabric devices.
+ * Save the Fabric controller's port database entry.
*/
- for (count = FC_SNS_ID+1; count < MAX_FC_TARG; count++) {
- struct lportdb *lp = &fcp->portdb[count];
- if (lp->valid == 0 || lp->fabdev == 0)
- continue;
- PRINTF("%s: logging out target %d at Loop ID %d "
- "(port id 0x%x)\n", isp->isp_name, count,
- 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);
+ lp = &fcp->portdb[FL_PORT_ID];
+ 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]));
+ 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;
+#if 0
+ if (isp->isp_rfabric == 0) {
+ isp_i_register_fc4_type(isp);
}
+#endif
} else
#endif
- CFGPRINTF("%s: Loop ID %d, ALPA 0x%x Loop State 0x%x topology '%s'\n",
- isp->isp_name, fcp->isp_loopid, fcp->isp_alpa, fcp->isp_loopstate,
+ {
+ fcp->isp_portid = mbs.param[2];
+ fcp->isp_onfabric = 0;
+#if 0
+ isp->isp_rfabric = 0;
+#endif
+ fcp->portdb[FL_PORT_ID].valid = 0;
+ }
+
+ CFGPRINTF("%s: Loop ID %d, AL_PA 0x%x, Port ID 0x%x Loop State "
+ "0x%x topology '%s'\n", isp->isp_name, fcp->isp_loopid,
+ fcp->isp_alpa, fcp->isp_portid, fcp->isp_loopstate,
toponames[fcp->isp_topo]);
+
return (0);
}
@@ -1365,7 +1404,7 @@ isp_same_lportdb(a, b)
*/
if (a->port_wwn == 0 || a->port_wwn != b->port_wwn ||
- a->loopid != b->loopid) {
+ a->loopid != b->loopid || a->roles != b->roles) {
return (0);
} else {
return (1);
@@ -1385,7 +1424,7 @@ isp_pdb_sync(isp, target)
struct lportdb *lp, *tport;
fcparam *fcp = isp->isp_param;
isp_pdb_t pdb;
- int loopid, lim;
+ int loopid, prange, lim;
#ifdef ISP2100_FABRIC
/*
@@ -1400,6 +1439,19 @@ isp_pdb_sync(isp, target)
#endif
+ switch (fcp->isp_topo) {
+ case TOPO_F_PORT:
+ case TOPO_PTP_STUB:
+ prange = 0;
+ break;
+ case TOPO_N_PORT:
+ prange = 2;
+ break;
+ default:
+ prange = FL_PORT_ID;
+ break;
+ }
+
/*
* Run through the local loop ports and get port database info
* for each loop ID.
@@ -1414,12 +1466,17 @@ isp_pdb_sync(isp, target)
* make sure the temp port database is clean...
*/
MEMZERO((void *) tport, sizeof (tport));
- for (lim = loopid = 0; loopid < FL_PORT_ID; loopid++) {
+
+ for (lim = loopid = 0; loopid < prange; loopid++) {
lp = &tport[loopid];
lp->node_wwn = isp_get_portname(isp, loopid, 1);
+ if (fcp->isp_loopstate < LOOP_PDB_RCVD)
+ return (-1);
if (lp->node_wwn == 0)
continue;
lp->port_wwn = isp_get_portname(isp, loopid, 0);
+ if (fcp->isp_loopstate < LOOP_PDB_RCVD)
+ return (-1);
if (lp->port_wwn == 0) {
lp->node_wwn = 0;
continue;
@@ -1429,16 +1486,19 @@ isp_pdb_sync(isp, target)
* Get an entry....
*/
if (isp_getpdb(isp, loopid, &pdb) != 0) {
+ if (fcp->isp_loopstate < LOOP_PDB_RCVD)
+ return (-1);
continue;
}
+ if (fcp->isp_loopstate < LOOP_PDB_RCVD)
+ return (-1);
+
/*
* If the returned database element doesn't match what we
* asked for, restart the process entirely (up to a point...).
*/
if (pdb.pdb_loopid != loopid) {
- IDPRINTF(1, ("%s: wankage (%d != %d)\n",
- isp->isp_name, pdb.pdb_loopid, loopid));
loopid = 0;
if (lim++ < FL_PORT_ID) {
continue;
@@ -1504,7 +1564,7 @@ isp_pdb_sync(isp, target)
* 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 < FL_PORT_ID; loopid++) {
+ for (loopid = 0; loopid < prange; loopid++) {
int i;
/*
@@ -1557,10 +1617,7 @@ isp_pdb_sync(isp, target)
fcp->portdb[i].portid = tport[loopid].portid;
fcp->portdb[i].loopid = loopid;
fcp->portdb[i].valid = 1;
- /*
- * XXX: Should we also propagate roles in case they
- * XXX: changed?
- */
+ fcp->portdb[i].roles = tport[loopid].roles;
/*
* Now make sure this Port WWN doesn't exist elsewhere
@@ -1635,7 +1692,7 @@ isp_pdb_sync(isp, target)
* Now find all previously used targets that are now invalid and
* notify the outer layers that they're gone.
*/
- for (lp = fcp->portdb; lp < &fcp->portdb[FL_PORT_ID]; lp++) {
+ for (lp = fcp->portdb; lp < &fcp->portdb[prange]; lp++) {
if (lp->valid || lp->port_wwn == 0)
continue;
@@ -1651,13 +1708,13 @@ isp_pdb_sync(isp, target)
/*
* Now log in any fabric devices
*/
- for (lim = FC_SNS_ID+1, lp = &fcp->portdb[FC_SNS_ID+1];
+ for (lp = &fcp->portdb[FC_SNS_ID+1];
lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
u_int32_t portid;
mbreg_t mbs;
/*
- * Nothing here?
+ * Anything here?
*/
if (lp->port_wwn == 0)
continue;
@@ -1668,16 +1725,61 @@ isp_pdb_sync(isp, target)
if ((portid = lp->portid) == fcp->isp_portid)
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..
+ */
+ if (lp->loggedin &&
+ isp_getpdb(isp, lp->loopid, &pdb) == 0) {
+ int nrole;
+ u_int64_t nwwnn, nwwpn;
+ nwwnn =
+ (((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]));
+ nwwpn =
+ (((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]));
+ nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >>
+ SVC3_ROLE_SHIFT;
+ if (pdb.pdb_loopid == lp->loopid && lp->portid ==
+ (u_int32_t) BITS2WORD(pdb.pdb_portid_bits) &&
+ nwwnn == lp->node_wwn && nwwpn == lp->port_wwn &&
+ lp->roles == nrole) {
+ lp->loggedin = lp->valid = 1;
+ IDPRINTF(1, ("%s: retained login of Target %d "
+ "(Loop 0x%x) Port ID 0x%x\n",
+ isp->isp_name, (int) (lp - fcp->portdb),
+ (int) lp->loopid, lp->portid));
+ continue;
+ }
+ }
+
/*
* Force a logout if we were logged in.
*/
- if (lp->valid) {
+ if (lp->loggedin) {
mbs.param[0] = MBOX_FABRIC_LOGOUT;
mbs.param[1] = lp->loopid << 8;
mbs.param[2] = 0;
mbs.param[3] = 0;
isp_mboxcmd(isp, &mbs);
- lp->valid = 0;
+ lp->loggedin = 0;
+ IDPRINTF(1, ("%s: Logging out target %d at Loop ID %d "
+ "(port id 0x%x)\n", isp->isp_name,
+ (int) (lp - fcp->portdb), lp->loopid, lp->portid));
}
/*
@@ -1685,16 +1787,15 @@ isp_pdb_sync(isp, target)
*/
loopid = lp - fcp->portdb;
lp->loopid = 0;
- lim = 0;
do {
mbs.param[0] = MBOX_FABRIC_LOGIN;
mbs.param[1] = loopid << 8;
+ mbs.param[2] = portid >> 16;
+ mbs.param[3] = portid & 0xffff;
if (IS_2200(isp)) {
/* only issue a PLOGI if not logged in */
mbs.param[1] |= 0x1;
}
- mbs.param[2] = portid >> 16;
- mbs.param[3] = portid & 0xffff;
isp_mboxcmd(isp, &mbs);
switch (mbs.param[0]) {
case MBOX_LOOP_ID_USED:
@@ -1706,49 +1807,71 @@ isp_pdb_sync(isp, target)
case MBOX_PORT_ID_USED:
/*
* This port is already logged in.
- * Snaffle the loop id it's using.
+ * Snaffle the loop id it's using if it's
+ * nonzero, otherwise we're hosed.
*/
- if ((loopid = mbs.param[1]) == 0) {
- lim = -1;
+ if (mbs.param[1] != 0) {
+ loopid = mbs.param[1];
+ IDPRINTF(1, ("%s: Retaining loopid 0x%x"
+ " for Target %d (port id 0x%x)\n",
+ isp->isp_name, loopid,
+ (int) (lp - fcp->portdb),
+ lp->portid));
+ } else {
+ loopid = MAX_FC_TARG;
+ break;
}
/* FALLTHROUGH */
case MBOX_COMMAND_COMPLETE:
+ lp->loggedin = 1;
lp->loopid = loopid;
- lim = 1;
break;
case MBOX_COMMAND_ERROR:
- PRINTF("%s: command error in PLOGI (0x%x)\n",
- isp->isp_name, mbs.param[1]);
+ PRINTF("%s: command error in PLOGI for port "
+ " 0x%x (0x%x)\n", isp->isp_name, portid,
+ mbs.param[1]);
/* FALLTHROUGH */
case MBOX_ALL_IDS_USED: /* We're outta IDs */
default:
- lim = -1;
+ loopid = MAX_FC_TARG;
break;
}
- } while (lim == 0 && loopid < MAX_FC_TARG);
- if (lim < 0)
+ } while (lp->loopid == 0 && 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 == 0) {
continue;
+ }
- lp->valid = 1;
- lp->fabdev = 1;
+ /*
+ * Make sure we can get the approriate port information.
+ */
if (isp_getpdb(isp, lp->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;
+ PRINTF("%s: could not get PDB for device@port 0x%x\n",
+ isp->isp_name, lp->portid);
+ goto dump_em;
}
+
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;
+ PRINTF("%s: PDB loopid info for device@port 0x%x does "
+ "not match up (0x%x)\n", isp->isp_name, lp->portid,
+ pdb.pdb_loopid);
+ goto dump_em;
}
+
+ if (lp->portid != (u_int32_t) BITS2WORD(pdb.pdb_portid_bits)) {
+ PRINTF("%s: PDB port info for device@port 0x%x does "
+ "not match up (0x%x)\n", isp->isp_name, lp->portid,
+ BITS2WORD(pdb.pdb_portid_bits));
+ goto dump_em;
+ }
+
lp->roles =
(pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT;
- lp->portid = BITS2WORD(pdb.pdb_portid_bits);
lp->node_wwn =
(((u_int64_t)pdb.pdb_nodename[0]) << 56) |
(((u_int64_t)pdb.pdb_nodename[1]) << 48) |
@@ -1771,13 +1894,15 @@ isp_pdb_sync(isp, target)
* 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_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);
+dump_em:
+ lp->valid = 0;
+ PRINTF("%s: Target %d (Loop 0x%x) Port ID 0x%x dumped after "
+ "login\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;
@@ -2011,7 +2136,7 @@ ispscsicmd(xs)
}
if (isp_getrqentry(isp, &iptr, &optr, (void **) &reqp)) {
- IDPRINTF(1, ("%s: Request Queue Overflow\n", isp->isp_name));
+ IDPRINTF(2, ("%s: Request Queue Overflow\n", isp->isp_name));
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
}
@@ -2040,7 +2165,7 @@ ispscsicmd(xs)
ISP_ADD_REQUEST(isp, iptr);
if (isp_getrqentry(isp, &iptr, &optr, (void **)&reqp)) {
- IDPRINTF(1, ("%s: Request Queue Overflow+\n",
+ IDPRINTF(2, ("%s: Request Queue Overflow+\n",
isp->isp_name));
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
@@ -2091,11 +2216,10 @@ ispscsicmd(xs)
reqp->req_lun_trn = XS_LUN(xs);
reqp->req_cdblen = XS_CDBLEN(xs);
} else {
-#ifdef ISP2100_SCCLUN
- t2reqp->req_scclun = XS_LUN(xs);
-#else
- t2reqp->req_lun_trn = XS_LUN(xs);
-#endif
+ if (isp->isp_maxluns > 16)
+ t2reqp->req_scclun = XS_LUN(xs);
+ else
+ t2reqp->req_lun_trn = XS_LUN(xs);
}
MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs));
@@ -2211,6 +2335,7 @@ isp_control(isp, ctl, arg)
case ISPCTL_ABORT_CMD:
xs = (ISP_SCSI_XFER_T *) arg;
+ tgt = XS_TGT(xs);
handle = isp_find_handle(isp, xs);
if (handle == 0) {
PRINTF("%s: isp_control- cannot find command to abort "
@@ -2220,14 +2345,14 @@ isp_control(isp, ctl, arg)
bus = XS_CHANNEL(xs);
mbs.param[0] = MBOX_ABORT;
if (IS_FC(isp)) {
-#ifdef ISP2100_SCCLUN
- mbs.param[1] = XS_TGT(xs) << 8;
- mbs.param[4] = 0;
- mbs.param[5] = 0;
- mbs.param[6] = XS_LUN(xs);
-#else
- mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);
-#endif
+ if (isp->isp_maxluns > 16) {
+ mbs.param[1] = tgt << 8;
+ mbs.param[4] = 0;
+ mbs.param[5] = 0;
+ mbs.param[6] = XS_LUN(xs);
+ } else {
+ mbs.param[1] = tgt << 8 | XS_LUN(xs);
+ }
} else {
mbs.param[1] =
(bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs);
@@ -2235,13 +2360,19 @@ isp_control(isp, ctl, arg)
mbs.param[3] = handle >> 16;
mbs.param[2] = handle & 0xffff;
isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- PRINTF("%s: isp_control MBOX_ABORT failure (code %x)\n",
- isp->isp_name, mbs.param[0]);
+ switch (mbs.param[0]) {
+ case MBOX_COMMAND_COMPLETE:
+ IDPRINTF(1,
+ ("%s: command (handle 0x%x) for %d.%d.%d aborted\n",
+ isp->isp_name, handle, bus, tgt, XS_LUN(xs)));
+ /* FALLTHROUGH */
+ case MBOX_COMMAND_ERROR:
+ break;
+ default:
+ PRINTF("%s: command (handle 0x%x) abort failed (%x)\n",
+ isp->isp_name, handle, mbs.param[0]);
break;
}
- PRINTF("%s: command for target %d lun %d was aborted\n",
- isp->isp_name, XS_TGT(xs), XS_LUN(xs));
return (0);
case ISPCTL_UPDATE_PARAMS:
@@ -2249,10 +2380,16 @@ isp_control(isp, ctl, arg)
return (0);
case ISPCTL_FCLINK_TEST:
- return (isp_fclink_test(isp, FC_FW_READY_DELAY));
+ if (IS_FC(isp)) {
+ return (isp_fclink_test(isp, FC_FW_READY_DELAY));
+ }
+ break;
case ISPCTL_PDB_SYNC:
- return (isp_pdb_sync(isp, -1));
+ if (IS_FC(isp)) {
+ return (isp_pdb_sync(isp, -1));
+ }
+ break;
#ifdef ISP_TARGET_MODE
case ISPCTL_TOGGLE_TMODE:
@@ -2287,42 +2424,74 @@ isp_intr(arg)
{
ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs;
struct ispsoftc *isp = arg;
- u_int16_t iptr, optr;
- u_int16_t isr, isrb, sema;
+ u_int16_t iptr, optr, isr, sema, junk;
int i, nlooked = 0, ndone = 0;
- /*
- * Well, if we've disabled interrupts, we may get a case where
- * isr isn't set, but sema is. In any case, debounce isr reads.
- */
- do {
+ if (IS_2100(isp)) {
+ i = 0;
+ do {
+ isr = ISP_READ(isp, BIU_ISR);
+ junk = ISP_READ(isp, BIU_ISR);
+ } while (isr != junk && ++i < 1000);
+ if (isr != junk) {
+ PRINTF("%s: isr unsteady (%x, %x)\n",
+ isp->isp_name, isr, junk);
+ }
+ i = 0;
+ do {
+ sema = ISP_READ(isp, BIU_SEMA);
+ junk = ISP_READ(isp, BIU_SEMA);
+ } while (sema != junk && ++i < 1000);
+ if (sema != junk) {
+ PRINTF("%s: sema unsteady (%x, %x)\n",
+ isp->isp_name, sema, junk);
+ }
+ } else {
isr = ISP_READ(isp, BIU_ISR);
- isrb = ISP_READ(isp, BIU_ISR);
- } while (isr != isrb);
- sema = ISP_READ(isp, BIU_SEMA) & 0x1;
- IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema));
- if (isr == 0) {
- return (0);
+ sema = ISP_READ(isp, BIU_SEMA);
}
- if (!INT_PENDING(isp, isr)) {
- IDPRINTF(4, ("%s: isp_intr isr=%x\n", isp->isp_name, isr));
+ IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema));
+ isr &= INT_PENDING_MASK(isp);
+ sema &= BIU_SEMA_LOCK;
+ if (isr == 0 && sema == 0) {
return (0);
}
- if (isp->isp_state != ISP_RUNSTATE) {
- IDPRINTF(3, ("%s: interrupt (isr=%x,sema=%x) when not ready\n",
- isp->isp_name, isr, sema));
- ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5));
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- ISP_WRITE(isp, BIU_SEMA, 0);
- ENABLE_INTS(isp);
- return (1);
- }
if (sema) {
- u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);
+ u_int16_t mbox;
+
+ if (IS_2100(isp)) {
+ i = 0;
+ do {
+ mbox = ISP_READ(isp, OUTMAILBOX0);
+ junk = ISP_READ(isp, OUTMAILBOX0);;
+ } while (junk != mbox && ++i < 1000);
+ if (mbox != junk) {
+ PRINTF("%s: mailbox0 unsteady (%x, %x)\n",
+ isp->isp_name, mbox, junk);
+ ISP_WRITE(isp, BIU_SEMA, 0);
+ ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
+ return (1);
+ }
+ } else {
+ mbox = ISP_READ(isp, OUTMAILBOX0);
+ }
if (mbox & 0x4000) {
- IDPRINTF(4, ("%s: Command Mbox 0x%x\n",
- isp->isp_name, mbox));
+ int obits, i = 0;
+ if ((obits = isp->isp_mboxbsy) != 0) {
+ isp->isp_mboxtmp[i++] = mbox;
+ for (i = 1; i < 8; i++) {
+ if ((obits & (1 << i)) == 0) {
+ continue;
+ }
+ isp->isp_mboxtmp[i] =
+ ISP_READ(isp, MBOX_OFF(i));
+ }
+ MBOX_NOTIFY_COMPLETE(isp);
+ } else {
+ PRINTF("%s: Command Mbox 0x%x\n",
+ isp->isp_name, mbox);
+ }
} else {
u_int32_t fhandle = isp_parse_async(isp, (int) mbox);
IDPRINTF(4, ("%s: Async Mbox 0x%x\n",
@@ -2331,9 +2500,22 @@ isp_intr(arg)
isp_fastpost_complete(isp, fhandle);
}
}
- ISP_WRITE(isp, BIU_SEMA, 0);
+ if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) {
+ ISP_WRITE(isp, BIU_SEMA, 0);
+ ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
+ return (1);
+ }
+ }
+
+ /*
+ * We can't be getting this now.
+ */
+ if (isp->isp_state != ISP_RUNSTATE) {
+ PRINTF("%s: interrupt (isr=%x, sema=%x) when not ready\n",
+ isp->isp_name, isr, sema);
+ ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5));
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- ENABLE_INTS(isp);
+ ISP_WRITE(isp, BIU_SEMA, 0);
return (1);
}
@@ -2341,11 +2523,41 @@ isp_intr(arg)
* You *must* read OUTMAILBOX5 prior to clearing the RISC interrupt.
*/
optr = isp->isp_residx;
- iptr = ISP_READ(isp, OUTMAILBOX5);
+
+ if (IS_2100(isp)) {
+ i = 0;
+ do {
+ iptr = ISP_READ(isp, OUTMAILBOX5);
+ junk = ISP_READ(isp, OUTMAILBOX5);
+ } while (junk != iptr && ++i < 1000);
+
+ if (iptr != junk) {
+ ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
+ PRINTF("%s: mailbox5 unsteady (%x, %x)\n",
+ isp->isp_name, iptr, junk);
+ return (1);
+ }
+ } else {
+ iptr = ISP_READ(isp, OUTMAILBOX5);
+ }
+
+ if (sema) {
+ ISP_WRITE(isp, BIU_SEMA, 0);
+ }
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- if (optr == iptr) {
- IDPRINTF(4, ("why intr? isr %x iptr %x optr %x\n",
- isr, optr, iptr));
+
+ if (optr == iptr && sema == 0) {
+ /*
+ * There are a lot of these- reasons unknown- mostly on
+ * faster Alpha machines.
+ *
+ * I tried delaying after writing HCCR_CMD_CLEAR_RISC_INT to
+ * make sure the old interrupt went away (to avoid 'ringing'
+ * effects), but that didn't stop this from occurring.
+ */
+ junk = ISP_READ(isp, BIU_ISR);
+ IDPRINTF(2, ("%s: null intr- isr %x (%x) iptr %x optr %x\n",
+ isp->isp_name, isr, junk, iptr, optr));
}
while (optr != iptr) {
@@ -2460,8 +2672,9 @@ isp_intr(arg)
XS_SNS_IS_VALID(xs);
sp->req_state_flags |= RQSF_GOT_SENSE;
} else if (XS_STS(xs) == SCSI_CHECK) {
- IDPRINTF(1, ("%s: check condition with no sense"
- " data\n", isp->isp_name));
+ IDPRINTF(2,
+ ("%s: check condition with no sense data\n",
+ isp->isp_name));
}
}
if (XS_NOERR(xs) && XS_STS(xs) == SCSI_BUSY) {
@@ -2503,24 +2716,6 @@ isp_intr(arg)
if (XS_XFRLEN(xs)) {
ISP_DMAFREE(isp, xs, sp->req_handle);
}
- /*
- * Let the platforms cope.
- */
-#if 0
- /*
- * XXX: If we have a check condition, but no Sense Data,
- * XXX: mark it as an error (ARQ failed). We need to
- * XXX: to do a more distinct job because there may
- * XXX: cases where ARQ is disabled.
- */
- if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) {
- if (XS_NOERR(xs)) {
- PRINTF("%s: ARQ failure for target %d lun %d\n",
- isp->isp_name, XS_TGT(xs), XS_LUN(xs));
- XS_SETERR(xs, HBA_ARQFAIL);
- }
- }
-#endif
if ((isp->isp_dblev >= 5) ||
(isp->isp_dblev > 2 && !XS_NOERR(xs))) {
PRINTF("%s(%d.%d): FIN dl%d resid%d STS %x",
@@ -2549,6 +2744,7 @@ isp_intr(arg)
ISP_WRITE(isp, INMAILBOX5, optr);
isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
}
+
isp->isp_residx = optr;
for (i = 0; i < ndone; i++) {
xs = complist[i];
@@ -2556,7 +2752,6 @@ isp_intr(arg)
XS_CMD_DONE(xs);
}
}
- ENABLE_INTS(isp);
return (1);
}
@@ -2746,7 +2941,7 @@ isp_parse_async(isp, mbox)
isp->isp_sendmarker = 1;
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
isp_mark_getpdb_all(isp);
- IDPRINTF(2, ("%s: Port Database Changed\n", isp->isp_name));
+ IDPRINTF(1, ("%s: Port Database Changed\n", isp->isp_name));
break;
case ASYNC_CHANGE_NOTIFY:
@@ -2759,6 +2954,17 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_PTPMODE:
+ if (((fcparam *) isp->isp_param)->isp_onfabric)
+ ((fcparam *) isp->isp_param)->isp_topo = TOPO_N_PORT;
+ else
+ ((fcparam *) isp->isp_param)->isp_topo = TOPO_F_PORT;
+ isp_mark_getpdb_all(isp);
+ isp->isp_sendmarker = 1;
+ ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
+ ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
+#ifdef ISP_TARGET_MODE
+ isp_target_async(isp, bus, mbox);
+#endif
PRINTF("%s: Point-to-Point mode\n", isp->isp_name);
break;
@@ -3013,7 +3219,7 @@ isp_parse_status(isp, sp, xs)
case RQCS_ARQS_FAILED:
PRINTF("%s: Auto Request Sense failed for %d.%d.%d\n",
- isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
+ isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
return;
case RQCS_WIDE_FAILED:
@@ -3117,309 +3323,279 @@ isp_fastpost_complete(isp, fph)
isp->isp_nactive--;
}
-#define HINIB(x) ((x) >> 0x4)
-#define LONIB(x) ((x) & 0xf)
-#define MAKNIB(a, b) (((a) << 4) | (b))
-static u_int8_t mbpcnt[] = {
- MAKNIB(1, 1), /* 0x00: MBOX_NO_OP */
- MAKNIB(5, 5), /* 0x01: MBOX_LOAD_RAM */
- MAKNIB(2, 0), /* 0x02: MBOX_EXEC_FIRMWARE */
- MAKNIB(5, 5), /* 0x03: MBOX_DUMP_RAM */
- MAKNIB(3, 3), /* 0x04: MBOX_WRITE_RAM_WORD */
- MAKNIB(2, 3), /* 0x05: MBOX_READ_RAM_WORD */
- MAKNIB(6, 6), /* 0x06: MBOX_MAILBOX_REG_TEST */
- MAKNIB(2, 3), /* 0x07: MBOX_VERIFY_CHECKSUM */
- MAKNIB(1, 4), /* 0x08: MBOX_ABOUT_FIRMWARE */
- MAKNIB(0, 0), /* 0x09: */
- MAKNIB(0, 0), /* 0x0a: */
- MAKNIB(0, 0), /* 0x0b: */
- MAKNIB(0, 0), /* 0x0c: */
- MAKNIB(0, 0), /* 0x0d: */
- MAKNIB(1, 2), /* 0x0e: MBOX_CHECK_FIRMWARE */
- MAKNIB(0, 0), /* 0x0f: */
- MAKNIB(5, 5), /* 0x10: MBOX_INIT_REQ_QUEUE */
- MAKNIB(6, 6), /* 0x11: MBOX_INIT_RES_QUEUE */
- MAKNIB(4, 4), /* 0x12: MBOX_EXECUTE_IOCB */
- MAKNIB(2, 2), /* 0x13: MBOX_WAKE_UP */
- MAKNIB(1, 6), /* 0x14: MBOX_STOP_FIRMWARE */
- MAKNIB(4, 4), /* 0x15: MBOX_ABORT */
- MAKNIB(2, 2), /* 0x16: MBOX_ABORT_DEVICE */
- MAKNIB(3, 3), /* 0x17: MBOX_ABORT_TARGET */
- MAKNIB(3, 1), /* 0x18: MBOX_BUS_RESET */
- MAKNIB(2, 3), /* 0x19: MBOX_STOP_QUEUE */
- MAKNIB(2, 3), /* 0x1a: MBOX_START_QUEUE */
- MAKNIB(2, 3), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
- MAKNIB(2, 3), /* 0x1c: MBOX_ABORT_QUEUE */
- MAKNIB(2, 4), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
- MAKNIB(0, 0), /* 0x1e: */
- MAKNIB(1, 3), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
- MAKNIB(1, 4), /* 0x20: MBOX_GET_INIT_SCSI_ID, MBOX_GET_LOOP_ID */
- MAKNIB(1, 3), /* 0x21: MBOX_GET_SELECT_TIMEOUT */
- MAKNIB(1, 3), /* 0x22: MBOX_GET_RETRY_COUNT */
- MAKNIB(1, 2), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */
- MAKNIB(1, 2), /* 0x24: MBOX_GET_CLOCK_RATE */
- MAKNIB(1, 2), /* 0x25: MBOX_GET_ACT_NEG_STATE */
- MAKNIB(1, 2), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */
- MAKNIB(1, 3), /* 0x27: MBOX_GET_PCI_PARAMS */
- MAKNIB(2, 4), /* 0x28: MBOX_GET_TARGET_PARAMS */
- MAKNIB(2, 4), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */
- MAKNIB(1, 2), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */
- MAKNIB(0, 0), /* 0x2b: */
- MAKNIB(0, 0), /* 0x2c: */
- MAKNIB(0, 0), /* 0x2d: */
- MAKNIB(0, 0), /* 0x2e: */
- MAKNIB(0, 0), /* 0x2f: */
- MAKNIB(2, 2), /* 0x30: MBOX_SET_INIT_SCSI_ID */
- MAKNIB(2, 3), /* 0x31: MBOX_SET_SELECT_TIMEOUT */
- MAKNIB(3, 3), /* 0x32: MBOX_SET_RETRY_COUNT */
- MAKNIB(2, 2), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */
- MAKNIB(2, 2), /* 0x34: MBOX_SET_CLOCK_RATE */
- MAKNIB(2, 2), /* 0x35: MBOX_SET_ACT_NEG_STATE */
- MAKNIB(2, 2), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */
- MAKNIB(3, 3), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */
- MAKNIB(4, 4), /* 0x38: MBOX_SET_TARGET_PARAMS */
- MAKNIB(4, 4), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */
- MAKNIB(1, 2), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */
- MAKNIB(0, 0), /* 0x3b: */
- MAKNIB(0, 0), /* 0x3c: */
- MAKNIB(0, 0), /* 0x3d: */
- MAKNIB(0, 0), /* 0x3e: */
- MAKNIB(0, 0), /* 0x3f: */
- MAKNIB(1, 2), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */
- MAKNIB(6, 1), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */
- MAKNIB(2, 3), /* 0x42: MBOX_EXEC_BIOS_IOCB */
- MAKNIB(0, 0), /* 0x43: */
- MAKNIB(0, 0), /* 0x44: */
- MAKNIB(0, 0), /* 0x45: */
- MAKNIB(0, 0), /* 0x46: */
- MAKNIB(0, 0), /* 0x47: */
- MAKNIB(0, 0), /* 0x48: */
- MAKNIB(0, 0), /* 0x49: */
- MAKNIB(2, 1), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */
- MAKNIB(1, 2), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */
- MAKNIB(0, 0), /* 0x4c: */
- MAKNIB(0, 0), /* 0x4d: */
- MAKNIB(0, 0), /* 0x4e: */
- MAKNIB(0, 0), /* 0x4f: */
- MAKNIB(0, 0), /* 0x50: */
- MAKNIB(0, 0), /* 0x51: */
- MAKNIB(0, 0), /* 0x52: */
- MAKNIB(0, 0), /* 0x53: */
- MAKNIB(8, 0), /* 0x54: MBOX_EXEC_COMMAND_IOCB_A64 */
- MAKNIB(2, 1), /* 0x55: MBOX_ENABLE_TARGET_MODE */
- MAKNIB(0, 0), /* 0x56: */
- MAKNIB(0, 0), /* 0x57: */
- MAKNIB(0, 0), /* 0x58: */
- MAKNIB(0, 0), /* 0x59: */
- MAKNIB(0, 0), /* 0x5a: */
- MAKNIB(0, 0), /* 0x5b: */
- MAKNIB(0, 0), /* 0x5c: */
- MAKNIB(0, 0), /* 0x5d: */
- MAKNIB(0, 0), /* 0x5e: */
- MAKNIB(0, 0), /* 0x5f: */
- MAKNIB(8, 6), /* 0x60: MBOX_INIT_FIRMWARE */
- MAKNIB(0, 0), /* 0x61: */
- MAKNIB(2, 1), /* 0x62: MBOX_INIT_LIP */
- MAKNIB(8, 1), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
- MAKNIB(8, 1), /* 0x64: MBOX_GET_PORT_DB */
- MAKNIB(3, 1), /* 0x65: MBOX_CLEAR_ACA */
- MAKNIB(3, 1), /* 0x66: MBOX_TARGET_RESET */
- MAKNIB(3, 1), /* 0x67: MBOX_CLEAR_TASK_SET */
- MAKNIB(3, 1), /* 0x68: MBOX_ABORT_TASK_SET */
- MAKNIB(1, 2), /* 0x69: MBOX_GET_FW_STATE */
- MAKNIB(2, 8), /* 0x6a: MBOX_GET_PORT_NAME */
- MAKNIB(8, 1), /* 0x6b: MBOX_GET_LINK_STATUS */
- MAKNIB(4, 4), /* 0x6c: MBOX_INIT_LIP_RESET */
- MAKNIB(0, 0), /* 0x6d: */
- 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 */
- MAKNIB(4, 1) /* 0x72: MBOX_INIT_LIP_LOGIN */
+#define HIBYT(x) ((x) >> 0x8)
+#define LOBYT(x) ((x) & 0xff)
+#define ISPOPMAP(a, b) (((a) << 8) | (b))
+static u_int16_t mbpscsi[] = {
+ ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
+ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
+ ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
+ ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */
+ ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
+ ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
+ ISPOPMAP(0x3f, 0x3f), /* 0x06: MBOX_MAILBOX_REG_TEST */
+ ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
+ ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */
+ ISPOPMAP(0x00, 0x00), /* 0x09: */
+ ISPOPMAP(0x00, 0x00), /* 0x0a: */
+ ISPOPMAP(0x00, 0x00), /* 0x0b: */
+ ISPOPMAP(0x00, 0x00), /* 0x0c: */
+ ISPOPMAP(0x00, 0x00), /* 0x0d: */
+ ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
+ ISPOPMAP(0x00, 0x00), /* 0x0f: */
+ ISPOPMAP(0x1f, 0x1f), /* 0x10: MBOX_INIT_REQ_QUEUE */
+ ISPOPMAP(0x3f, 0x3f), /* 0x11: MBOX_INIT_RES_QUEUE */
+ ISPOPMAP(0x0f, 0x0f), /* 0x12: MBOX_EXECUTE_IOCB */
+ ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
+ ISPOPMAP(0x01, 0x3f), /* 0x14: MBOX_STOP_FIRMWARE */
+ ISPOPMAP(0x0f, 0x0f), /* 0x15: MBOX_ABORT */
+ ISPOPMAP(0x03, 0x03), /* 0x16: MBOX_ABORT_DEVICE */
+ ISPOPMAP(0x07, 0x07), /* 0x17: MBOX_ABORT_TARGET */
+ ISPOPMAP(0x07, 0x07), /* 0x18: MBOX_BUS_RESET */
+ ISPOPMAP(0x03, 0x07), /* 0x19: MBOX_STOP_QUEUE */
+ ISPOPMAP(0x03, 0x07), /* 0x1a: MBOX_START_QUEUE */
+ ISPOPMAP(0x03, 0x07), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
+ ISPOPMAP(0x03, 0x07), /* 0x1c: MBOX_ABORT_QUEUE */
+ ISPOPMAP(0x03, 0x4f), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
+ ISPOPMAP(0x00, 0x00), /* 0x1e: */
+ ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
+ ISPOPMAP(0x01, 0x07), /* 0x20: MBOX_GET_INIT_SCSI_ID */
+ ISPOPMAP(0x01, 0x07), /* 0x21: MBOX_GET_SELECT_TIMEOUT */
+ ISPOPMAP(0x01, 0xc7), /* 0x22: MBOX_GET_RETRY_COUNT */
+ ISPOPMAP(0x01, 0x07), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */
+ ISPOPMAP(0x01, 0x03), /* 0x24: MBOX_GET_CLOCK_RATE */
+ ISPOPMAP(0x01, 0x07), /* 0x25: MBOX_GET_ACT_NEG_STATE */
+ ISPOPMAP(0x01, 0x07), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */
+ ISPOPMAP(0x01, 0x07), /* 0x27: MBOX_GET_PCI_PARAMS */
+ ISPOPMAP(0x03, 0x4f), /* 0x28: MBOX_GET_TARGET_PARAMS */
+ ISPOPMAP(0x03, 0x0f), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */
+ ISPOPMAP(0x01, 0x07), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */
+ ISPOPMAP(0x00, 0x00), /* 0x2b: */
+ ISPOPMAP(0x00, 0x00), /* 0x2c: */
+ ISPOPMAP(0x00, 0x00), /* 0x2d: */
+ ISPOPMAP(0x00, 0x00), /* 0x2e: */
+ ISPOPMAP(0x00, 0x00), /* 0x2f: */
+ ISPOPMAP(0x03, 0x03), /* 0x30: MBOX_SET_INIT_SCSI_ID */
+ ISPOPMAP(0x07, 0x07), /* 0x31: MBOX_SET_SELECT_TIMEOUT */
+ ISPOPMAP(0xc7, 0xc7), /* 0x32: MBOX_SET_RETRY_COUNT */
+ ISPOPMAP(0x07, 0x07), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */
+ ISPOPMAP(0x03, 0x03), /* 0x34: MBOX_SET_CLOCK_RATE */
+ ISPOPMAP(0x07, 0x07), /* 0x35: MBOX_SET_ACT_NEG_STATE */
+ ISPOPMAP(0x07, 0x07), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */
+ ISPOPMAP(0x07, 0x07), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */
+ ISPOPMAP(0x4f, 0x4f), /* 0x38: MBOX_SET_TARGET_PARAMS */
+ ISPOPMAP(0x0f, 0x0f), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */
+ ISPOPMAP(0x07, 0x07), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */
+ ISPOPMAP(0x00, 0x00), /* 0x3b: */
+ ISPOPMAP(0x00, 0x00), /* 0x3c: */
+ ISPOPMAP(0x00, 0x00), /* 0x3d: */
+ ISPOPMAP(0x00, 0x00), /* 0x3e: */
+ ISPOPMAP(0x00, 0x00), /* 0x3f: */
+ ISPOPMAP(0x01, 0x03), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */
+ ISPOPMAP(0x3f, 0x01), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */
+ ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_EXEC_BIOS_IOCB */
+ ISPOPMAP(0x00, 0x00), /* 0x43: */
+ ISPOPMAP(0x00, 0x00), /* 0x44: */
+ ISPOPMAP(0x03, 0x03), /* 0x45: SET SYSTEM PARAMETER */
+ ISPOPMAP(0x01, 0x03), /* 0x46: GET SYSTEM PARAMETER */
+ ISPOPMAP(0x00, 0x00), /* 0x47: */
+ ISPOPMAP(0x01, 0xcf), /* 0x48: GET SCAM CONFIGURATION */
+ ISPOPMAP(0xcf, 0xcf), /* 0x49: SET SCAM CONFIGURATION */
+ ISPOPMAP(0x03, 0x03), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */
+ ISPOPMAP(0x01, 0x03), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */
+ ISPOPMAP(0x00, 0x00), /* 0x4c: */
+ ISPOPMAP(0x00, 0x00), /* 0x4d: */
+ ISPOPMAP(0x00, 0x00), /* 0x4e: */
+ ISPOPMAP(0x00, 0x00), /* 0x4f: */
+ ISPOPMAP(0xdf, 0xdf), /* 0x50: LOAD RAM A64 */
+ ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */
+ ISPOPMAP(0xdf, 0xdf), /* 0x52: INITIALIZE REQUEST QUEUE A64 */
+ ISPOPMAP(0xff, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */
+ ISPOPMAP(0xcf, 0xff), /* 0x54: EXECUTE IOCB A64 */
+ ISPOPMAP(0x03, 0x01), /* 0x55: ENABLE TARGET MODE */
+ ISPOPMAP(0x00, 0x00), /* 0x56: */
+ ISPOPMAP(0x00, 0x00), /* 0x57: */
+ ISPOPMAP(0x00, 0x00), /* 0x58: */
+ ISPOPMAP(0x00, 0x00), /* 0x59: */
+ ISPOPMAP(0x03, 0x03), /* 0x5a: SET DATA OVERRUN RECOVERY MODE */
+ ISPOPMAP(0x01, 0x03), /* 0x5b: GET DATA OVERRUN RECOVERY MODE */
+ ISPOPMAP(0x0f, 0x0f), /* 0x5c: SET HOST DATA */
+ ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */
+};
+
+static u_int16_t mbpfc[] = {
+ ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
+ ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
+ ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
+ ISPOPMAP(0x1f, 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(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */
+ ISPOPMAP(0xdf, 0x01), /* 0x09: LOAD RAM */
+ ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
+ ISPOPMAP(0x00, 0x00), /* 0x0b: */
+ ISPOPMAP(0x00, 0x00), /* 0x0c: */
+ ISPOPMAP(0x00, 0x00), /* 0x0d: */
+ ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */
+ ISPOPMAP(0x00, 0x00), /* 0x0f: */
+ ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */
+ ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */
+ ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */
+ ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */
+ ISPOPMAP(0x01, 0xff), /* 0x14: MBOX_STOP_FIRMWARE */
+ ISPOPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */
+ ISPOPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */
+ ISPOPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */
+ ISPOPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */
+ ISPOPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */
+ ISPOPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */
+ ISPOPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */
+ ISPOPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */
+ ISPOPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
+ ISPOPMAP(0x00, 0x00), /* 0x1e: */
+ ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */
+ ISPOPMAP(0x01, 0x4f), /* 0x20: MBOX_GET_LOOP_ID */
+ ISPOPMAP(0x00, 0x00), /* 0x21: */
+ ISPOPMAP(0x01, 0x07), /* 0x22: MBOX_GET_RETRY_COUNT */
+ ISPOPMAP(0x00, 0x00), /* 0x23: */
+ ISPOPMAP(0x00, 0x00), /* 0x24: */
+ ISPOPMAP(0x00, 0x00), /* 0x25: */
+ ISPOPMAP(0x00, 0x00), /* 0x26: */
+ ISPOPMAP(0x00, 0x00), /* 0x27: */
+ ISPOPMAP(0x0f, 0x1), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
+ ISPOPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
+ ISPOPMAP(0x00, 0x00), /* 0x2a: */
+ ISPOPMAP(0x00, 0x00), /* 0x2b: */
+ ISPOPMAP(0x00, 0x00), /* 0x2c: */
+ ISPOPMAP(0x00, 0x00), /* 0x2d: */
+ ISPOPMAP(0x00, 0x00), /* 0x2e: */
+ ISPOPMAP(0x00, 0x00), /* 0x2f: */
+ ISPOPMAP(0x00, 0x00), /* 0x30: */
+ ISPOPMAP(0x00, 0x00), /* 0x31: */
+ ISPOPMAP(0x07, 0x07), /* 0x32: MBOX_SET_RETRY_COUNT */
+ ISPOPMAP(0x00, 0x00), /* 0x33: */
+ ISPOPMAP(0x00, 0x00), /* 0x34: */
+ ISPOPMAP(0x00, 0x00), /* 0x35: */
+ ISPOPMAP(0x00, 0x00), /* 0x36: */
+ ISPOPMAP(0x00, 0x00), /* 0x37: */
+ ISPOPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
+ ISPOPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
+ ISPOPMAP(0x00, 0x00), /* 0x3a: */
+ ISPOPMAP(0x00, 0x00), /* 0x3b: */
+ ISPOPMAP(0x00, 0x00), /* 0x3c: */
+ ISPOPMAP(0x00, 0x00), /* 0x3d: */
+ ISPOPMAP(0x00, 0x00), /* 0x3e: */
+ 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(0x00, 0x00), /* 0x44: */
+ ISPOPMAP(0x00, 0x00), /* 0x45: */
+ ISPOPMAP(0x00, 0x00), /* 0x46: */
+ ISPOPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
+ ISPOPMAP(0x00, 0x00), /* 0x48: */
+ ISPOPMAP(0x00, 0x00), /* 0x49: */
+ ISPOPMAP(0x00, 0x00), /* 0x4a: */
+ ISPOPMAP(0x00, 0x00), /* 0x4b: */
+ ISPOPMAP(0x00, 0x00), /* 0x4c: */
+ ISPOPMAP(0x00, 0x00), /* 0x4d: */
+ ISPOPMAP(0x00, 0x00), /* 0x4e: */
+ ISPOPMAP(0x00, 0x00), /* 0x4f: */
+ ISPOPMAP(0x00, 0x00), /* 0x50: */
+ ISPOPMAP(0x00, 0x00), /* 0x51: */
+ ISPOPMAP(0x00, 0x00), /* 0x52: */
+ ISPOPMAP(0x00, 0x00), /* 0x53: */
+ ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
+ ISPOPMAP(0x00, 0x00), /* 0x55: */
+ ISPOPMAP(0x00, 0x00), /* 0x56: */
+ ISPOPMAP(0x00, 0x00), /* 0x57: */
+ ISPOPMAP(0x00, 0x00), /* 0x58: */
+ ISPOPMAP(0x00, 0x00), /* 0x59: */
+ ISPOPMAP(0x00, 0x00), /* 0x5a: */
+ ISPOPMAP(0x00, 0x00), /* 0x5b: */
+ ISPOPMAP(0x00, 0x00), /* 0x5c: */
+ ISPOPMAP(0x00, 0x00), /* 0x5d: */
+ ISPOPMAP(0x00, 0x00), /* 0x5e: */
+ ISPOPMAP(0x00, 0x00), /* 0x5f: */
+ ISPOPMAP(0xfd, 0x31), /* 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 */
+ ISPOPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
+ ISPOPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */
+ ISPOPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */
+ ISPOPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */
+ ISPOPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */
+ ISPOPMAP(0x01, 0x07), /* 0x69: MBOX_GET_FW_STATE */
+ ISPOPMAP(0x03, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */
+ ISPOPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */
+ ISPOPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */
+ ISPOPMAP(0x00, 0x00), /* 0x6d: */
+ ISPOPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */
+ ISPOPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */
+ ISPOPMAP(0x03, 0x01), /* 0x70: MBOX_SEND_CHANGE_REQUEST */
+ ISPOPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */
+ ISPOPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */
+ ISPOPMAP(0x00, 0x00), /* 0x73: */
+ ISPOPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */
+ ISPOPMAP(0xcf, 0x03), /* 0x75: GET PORT/NODE NAME LIST */
+ ISPOPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */
+ ISPOPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */
+ ISPOPMAP(0x00, 0x00), /* 0x78: */
+ ISPOPMAP(0x00, 0x00), /* 0x79: */
+ ISPOPMAP(0x00, 0x00), /* 0x7a: */
+ ISPOPMAP(0x00, 0x00), /* 0x7b: */
+ ISPOPMAP(0x4f, 0x03), /* 0x7c: Get ID List */
+ ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */
+ ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */
};
-#define NMBCOM (sizeof (mbpcnt) / sizeof (mbpcnt[0]))
static void
isp_mboxcmd(isp, mbp)
struct ispsoftc *isp;
mbreg_t *mbp;
{
- int outparam, inparam;
- int loops, dld = 0;
- u_int8_t opcode;
-
- if (mbp->param[0] == ISP2100_SET_PCI_PARAM) {
- opcode = mbp->param[0] = MBOX_SET_PCI_PARAMETERS;
- inparam = 4;
- outparam = 4;
- goto command_known;
- } else if (mbp->param[0] > NMBCOM) {
- PRINTF("%s: bad command %x\n", isp->isp_name, mbp->param[0]);
- return;
- }
-
- opcode = mbp->param[0];
- inparam = HINIB(mbpcnt[mbp->param[0]]);
- outparam = LONIB(mbpcnt[mbp->param[0]]);
+ unsigned int lim, ibits, obits, box, opcode;
+ u_int16_t *mcp;
- if (inparam == 0 && outparam == 0) {
- PRINTF("%s: no parameters for %x\n", isp->isp_name,
- mbp->param[0]);
- return;
- }
-
-
- /*
- * Check for variants
- */
-#ifdef ISP2100_SCCLUN
if (IS_FC(isp)) {
- switch (mbp->param[0]) {
- case MBOX_ABORT:
- inparam = 7;
- break;
- case MBOX_ABORT_DEVICE:
- case MBOX_START_QUEUE:
- case MBOX_STOP_QUEUE:
- case MBOX_SINGLE_STEP_QUEUE:
- case MBOX_ABORT_QUEUE:
- case MBOX_GET_DEV_QUEUE_STATUS:
- inparam = 3;
- break;
- case MBOX_BUS_RESET:
- inparam = 2;
- break;
- default:
- break;
- }
+ mcp = mbpfc;
+ lim = (sizeof (mbpfc) / sizeof (mbpfc[0]));
+ } else {
+ mcp = mbpscsi;
+ lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0]));
}
-#endif
-
-command_known:
-
- /*
- * Set semaphore on mailbox registers to win any races to acquire them.
- */
- ISP_WRITE(isp, BIU_SEMA, 1);
- /*
- * Qlogic Errata for the ISP2100 says that there is a necessary
- * debounce between between writing the semaphore register
- * and reading a mailbox register. I believe we're okay here.
- */
+ if ((opcode = mbp->param[0]) >= lim) {
+ mbp->param[0] = MBOX_INVALID_COMMAND;
+ PRINTF("%s: unknown command 0x%x\n", isp->isp_name, opcode);
+ return;
+ }
- /*
- * Make sure we can send some words.
- * Check to see if there's an async mbox event pending.
- */
+ ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp);
+ obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp);
- loops = MBOX_DELAY_COUNT;
- while ((ISP_READ(isp, HCCR) & HCCR_HOST_INT) != 0) {
- if (ISP_READ(isp, BIU_SEMA) & 1) {
- int fph;
- u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);
- /*
- * We have a pending MBOX async event.
- */
- if (mbox & 0x8000) {
- fph = isp_parse_async(isp, (int) mbox);
- IDPRINTF(5, ("%s: line %d, fph %d\n",
- isp->isp_name, __LINE__, fph));
- ISP_WRITE(isp, BIU_SEMA, 0);
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- if (fph < 0) {
- return;
- } else if (fph > 0) {
- isp_fastpost_complete(isp, fph);
- }
- SYS_DELAY(100);
- goto command_known;
- }
- /*
- * We have a pending MBOX completion? Might be
- * from a previous command. We can't (sometimes)
- * just clear HOST INTERRUPT, so we'll just silently
- * eat this here.
- */
- if (mbox & 0x4000) {
- IDPRINTF(5, ("%s: line %d, mbox 0x%x\n",
- isp->isp_name, __LINE__, mbox));
- ISP_WRITE(isp, BIU_SEMA, 0);
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- SYS_DELAY(100);
- goto command_known;
- }
- }
- SYS_DELAY(100);
- if (--loops < 0) {
- if (dld++ > 10) {
- PRINTF("%s: isp_mboxcmd could not get command "
- "started\n", isp->isp_name);
- return;
- }
- ISP_WRITE(isp, BIU_SEMA, 0);
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- goto command_known;
- }
+ if (ibits == 0 && obits == 0) {
+ mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
+ PRINTF("%s: no parameters for opcode 0x%x\n", isp->isp_name,
+ opcode);
+ return;
}
- /*
- * Write input parameters.
- *
- * Special case some of the setups for the dual port SCSI cards.
- * XXX Eventually will be fixed by converting register write/read
- * XXX counts to bitmasks.
- */
- if (IS_DUALBUS(isp)) {
- switch (opcode) {
- case MBOX_GET_RETRY_COUNT:
- case MBOX_SET_RETRY_COUNT:
- ISP_WRITE(isp, INMAILBOX7, mbp->param[7]);
- mbp->param[7] = 0;
- ISP_WRITE(isp, INMAILBOX6, mbp->param[6]);
- mbp->param[6] = 0;
- break;
- case MBOX_SET_ASYNC_DATA_SETUP_TIME:
- case MBOX_SET_ACT_NEG_STATE:
- case MBOX_SET_TAG_AGE_LIMIT:
- case MBOX_SET_SELECT_TIMEOUT:
- ISP_WRITE(isp, INMAILBOX2, mbp->param[2]);
- mbp->param[2] = 0;
- break;
+ for (box = 0; box < MAX_MAILBOX; box++) {
+ if (ibits & (1 << box)) {
+ ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
}
- }
-
- switch (inparam) {
- case 8: ISP_WRITE(isp, INMAILBOX7, mbp->param[7]); mbp->param[7] = 0;
- case 7: ISP_WRITE(isp, INMAILBOX6, mbp->param[6]); mbp->param[6] = 0;
- case 6:
- /*
- * The Qlogic 2100 cannot have registers 4 and 5 written to
- * after initialization or BAD THINGS HAPPEN (tm).
- */
- if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE)
- ISP_WRITE(isp, INMAILBOX5, mbp->param[5]);
- mbp->param[5] = 0;
- case 5:
- if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE)
- ISP_WRITE(isp, INMAILBOX4, mbp->param[4]);
- mbp->param[4] = 0;
- case 4: ISP_WRITE(isp, INMAILBOX3, mbp->param[3]); mbp->param[3] = 0;
- case 3: ISP_WRITE(isp, INMAILBOX2, mbp->param[2]); mbp->param[2] = 0;
- case 2: ISP_WRITE(isp, INMAILBOX1, mbp->param[1]); mbp->param[1] = 0;
- case 1: ISP_WRITE(isp, INMAILBOX0, mbp->param[0]); mbp->param[0] = 0;
+ isp->isp_mboxtmp[box] = mbp->param[box] = 0;
}
/*
- * Clear RISC int condition.
+ * We assume that we can't overwrite a previous command.
*/
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
-
- /*
- * Clear semaphore on mailbox registers so that the Qlogic
- * may update outgoing registers.
- */
- ISP_WRITE(isp, BIU_SEMA, 0);
+ isp->isp_mboxbsy = obits;
/*
* Set Host Interrupt condition so that RISC will pick up mailbox regs.
@@ -3427,121 +3603,25 @@ command_known:
ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT);
/*
- * Wait until HOST INT has gone away (meaning that the Qlogic
- * has picked up the mailbox command. Wait a long time.
+ * Give the f/w a chance to pick this up.
*/
- loops = MBOX_DELAY_COUNT * 5;
- while ((ISP_READ(isp, HCCR) & HCCR_CMD_CLEAR_RISC_INT) != 0) {
- SYS_DELAY(100);
- if (--loops < 0) {
- PRINTF("%s: isp_mboxcmd timeout #2\n", isp->isp_name);
- return;
- }
- }
+ SYS_DELAY(250);
- /*
- * While the Semaphore registers isn't set, wait for the Qlogic
- * to process the mailbox command. Again- wait a long time.
- */
- loops = MBOX_DELAY_COUNT * 5;
- while ((ISP_READ(isp, BIU_SEMA) & 1) == 0) {
- SYS_DELAY(100);
- /*
- * Wierd- I've seen the case where the semaphore register
- * isn't getting set- sort of a violation of the protocol..
- */
- if (ISP_READ(isp, OUTMAILBOX0) & 0x4000)
- break;
- if (--loops < 0) {
- PRINTF("%s: isp_mboxcmd timeout #3\n", isp->isp_name);
- return;
- }
- }
/*
- * Make sure that the MBOX_BUSY has gone away
+ * While we haven't finished the command, spin our wheels here.
*/
- loops = MBOX_DELAY_COUNT;
- for (;;) {
- u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);
- if (mbox == MBOX_BUSY) {
- if (--loops < 0) {
- PRINTF("%s: isp_mboxcmd timeout #4\n",
- isp->isp_name);
- return;
- }
- SYS_DELAY(100);
- continue;
- }
- /*
- * We have a pending MBOX async event.
- */
- if (mbox & 0x8000) {
- int fph = isp_parse_async(isp, (int) mbox);
- ISP_WRITE(isp, BIU_SEMA, 0);
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
- if (fph < 0) {
- return;
- } else if (fph > 0) {
- isp_fastpost_complete(isp, fph);
- }
- SYS_DELAY(100);
- continue;
- }
- break;
- }
+ MBOX_WAIT_COMPLETE(isp);
/*
- * Pick up output parameters. Special case some of the readbacks
- * for the dual port SCSI cards.
+ * Copy back output registers.
*/
- if (IS_DUALBUS(isp)) {
- switch (opcode) {
- case MBOX_GET_RETRY_COUNT:
- case MBOX_SET_RETRY_COUNT:
- mbp->param[7] = ISP_READ(isp, OUTMAILBOX7);
- mbp->param[6] = ISP_READ(isp, OUTMAILBOX6);
- break;
- case MBOX_GET_TAG_AGE_LIMIT:
- case MBOX_SET_TAG_AGE_LIMIT:
- case MBOX_GET_ACT_NEG_STATE:
- case MBOX_SET_ACT_NEG_STATE:
- case MBOX_SET_ASYNC_DATA_SETUP_TIME:
- case MBOX_GET_ASYNC_DATA_SETUP_TIME:
- case MBOX_GET_RESET_DELAY_PARAMS:
- case MBOX_SET_RESET_DELAY_PARAMS:
- mbp->param[2] = ISP_READ(isp, OUTMAILBOX2);
- break;
- }
- }
-
- if (IS_2200(isp)) {
- if (opcode == MBOX_GET_LOOP_ID) {
- mbp->param[6] = ISP_READ(isp, OUTMAILBOX6);
+ for (box = 0; box < MAX_MAILBOX; box++) {
+ if (obits & (1 << box)) {
+ mbp->param[box] = isp->isp_mboxtmp[box];
}
}
- switch (outparam) {
- case 8: mbp->param[7] = ISP_READ(isp, OUTMAILBOX7);
- case 7: mbp->param[6] = ISP_READ(isp, OUTMAILBOX6);
- case 6: mbp->param[5] = ISP_READ(isp, OUTMAILBOX5);
- case 5: mbp->param[4] = ISP_READ(isp, OUTMAILBOX4);
- case 4: mbp->param[3] = ISP_READ(isp, OUTMAILBOX3);
- case 3: mbp->param[2] = ISP_READ(isp, OUTMAILBOX2);
- case 2: mbp->param[1] = ISP_READ(isp, OUTMAILBOX1);
- case 1: mbp->param[0] = ISP_READ(isp, OUTMAILBOX0);
- }
-
- /*
- * Clear RISC int.
- */
- ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
-
- /*
- * Release semaphore on mailbox registers
- */
- ISP_WRITE(isp, BIU_SEMA, 0);
-
/*
* Just to be chatty here...
*/
@@ -3582,30 +3662,6 @@ command_known:
case MBOX_ALL_IDS_USED:
break;
-
- /*
- * Be silent about these...
- */
- case ASYNC_PDB_CHANGED:
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
- break;
-
- case ASYNC_LIP_OCCURRED:
- ((fcparam *) isp->isp_param)->isp_lipseq = mbp->param[1];
- /* FALLTHROUGH */
- case ASYNC_LOOP_UP:
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
- break;
-
- case ASYNC_LOOP_DOWN:
- case ASYNC_LOOP_RESET:
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL;
- /* FALLTHROUGH */
- case ASYNC_CHANGE_NOTIFY:
- break;
-
default:
/*
* The expected return of EXEC_FIRMWARE is zero.
@@ -3778,7 +3834,7 @@ isp_update_bus(isp, bus)
int get;
if (sdp->isp_devparam[tgt].dev_enable == 0) {
- IDPRINTF(1, ("%s: skipping target %d bus %d update\n",
+ IDPRINTF(2, ("%s: skipping target %d bus %d update\n",
isp->isp_name, tgt, bus));
continue;
}
@@ -3877,15 +3933,23 @@ isp_setdfltparm(isp, channel)
/* Platform specific.... */
fcp->isp_loopid = DEFAULT_LOOPID(isp);
fcp->isp_nodewwn = DEFAULT_WWN(isp);
- fcp->isp_portwwn = 0;
+ if ((fcp->isp_nodewwn >> 60) == 2) {
+ fcp->isp_nodewwn &= ~((u_int64_t) 0xfff << 48);
+ fcp->isp_portwwn = fcp->isp_nodewwn |
+ (((u_int64_t)(isp->isp_unit+1)) << 48);
+ } else {
+ fcp->isp_portwwn = fcp->isp_nodewwn;
+ }
/*
* Now try and read NVRAM
*/
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));
+ PRINTF("%s: Node WWN 0x%08x%08x, Port WWN 0x%08x%08x\n",
+ isp->isp_name, (u_int32_t) (fcp->isp_nodewwn >> 32),
+ (u_int32_t) (fcp->isp_nodewwn & 0xffffffff),
+ (u_int32_t) (fcp->isp_portwwn >> 32),
+ (u_int32_t) (fcp->isp_portwwn & 0xffffffff));
}
return;
}
@@ -3958,7 +4022,8 @@ isp_setdfltparm(isp, channel)
isp->isp_type < ISP_HA_SCSI_1020A) ||
(isp->isp_bustype == ISP_BT_PCI &&
isp->isp_type < ISP_HA_SCSI_1040) ||
- (isp->isp_clock && isp->isp_clock < 60)) {
+ (isp->isp_clock && isp->isp_clock < 60) ||
+ (sdp->isp_ultramode == 0)) {
sdp->isp_devparam[tgt].sync_offset =
ISP_10M_SYNCPARMS >> 8;
sdp->isp_devparam[tgt].sync_period =
@@ -4067,9 +4132,6 @@ isp_restart(isp)
ISP_SCSI_XFER_T *xs;
u_int32_t handle;
-#if 0
- isp->isp_gotdparms = 0;
-#endif
isp_reset(isp);
if (isp->isp_state == ISP_RESETSTATE) {
isp_init(isp);
@@ -4668,39 +4730,42 @@ isp_parse_nvram_2100(isp, nvram_data)
u_int64_t full64;
} wwnstore;
- wwnstore.full64 = ISP2100_NVRAM_NODE_NAME(nvram_data);
-
/*
- * Broken PTI cards with nothing in the top nibble. Pah.
+ * There is supposed to be WWNN storage as distinct
+ * from WWPN storage in NVRAM, but it doesn't appear
+ * to be used sanely.
*/
- if ((wwnstore.wd.hi32 >> 28) == 0) {
- wwnstore.wd.hi32 |= (2 << 28);
- CFGPRINTF("%s: (corrected) Adapter WWN 0x%08x%08x\n",
- isp->isp_name, wwnstore.wd.hi32, wwnstore.wd.lo32);
- } else {
- CFGPRINTF("%s: Adapter WWN 0x%08x%08x\n", isp->isp_name,
- wwnstore.wd.hi32, wwnstore.wd.lo32);
- }
- fcp->isp_nodewwn = wwnstore.full64;
- /*
- * If the Node WWN has 2 in the top nibble, we can
- * authoritatively construct a Port WWN by adding
- * our unit number (plus one to make it nonzero) and
- * putting it into bits 59..56. If the top nibble isn't
- * 2, then we just set them identically.
- */
- if ((fcp->isp_nodewwn >> 60) == 2) {
- fcp->isp_portwwn = fcp->isp_nodewwn |
- (((u_int64_t)(isp->isp_unit+1)) << 56);
- } else {
- fcp->isp_portwwn = fcp->isp_nodewwn;
- }
- wwnstore.full64 = ISP2100_NVRAM_BOOT_NODE_NAME(nvram_data);
- if (wwnstore.full64 != 0) {
- PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n",
- isp->isp_name, wwnstore.wd.hi32, wwnstore.wd.lo32);
+ wwnstore.full64 = ISP2100_NVRAM_PORT_NAME(nvram_data);
+ if (wwnstore.full64 != 0LL) {
+ switch ((int) (wwnstore.full64 >> 60)) {
+ case 0:
+ /*
+ * Broken cards with nothing in the top nibble.
+ * Pah.
+ */
+ wwnstore.full64 |= (2LL << 60);
+ /* FALLTHROUGH */
+ case 2:
+ fcp->isp_portwwn = wwnstore.full64;
+ fcp->isp_nodewwn = wwnstore.full64;
+ fcp->isp_nodewwn &= ~((0xfffLL) << 48);
+ if (fcp->isp_nodewwn == fcp->isp_portwwn) {
+ fcp->isp_portwwn |=
+ (((u_int64_t)(isp->isp_unit+1)) << 48);
+ }
+ break;
+ default:
+ fcp->isp_portwwn = wwnstore.full64;
+ fcp->isp_nodewwn = wwnstore.full64;
+ }
}
+ CFGPRINTF("%s: Node WWN 0x%08x%08x, Port WWN 0x%08x%08x\n",
+ isp->isp_name, (u_int32_t) (fcp->isp_nodewwn >> 32),
+ (u_int32_t) (fcp->isp_nodewwn & 0xffffffff),
+ (u_int32_t) (fcp->isp_portwwn >> 32),
+ (u_int32_t) (fcp->isp_portwwn & 0xffffffff));
+
fcp->isp_maxalloc =
ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
fcp->isp_maxfrmlen =
diff --git a/sys/dev/ic/isp_inline.h b/sys/dev/ic/isp_inline.h
index 9e45b7d443c..08dbbbbfc4b 100644
--- a/sys/dev/ic/isp_inline.h
+++ b/sys/dev/ic/isp_inline.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_inline.h,v 1.3 2000/02/20 21:22:41 mjacob Exp $ */
+/* $OpenBSD: isp_inline.h,v 1.4 2000/07/06 05:31:48 mjacob Exp $ */
/*
* Qlogic Inline Functions
*
@@ -46,71 +46,54 @@ static INLINE void
isp_prtstst(sp)
ispstatusreq_t *sp;
{
- char buf[172], *p = buf;
- sprintf(p, "states->");
+ char buf[172];
+ buf[0] = 0;
+ STRNCAT(buf, "states=>", sizeof buf);
if (sp->req_state_flags & RQSF_GOT_BUS) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "GOT_BUS ");
+ STRNCAT(buf, " GOT_BUS", sizeof buf);
}
if (sp->req_state_flags & RQSF_GOT_TARGET) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "GOT_TGT ");
+ STRNCAT(buf, " GOT_TGT", sizeof buf);
}
if (sp->req_state_flags & RQSF_SENT_CDB) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "SENT_CDB ");
+ STRNCAT(buf, " SENT_CDB", sizeof buf);
}
if (sp->req_state_flags & RQSF_XFRD_DATA) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "XFRD_DATA ");
+ STRNCAT(buf, " XFRD_DATA", sizeof buf);
}
if (sp->req_state_flags & RQSF_GOT_STATUS) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "GOT_STS ");
+ STRNCAT(buf, " GOT_STS", sizeof buf);
}
if (sp->req_state_flags & RQSF_GOT_SENSE) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "GOT_SNS ");
+ STRNCAT(buf, " GOT_SNS", sizeof buf);
}
if (sp->req_state_flags & RQSF_XFER_COMPLETE) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "XFR_CMPLT ");
+ STRNCAT(buf, " XFR_CMPLT", sizeof buf);
}
- p += strlen(p);
- sprintf(p, "%s%s", buf, "\n");
- p += strlen(p);
- sprintf(p, "%s%s", buf, "status->");
+ STRNCAT(buf, "\nstatus=>", sizeof buf);
if (sp->req_status_flags & RQSTF_DISCONNECT) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Disconnect ");
+ STRNCAT(buf, " Disconnect", sizeof buf);
}
if (sp->req_status_flags & RQSTF_SYNCHRONOUS) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Sync_xfr ");
+ STRNCAT(buf, " Sync_xfr", sizeof buf);
}
if (sp->req_status_flags & RQSTF_PARITY_ERROR) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Parity ");
+ STRNCAT(buf, " Parity", sizeof buf);
}
if (sp->req_status_flags & RQSTF_BUS_RESET) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Bus_Reset ");
+ STRNCAT(buf, " Bus_Reset", sizeof buf);
}
if (sp->req_status_flags & RQSTF_DEVICE_RESET) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Device_Reset ");
+ STRNCAT(buf, " Device_Reset", sizeof buf);
}
if (sp->req_status_flags & RQSTF_ABORTED) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Aborted ");
+ STRNCAT(buf, " Aborted", sizeof buf);
}
if (sp->req_status_flags & RQSTF_TIMEOUT) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Timeout ");
+ STRNCAT(buf, " Timeout", sizeof buf);
}
if (sp->req_status_flags & RQSTF_NEGOTIATION) {
- p += strlen(p);
- sprintf(p, "%s%s", buf, "Negotiation ");
+ STRNCAT(buf, " Negotiation", sizeof buf);
}
PRINTF(buf, "%s\n", buf);
}
@@ -173,6 +156,9 @@ isp_find_xs __P((struct ispsoftc *, u_int32_t));
static INLINE u_int32_t
isp_find_handle __P((struct ispsoftc *, ISP_SCSI_XFER_T *));
+static INLINE int
+isp_handle_index __P((u_int32_t));
+
static INLINE void
isp_destroy_handle __P((struct ispsoftc *, u_int32_t));
@@ -234,13 +220,20 @@ isp_find_handle(isp, xs)
return (0);
}
+static INLINE int
+isp_handle_index(handle)
+ u_int32_t handle;
+{
+ return (handle-1);
+}
+
static INLINE void
isp_destroy_handle(isp, handle)
struct ispsoftc *isp;
u_int32_t handle;
{
if (handle > 0 && handle <= (u_int32_t) isp->isp_maxcmds) {
- isp->isp_xflist[handle - 1] = NULL;
+ isp->isp_xflist[isp_handle_index(handle)] = NULL;
}
}
@@ -271,8 +264,10 @@ isp_getrqentry(isp, iptrp, optrp, resultp)
if (iptr == optr) {
return (1);
}
- *optrp = optr;
- *iptrp = iptr;
+ if (optrp)
+ *optrp = optr;
+ if (iptrp)
+ *iptrp = iptr;
return (0);
}
diff --git a/sys/dev/ic/isp_openbsd.c b/sys/dev/ic/isp_openbsd.c
index 86c51cb323a..e882bb8ed01 100644
--- a/sys/dev/ic/isp_openbsd.c
+++ b/sys/dev/ic/isp_openbsd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_openbsd.c,v 1.9 2000/04/06 05:47:54 mjacob Exp $ */
+/* $OpenBSD: isp_openbsd.c,v 1.10 2000/07/06 05:31:48 mjacob Exp $ */
/*
* Platform (OpenBSD) dependent common attachment code for Qlogic adapters.
*
@@ -55,10 +55,12 @@ static int32_t ispcmd __P((ISP_SCSI_XFER_T *));
static struct scsi_device isp_dev = { NULL, NULL, NULL, NULL };
static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
-static void isp_watch __P((void *));
-static void isp_command_requeue(void *);
+static void isp_wdog __P((void *));
+static void isp_requeue(void *);
static void isp_internal_restart(void *);
+#define _XT(xs) ((((xs)->timeout + 999)/1000) + (2 * hz))
+
struct cfdriver isp_cd = {
NULL, "isp", DV_DULL
};
@@ -145,7 +147,6 @@ isp_attach(isp)
for (i = 0; i < 5; i++) {
if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL))
continue;
-#ifdef ISP2100_FABRIC
/*
* Wait extra time to see if the f/w
* eventually completed an FLOGI that
@@ -156,7 +157,6 @@ isp_attach(isp)
delay(1 * 1000000);
continue;
}
-#endif
break;
}
if (fcp->isp_fwstate == FW_READY &&
@@ -168,14 +168,6 @@ isp_attach(isp)
}
/*
- * Start the watchdog.
- *
- * The watchdog will, ridiculously enough, also enable Sync negotiation.
- */
- isp->isp_dogactive = 1;
- timeout(isp_watch, isp, WATCH_INTERVAL * hz);
-
- /*
* And attach children (if any).
*/
config_found((void *)isp, lptr, scsiprint);
@@ -299,9 +291,15 @@ ispcmd(xs)
int result;
int s;
- isp = xs->sc_link->adapter_softc;
- s = splbio();
+ /*
+ * Make sure that there's *some* kind of sane setting.
+ */
+ timeout_set(&xs->stimeout, isp_wdog, isp);
+ timeout_del(&xs->stimeout);
+ isp = XS_ISP(xs);
+
+ s = splbio();
if (isp->isp_state < ISP_RUNSTATE) {
DISABLE_INTS(isp);
isp_init(isp);
@@ -335,21 +333,23 @@ ispcmd(xs)
splx(s);
return (SUCCESSFULLY_QUEUED);
}
- DISABLE_INTS(isp);
result = ispscsicmd(xs);
- ENABLE_INTS(isp);
if ((xs->flags & SCSI_POLL) == 0) {
switch (result) {
case CMD_QUEUED:
result = SUCCESSFULLY_QUEUED;
+ if (xs->timeout) {
+ timeout_add(&xs->stimeout, _XT(xs));
+ }
break;
case CMD_EAGAIN:
result = TRY_AGAIN_LATER;
break;
case CMD_RQLATER:
result = SUCCESSFULLY_QUEUED;
- timeout(isp_command_requeue, xs, hz);
+ timeout_set(&xs->stimeout, isp_requeue, xs);
+ timeout_add(&xs->stimeout, hz);
break;
case CMD_COMPLETE:
result = COMPLETE;
@@ -385,7 +385,7 @@ ispcmd(xs)
* If no other error occurred but we didn't finish,
* something bad happened.
*/
- if (XS_IS_CMD_DONE(xs) == 0) {
+ if (XS_CMD_DONE_P(xs) == 0) {
if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
isp_restart(isp);
}
@@ -400,6 +400,25 @@ ispcmd(xs)
return (result);
}
+void
+isp_done(xs)
+ ISP_SCSI_XFER_T *xs;
+{
+ XS_CMD_S_DONE(xs);
+ if (XS_CMD_WDOG_P(xs) == 0) {
+ if (xs->timeout) {
+ timeout_del(&xs->stimeout);
+ }
+ if (XS_CMD_GRACE_P(xs)) {
+ struct ispsoftc *isp = XS_ISP(xs);
+ PRINTF("%s: finished command on borrowed time\n",
+ isp->isp_name);
+ }
+ XS_CMD_S_CLEAR(xs);
+ scsi_done(xs);
+ }
+}
+
static int
isp_poll(isp, xs, mswait)
struct ispsoftc *isp;
@@ -412,7 +431,7 @@ isp_poll(isp, xs, mswait)
(void)isp_intr((void *)isp);
/* See if the xs is now done */
- if (XS_IS_CMD_DONE(xs)) {
+ if (XS_CMD_DONE_P(xs)) {
return (0);
}
delay(1000); /* wait one millisecond */
@@ -423,48 +442,97 @@ isp_poll(isp, xs, mswait)
static void
-isp_watch(arg)
+isp_wdog(arg)
void *arg;
{
- int i;
- struct ispsoftc *isp = arg;
- struct scsi_xfer *xs;
- int s;
+ ISP_SCSI_XFER_T *xs = arg;
+ struct ispsoftc *isp = XS_ISP(xs);
+ u_int32_t handle;
+ int s = splbio();
/*
- * Look for completely dead commands (but not polled ones).
+ * We've decided this command is dead. Make sure we're not trying
+ * to kill a command that's already dead by getting it's handle and
+ * and seeing whether it's still alive.
*/
- s = splbio();
- for (i = 0; i < isp->isp_maxcmds; i++) {
- if ((xs = (struct scsi_xfer *) isp->isp_xflist[i]) == NULL) {
- continue;
- }
- if (xs->timeout == 0 || (xs->flags & SCSI_POLL)) {
- continue;
+ handle = isp_find_handle(isp, xs);
+ if (handle) {
+ u_int16_t r, r1, i;
+
+ if (XS_CMD_DONE_P(xs)) {
+ PRINTF("%s: watchdog found done cmd (handle 0x%x)\n",
+ isp->isp_name, handle);
+ (void) splx(s);
+ return;
}
- xs->timeout -= (WATCH_INTERVAL * 1000);
- /*
- * Avoid later thinking that this
- * transaction is not being timed.
- * Then give ourselves to watchdog
- * periods of grace.
- */
- if (xs->timeout == 0) {
- xs->timeout = 1;
- } else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
- continue;
+ if (XS_CMD_WDOG_P(xs)) {
+ PRINTF("%s: recursive watchdog (handle 0x%x)\n",
+ isp->isp_name, handle);
+ (void) splx(s);
+ return;
}
- if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
- printf("%s: isp_watch failed to abort command\n",
- isp->isp_name);
- isp_restart(isp);
- break;
+
+ XS_CMD_S_WDOG(xs);
+
+ i = 0;
+ do {
+ r = ISP_READ(isp, BIU_ISR);
+ SYS_DELAY(1);
+ r1 = ISP_READ(isp, BIU_ISR);
+ } while (r != r1 && ++i < 1000);
+
+ if (INT_PENDING(isp, r) && isp_intr(isp) && XS_CMD_DONE_P(xs)) {
+ IDPRINTF(1, ("%s: watchdog cleanup (%x, %x)\n",
+ isp->isp_name, handle, r));
+ XS_CMD_C_WDOG(xs);
+ isp_done(xs);
+ } else if (XS_CMD_GRACE_P(xs)) {
+ /*
+ * Make sure the command is *really* dead before we
+ * release the handle (and DMA resources) for reuse.
+ */
+ (void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
+
+ /*
+ * After this point, the comamnd is really dead.
+ */
+ if (XS_XFRLEN(xs)) {
+ ISP_DMAFREE(isp, xs, handle);
+ }
+ printf("%s: watchdog timeout (%x, %x)\n",
+ isp->isp_name, handle, r);
+ isp_destroy_handle(isp, handle);
+ XS_SETERR(xs, XS_TIMEOUT);
+ XS_CMD_S_CLEAR(xs);
+ isp_done(xs);
+ } else {
+ u_int16_t iptr, optr;
+ ispreq_t *mp;
+
+ IDPRINTF(2, ("%s: possible command timeout (%x, %x)\n",
+ isp->isp_name, handle, r));
+
+ XS_CMD_C_WDOG(xs);
+ timeout_add(&xs->stimeout, _XT(xs));
+ if (isp_getrqentry(isp, &iptr, &optr, (void **) &mp)) {
+ (void) splx(s);
+ 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_SWIZZLE_REQUEST(isp, mp);
+ MemoryBarrier();
+ ISP_ADD_REQUEST(isp, iptr);
}
+ } else if (isp->isp_dblev) {
+ PRINTF("%s: watchdog with no command\n", isp->isp_name);
}
- timeout(isp_watch, isp, WATCH_INTERVAL * hz);
- isp->isp_dogactive = 1;
- splx(s);
+ (void) splx(s);
}
/*
@@ -484,14 +552,6 @@ isp_uninit(isp)
*/
DISABLE_INTS(isp);
- /*
- * Turn off the watchdog (if active).
- */
- if (isp->isp_dogactive) {
- untimeout(isp_watch, isp);
- isp->isp_dogactive = 0;
- }
-
splx(s);
}
@@ -499,7 +559,7 @@ isp_uninit(isp)
* Restart function for a command to be requeued later.
*/
static void
-isp_command_requeue(void *arg)
+isp_requeue(void *arg)
{
struct scsi_xfer *xs = arg;
struct ispsoftc *isp = XS_ISP(xs);
@@ -508,6 +568,10 @@ isp_command_requeue(void *arg)
case SUCCESSFULLY_QUEUED:
printf("%s: isp_command_reque: queued %d.%d\n",
isp->isp_name, XS_TGT(xs), XS_LUN(xs));
+ if (xs->timeout) {
+ timeout_set(&xs->stimeout, isp_wdog, isp);
+ timeout_add(&xs->stimeout, _XT(xs));
+ }
break;
case TRY_AGAIN_LATER:
printf("%s: EAGAIN for %d.%d\n",
@@ -548,6 +612,8 @@ isp_internal_restart(void *arg)
if (XS_NOERR(xs))
XS_SETERR(xs, XS_DRIVER_STUFFUP);
XS_CMD_DONE(xs);
+ } else if (xs->timeout) {
+ timeout_add(&xs->stimeout, _XT(xs));
}
nrestarted++;
}
@@ -645,7 +711,8 @@ isp_async(isp, cmd, arg)
break;
case ISPASYNC_LOOP_UP:
isp->isp_osinfo.blocked = 0;
- timeout(isp_internal_restart, isp, 1);
+ timeout_set(&isp->isp_osinfo.rqt, isp_internal_restart, isp);
+ timeout_add(&isp->isp_osinfo.rqt, 1);
printf("%s: Loop UP\n", isp->isp_name);
break;
case ISPASYNC_PDB_CHANGED:
@@ -673,7 +740,6 @@ isp_async(isp, cmd, arg)
(u_int32_t) (lp->node_wwn & 0xffffffffLL));
break;
}
-#ifdef ISP2100_FABRIC
case ISPASYNC_CHANGE_NOTIFY:
printf("%s: Name Server Database Changed\n", isp->isp_name);
break;
@@ -776,7 +842,6 @@ isp_async(isp, cmd, arg)
lp->portid = portid;
break;
}
-#endif
default:
break;
}
diff --git a/sys/dev/ic/isp_openbsd.h b/sys/dev/ic/isp_openbsd.h
index fabd0857fe2..89f34fb2633 100644
--- a/sys/dev/ic/isp_openbsd.h
+++ b/sys/dev/ic/isp_openbsd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_openbsd.h,v 1.8 2000/03/05 22:20:09 mjacob Exp $ */
+/* $OpenBSD: isp_openbsd.h,v 1.9 2000/07/06 05:31:48 mjacob Exp $ */
/*
* OpenBSD Specific definitions for the Qlogic ISP Host Adapter
*
@@ -63,7 +63,7 @@
#include <vm/pmap.h>
#define ISP_PLATFORM_VERSION_MAJOR 0
-#define ISP_PLATFORM_VERSION_MINOR 9
+#define ISP_PLATFORM_VERSION_MINOR 10
#define ISP_SCSI_XFER_T struct scsi_xfer
struct isposinfo {
@@ -78,14 +78,28 @@ struct isposinfo {
#define seed un._seed
#define discovered un._discovered
struct scsi_xfer *wqf, *wqt;
+ struct timeout rqt;
};
+#define MBOX_WAIT_COMPLETE(isp) \
+ { \
+ int j; \
+ for (j = 0; j < 60 * 2000; j++) { \
+ if (isp_intr(isp) == 0) { \
+ SYS_DELAY(500); \
+ } \
+ if (isp->isp_mboxbsy == 0) \
+ break; \
+ } \
+ if (isp->isp_mboxbsy != 0) \
+ printf("%s: mailbox timeout\n", isp->isp_name); \
+ }
+
+#define MBOX_NOTIFY_COMPLETE(isp) isp->isp_mboxbsy = 0
+
#define MAXISPREQUEST 256
-#ifdef ISP2100_FABRIC
+#define ISP2100_FABRIC 1
#define ISP2100_SCRLEN 0x400
-#else
-#define ISP2100_SCRLEN 0x100
-#endif
#include <dev/ic/ispreg.h>
#include <dev/ic/ispvar.h>
@@ -160,13 +174,30 @@ struct isposinfo {
#define XS_SNS_IS_VALID(xs) (xs)->error = XS_SENSE
#define XS_IS_SNS_VALID(xs) ((xs)->error == XS_SENSE)
-#define XS_INITERR(xs) (xs)->error = 0
+#define XS_PSTS_INWDOG 0x10000
+#define XS_PSTS_GRACE 0x20000
+#define XS_PSTS_ALL SCSI_PRIVATE
+
+#define XS_CMD_S_WDOG(xs) (xs)->flags |= XS_PSTS_INWDOG
+#define XS_CMD_C_WDOG(xs) (xs)->flags &= ~XS_PSTS_INWDOG
+#define XS_CMD_WDOG_P(xs) (((xs)->flags & XS_PSTS_INWDOG) != 0)
+
+#define XS_CMD_S_GRACE(xs) (xs)->flags |= XS_PSTS_GRACE
+#define XS_CMD_C_GRACE(xs) (xs)->flags &= ~XS_PSTS_GRACE
+#define XS_CMD_GRACE_P(xs) (((xs)->flags & XS_PSTS_GRACE) != 0)
+
+#define XS_CMD_S_DONE(xs) (xs)->flags |= ITSDONE
+#define XS_CMD_C_DONE(xs) (xs)->flags &= ~ITSDONE
+#define XS_CMD_DONE_P(xs) (((xs)->flags & ITSDONE) != 0)
+
+#define XS_CMD_S_CLEAR(xs) (xs)->flags &= ~XS_PSTS_ALL
+
+#define XS_INITERR(xs) (xs)->error = 0, XS_CMD_S_CLEAR(xs)
#define XS_SETERR(xs, v) (xs)->error = v
#define XS_ERR(xs) (xs)->error
#define XS_NOERR(xs) (xs)->error == XS_NOERROR
-#define XS_CMD_DONE(xs) (xs)->flags |= ITSDONE, scsi_done(xs)
-#define XS_IS_CMD_DONE(xs) (((xs)->flags & ITSDONE) != 0)
+#define XS_CMD_DONE isp_done
/*
* We use whether or not we're a polled command to decide about tagging.
@@ -198,6 +229,7 @@ struct isposinfo {
extern void isp_attach __P((struct ispsoftc *));
extern void isp_uninit __P((struct ispsoftc *));
+extern void isp_done __P((ISP_SCSI_XFER_T *));
#define ISP_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src) \
@@ -218,6 +250,27 @@ extern void isp_uninit __P((struct ispsoftc *));
#define ISP_SWIZZLE_SNS_REQ(a, b)
#define ISP_UNSWIZZLE_SNS_RSP(a, b, c)
+#define STRNCAT strncat
+static inline char *strncat(char *, const char *, size_t);
+static inline char *
+strncat(char *d, const char *s, size_t c)
+{
+ char *t = d;
+
+ if (c) {
+ while (*d)
+ d++;
+ while ((*d++ = *s++)) {
+ if (--c == 0) {
+ *d = '\0';
+ break;
+ }
+ }
+ }
+ return (t);
+}
+
+
#define INLINE inline
#include <dev/ic/isp_inline.h>
diff --git a/sys/dev/ic/isp_target.c b/sys/dev/ic/isp_target.c
index bd7a4824e2b..d6b7fd14b9e 100644
--- a/sys/dev/ic/isp_target.c
+++ b/sys/dev/ic/isp_target.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_target.c,v 1.1 2000/02/20 21:22:40 mjacob Exp $ */
+/* $OpenBSD: isp_target.c,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */
/*
* Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
*
@@ -285,7 +285,7 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
el.le_in_count = DFLT_INOTIFY;
if (cmd == RQSTYPE_ENABLE_LUN) {
if (IS_SCSI(isp)) {
- el.le_flags = LUN_TQAE;
+ el.le_flags = LUN_TQAE|LUN_DISAD;
el.le_cdb6len = 12;
el.le_cdb7len = 12;
}
@@ -305,10 +305,8 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
if (IS_SCSI(isp)) {
el.le_tgt = tgt;
el.le_lun = lun;
-#ifndef ISP2100_SCCLUN
- } else {
+ } else if (isp->isp_maxluns <= 16) {
el.le_lun = lun;
-#endif
}
if (isp_getrqentry(isp, &iptr, &optr, &outp)) {
@@ -380,11 +378,11 @@ isp_target_put_atio(isp, iid, tgt, lun, ttype, tval)
if (IS_FC(isp)) {
atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
atun._atio2.at_header.rqs_entry_count = 1;
-#ifdef ISP2100_SCCLUN
- atun._atio2.at_scclun = (uint16_t) lun;
-#else
- atun._atio2.at_lun = (uint8_t) lun;
-#endif
+ if (isp->isp_maxluns > 16) {
+ atun._atio2.at_scclun = (u_int16_t) lun;
+ } else {
+ atun._atio2.at_lun = (u_int8_t) lun;
+ }
atun._atio2.at_status = CT_OK;
} else {
atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO;
@@ -436,9 +434,9 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int32_t hdl)
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
cto->ct_header.rqs_entry_count = 1;
cto->ct_iid = aep->at_iid;
-#ifndef ISP2100_SCCLUN
- cto->ct_lun = aep->at_lun;
-#endif
+ if (isp->isp_maxluns <= 16) {
+ cto->ct_lun = aep->at_lun;
+ }
cto->ct_rxid = aep->at_rxid;
cto->rsp.m1.ct_scsi_status = sts & 0xff;
cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1;
@@ -596,11 +594,11 @@ isp_got_msg_fc(isp, bus, inp)
MEMZERO(&msg, sizeof (msg));
msg.nt_bus = bus;
msg.nt_iid = inp->in_iid;
-#ifdef ISP2100_SCCLUN
- msg.nt_lun = inp->in_scclun;
-#else
- msg.nt_lun = inp->in_lun;
-#endif
+ if (isp->isp_maxluns > 16) {
+ msg.nt_lun = inp->in_scclun;
+ } else {
+ msg.nt_lun = inp->in_lun;
+ }
msg.nt_tagval = inp->in_seqid;
if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) {
@@ -658,11 +656,11 @@ isp_notify_ack(isp, arg)
in_fcentry_t *inp = arg;
MEMCPY(storage, arg, sizeof (isphdr_t));
na->na_iid = inp->in_iid;
-#ifdef ISP2100_SCCLUN
- na->na_lun = inp->in_scclun;
-#else
- na->na_lun = inp->in_lun;
-#endif
+ if (isp->isp_maxluns > 16) {
+ na->na_lun = inp->in_scclun;
+ } else {
+ na->na_lun = inp->in_lun;
+ }
na->na_task_flags = inp->in_task_flags;
na->na_seqid = inp->in_seqid;
na->na_flags = NAFC_RCOUNT;
@@ -672,6 +670,8 @@ isp_notify_ack(isp, arg)
} else {
na->na_flags = NAFC_RST_CLRD;
}
+ na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
+ na->na_header.rqs_entry_count = 1;
ISP_SWIZ_NOT_ACK_FC(isp, outp, na);
} else {
na_entry_t *na = (na_entry_t *) storage;
@@ -683,11 +683,13 @@ isp_notify_ack(isp, arg)
na->na_tgt = inp->in_tgt;
na->na_seqid = inp->in_seqid;
if (inp->in_status == IN_RESET) {
- na->na_flags = NA_RST_CLRD;
+ na->na_event = NA_RST_CLRD;
}
} else {
- na->na_flags = NA_RST_CLRD;
+ na->na_event = NA_RST_CLRD;
}
+ na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
+ na->na_header.rqs_entry_count = 1;
ISP_SWIZ_NOT_ACK(isp, outp, na);
}
ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
@@ -784,11 +786,13 @@ isp_handle_atio2(isp, aep)
at2_entry_t *aep;
{
int lun;
-#ifdef ISP2100_SCCLUN
- lun = aep->at_scclun;
-#else
- lun = aep->at_lun;
-#endif
+
+ if (isp->isp_maxluns > 16) {
+ lun = aep->at_scclun;
+ } else {
+ lun = aep->at_lun;
+ }
+
/*
* The firmware status (except for the QLTM_SVALID bit) indicates
* why this ATIO was sent to us.
@@ -892,12 +896,14 @@ isp_handle_ctio(isp, ct)
* We sent status & command complete.
*/
- if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) {
+ if (ct->ct_flags & CT_SENDSTATUS) {
+ break;
+ } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) {
/*
* Nothing to do in this case.
*/
- IDPRINTF(pl, ("%s: CTIO- initiator disconnected OK\n",
- isp->isp_name));
+ IDPRINTF(pl, ("%s:CTIO- iid %d disconnected OK\n",
+ isp->isp_name, ct->ct_iid));
return;
}
break;
@@ -1025,7 +1031,7 @@ isp_handle_ctio(isp, ct)
* complete thread synchronization.
*/
IDPRINTF(pl,
- ("%s: status CTIO complete\n", isp->isp_name));
+ ("%s:status CTIO complete\n", isp->isp_name));
} else {
/*
* Final CTIO completed. Release DMA resources and
diff --git a/sys/dev/ic/isp_target.h b/sys/dev/ic/isp_target.h
index 7b86aa1de94..725a9dfb2e7 100644
--- a/sys/dev/ic/isp_target.h
+++ b/sys/dev/ic/isp_target.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_target.h,v 1.1 2000/02/20 21:22:40 mjacob Exp $ */
+/* $OpenBSD: isp_target.h,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */
/*
* Qlogic Target Mode Structure and Flag Definitions
*
@@ -71,6 +71,7 @@ typedef struct {
*/
#define LUN_TQAE 0x00000001 /* bit1 Tagged Queue Action Enable */
#define LUN_DSSM 0x01000000 /* bit24 Disable Sending SDP Message */
+#define LUN_DISAD 0x02000000 /* bit25 Disable autodisconnect */
#define LUN_DM 0x40000000 /* bit30 Disconnects Mandatory */
/*
@@ -186,6 +187,8 @@ typedef struct {
* Value for the na_event field
*/
#define NA_RST_CLRD 0x80 /* Clear an async event notification */
+#define NA_OK 0x01 /* Notify Acknowledge Succeeded */
+#define NA_INVALID 0x06 /* Invalid Notify Acknowledge */
#define NA2_RSVDLEN 21
typedef struct {
@@ -623,7 +626,7 @@ int isp_target_notify __P((struct ispsoftc *, void *, u_int16_t *));
*/
#define DFLT_CMD_CNT (RESULT_QUEUE_LEN >> 1)
#define DFLT_INOTIFY (4)
-int isp_lun_cmd __P((struct ispsoftc *isp, int, int, int, int, u_int32_t));
+int isp_lun_cmd __P((struct ispsoftc *, int, int, int, int, u_int32_t));
/*
* General request queue 'put' routine for target mode entries.
@@ -635,14 +638,14 @@ int isp_target_put_entry __P((struct ispsoftc *isp, void *));
* used for replenishing f/w resource counts.
*/
int
-isp_target_put_atio __P((struct ispsoftc *isp, int, int, int, int, int));
+isp_target_put_atio __P((struct ispsoftc *, int, int, int, int, int));
/*
* General routine to send a final CTIO for a command- used mostly for
* local responses.
*/
int
-isp_endcmd __P((struct ispsoftc *isp, void *, u_int32_t, u_int32_t));
+isp_endcmd __P((struct ispsoftc *, void *, u_int32_t, u_int32_t));
#define ECMD_SVALID 0x100
/*
diff --git a/sys/dev/ic/isp_tpublic.h b/sys/dev/ic/isp_tpublic.h
index a9ebe9589a8..34619b99df7 100644
--- a/sys/dev/ic/isp_tpublic.h
+++ b/sys/dev/ic/isp_tpublic.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_tpublic.h,v 1.1 2000/02/20 21:22:40 mjacob Exp $ */
+/* $OpenBSD: isp_tpublic.h,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */
/*
* Qlogic ISP Host Adapter Public Target Interface Structures && Routines
*---------------------------------------
@@ -59,11 +59,26 @@ typedef struct {
} tmd_event_t;
/*
- * Suggested software target mode command handling structure.
+ * Suggested Software Target Mode Command Handling structure.
*
- * The command structure is one suggested possible MD command structure,
- * but since the handling of thbis is entirely in the MD layer, there
- * is no requirement that it be used.
+ * A note about terminology:
+ *
+ * MD stands for "Machine Dependent".
+ *
+ * This driver is structured in three layers: Outer MD, core, and inner MD.
+ * The latter also is bus dependent (i.e., is cognizant of PCI bus issues
+ * as well as platform issues).
+ *
+ *
+ * "Outer Layer" means "Other Module"
+ *
+ * Some additional module that actually implements SCSI target command
+ * policy is the recipient of incoming commands and the source of the
+ * disposition for them.
+ *
+ * The command structure below is one suggested possible MD command structure,
+ * but since the handling of thbis is entirely in the MD layer, there is
+ * no explicit or implicit requirement that it be used.
*
* The cd_private tag should be used by the MD layer to keep a free list
* of these structures. Code outside of this driver can then use this
@@ -123,17 +138,16 @@ typedef struct {
* layers must agree on the meaning of cd_data.
*
* The tag cd_totlen is the total data amount expected to be moved
- * over the life of the command. It may be set by the MD layer,
- * for example, from the datalen field of an FCP CMND IU unit. If
- * it shows up in the outer layers set to zero and the CDB indicates
- * data should be moved, the outer layer should set it to the amount
- * expected to be moved.
+ * over the life of the command. It *may* be set by the MD layer, possibly
+ * from the datalen field of an FCP CMND IU unit. If it shows up in the outer
+ * layers set to zero and the CDB indicates data should be moved, the outer
+ * layer should set it to the amount expected to be moved.
*
* The tag cd_resid should be the total residual of data not transferred.
* The outer layers need to set this at the begining of command processing
* to equal cd_totlen. As data is successfully moved, this value is decreased.
* At the end of a command, any nonzero residual indicates the number of bytes
- * requested but not moved.
+ * requested but not moved. XXXXXXXXXXXXXXXXXXXXXXX TOO VAGUE!!!
*
* The tag cd_xfrlen is the length of the currently active data transfer.
* This allows several interations between any outside software and the
@@ -206,9 +220,10 @@ typedef struct tmd_cmd {
} tmd_cmd_t;
#define CDFL_BUSY 0x01 /* this command is not on a free list */
-#define CDFL_NODISC 0x02 /* disconnect not allowed */
+#define CDFL_NODISC 0x02 /* disconnects disabled */
#define CDFL_SENTSENSE 0x04 /* last action sent sense data */
-#define CDFL_ERROR 0x08 /* last action ended in error */
+#define CDFL_SENTSTATUS 0x08 /* last action sent status */
+#define CDFL_ERROR 0x10 /* last action ended in error */
#define CDFL_PRIVATE_0 0x80 /* private layer flags */
#define CDFH_SNSVALID 0x01 /* sense data valid */
@@ -238,6 +253,8 @@ typedef enum {
*/
typedef enum {
QIN_HBA_REG=6, /* the argument is a pointer to a hba_register_t */
+ QIN_ENABLE, /* the argument is a pointer to a tmd_cmd_t */
+ QIN_DISABLE, /* the argument is a pointer to a tmd_cmd_t */
QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */
QIN_TMD_FIN, /* the argument is a pointer to a done tmd_cmd_t */
QIN_HBA_UNREG /* the argument is a pointer to a hba_register_t */
@@ -267,6 +284,16 @@ typedef enum {
* The graph looks like:
*
* QOUT_TMD_START -> [ QIN_TMD_CONT -> QOUT_TMD_DONE ] * -> QIN_TMD_FIN.
+ *
+ */
+
+/*
+ * A word about ENABLE/DISABLE: the argument is a pointer to an tmd_cmd_t
+ * with cd_hba, cd_bus, cd_tgt and cd_lun filled out. If an error occurs
+ * in either enabling or disabling the described lun, cd_lflags is set
+ * with CDFL_ERROR.
+ *
+ * Logical unit zero must be the first enabled and the last disabled.
*/
/*
@@ -297,5 +324,6 @@ typedef struct {
char r_name[8];
int r_inst;
int r_lunwidth;
+ int r_buswidth;
void (*r_action) __P((int, void *));
} hba_register_t;
diff --git a/sys/dev/ic/ispmbox.h b/sys/dev/ic/ispmbox.h
index 51cc085b2b9..1d298dbd751 100644
--- a/sys/dev/ic/ispmbox.h
+++ b/sys/dev/ic/ispmbox.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ispmbox.h,v 1.8 2000/02/20 21:22:41 mjacob Exp $ */
+/* $OpenBSD: ispmbox.h,v 1.9 2000/07/06 05:31:49 mjacob Exp $ */
/*
* Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters.
*
@@ -118,6 +118,7 @@
/* These are for the ISP2100 FC cards */
#define MBOX_GET_LOOP_ID 0x20
+#define MBOX_GET_RESOURCE_COUNT 0x42
#define MBOX_EXEC_COMMAND_IOCB_A64 0x54
#define MBOX_INIT_FIRMWARE 0x60
#define MBOX_GET_INIT_CONTROL_BLOCK 0x61
@@ -564,7 +565,7 @@ typedef struct {
u_int16_t pdb_options;
u_int8_t pdb_mstate;
u_int8_t pdb_sstate;
-#define BITS2WORD(x) (x)[0] << 16 | (x)[3] << 8 | (x)[2]
+#define BITS2WORD(x) ((x)[0] << 16 | (x)[3] << 8 | (x)[2])
u_int8_t pdb_hardaddr_bits[4];
u_int8_t pdb_portid_bits[4];
u_int8_t pdb_nodename[8];
diff --git a/sys/dev/ic/ispreg.h b/sys/dev/ic/ispreg.h
index 0a7a1ae7ac2..bacf424cb8f 100644
--- a/sys/dev/ic/ispreg.h
+++ b/sys/dev/ic/ispreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ispreg.h,v 1.7 2000/02/20 21:22:41 mjacob Exp $ */
+/* $OpenBSD: ispreg.h,v 1.8 2000/07/06 05:31:49 mjacob Exp $ */
/*
* Machine Independent (well, as best as possible) register
* definitions for Qlogic ISP SCSI adapters.
@@ -225,6 +225,9 @@
#define INT_PENDING(isp, isr) (IS_FC(isp)? \
((isr & BIU2100_ISR_RISC_INT) != 0) : ((isr & BIU_ISR_RISC_INT) != 0))
+#define INT_PENDING_MASK(isp) \
+ (IS_FC(isp)? BIU2100_ISR_RISC_INT: BIU_ISR_RISC_INT)
+
/* BUS SEMAPHORE REGISTER */
#define BIU_SEMA_STATUS 0x0002 /* Semaphore Status Bit */
#define BIU_SEMA_LOCK 0x0001 /* Semaphore Lock Bit */
@@ -337,10 +340,15 @@
#define OUTMAILBOX6 (MBOX_BLOCK+0xC)
#define OUTMAILBOX7 (MBOX_BLOCK+0xE)
-#define OMBOX_OFFN(n) (MBOX_BLOCK + (n * 2))
+#define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1))
#define NMBOX(isp) \
(((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \
((isp)->isp_type & ISP_HA_FC))? 8 : 6)
+#define NMBOX_BMASK(isp) \
+ (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \
+ ((isp)->isp_type & ISP_HA_FC))? 0xff : 0x3f)
+
+#define MAX_MAILBOX 8
/*
* SXP Block Register Offsets
@@ -699,26 +707,26 @@
/* Offset 5 */
/*
- uint8_t bios_configuration_mode :2;
- uint8_t bios_disable :1;
- uint8_t selectable_scsi_boot_enable :1;
- uint8_t cd_rom_boot_enable :1;
- uint8_t disable_loading_risc_code :1;
- uint8_t enable_64bit_addressing :1;
- uint8_t unused_7 :1;
+ u_int8_t bios_configuration_mode :2;
+ u_int8_t bios_disable :1;
+ u_int8_t selectable_scsi_boot_enable :1;
+ u_int8_t cd_rom_boot_enable :1;
+ u_int8_t disable_loading_risc_code :1;
+ u_int8_t enable_64bit_addressing :1;
+ u_int8_t unused_7 :1;
*/
/* Offsets 6, 7 */
/*
- uint8_t boot_lun_number :5;
- uint8_t scsi_bus_number :1;
- uint8_t unused_6 :1;
- uint8_t unused_7 :1;
- uint8_t boot_target_number :4;
- uint8_t unused_12 :1;
- uint8_t unused_13 :1;
- uint8_t unused_14 :1;
- uint8_t unused_15 :1;
+ u_int8_t boot_lun_number :5;
+ u_int8_t scsi_bus_number :1;
+ u_int8_t unused_6 :1;
+ u_int8_t unused_7 :1;
+ u_int8_t boot_target_number :4;
+ u_int8_t unused_12 :1;
+ u_int8_t unused_13 :1;
+ u_int8_t unused_14 :1;
+ u_int8_t unused_15 :1;
*/
#define ISP1080_NVRAM_HBA_ENABLE(c) ISPBSMX(c, 16, 3, 0x01)
@@ -887,7 +895,7 @@
#define ISP2100_NVRAM_RETRY_COUNT(c) (c)[16]
#define ISP2100_NVRAM_RETRY_DELAY(c) (c)[17]
-#define ISP2100_NVRAM_NODE_NAME(c) (\
+#define ISP2100_NVRAM_PORT_NAME(c) (\
(((u_int64_t)(c)[18]) << 56) | \
(((u_int64_t)(c)[19]) << 48) | \
(((u_int64_t)(c)[20]) << 40) | \
@@ -896,8 +904,19 @@
(((u_int64_t)(c)[23]) << 16) | \
(((u_int64_t)(c)[24]) << 8) | \
(((u_int64_t)(c)[25]) << 0))
+
#define ISP2100_NVRAM_HARDLOOPID(c) (c)[26]
+#define ISP2100_NVRAM_NODE_NAME(c) (\
+ (((u_int64_t)(c)[30]) << 56) | \
+ (((u_int64_t)(c)[31]) << 48) | \
+ (((u_int64_t)(c)[32]) << 40) | \
+ (((u_int64_t)(c)[33]) << 32) | \
+ (((u_int64_t)(c)[34]) << 24) | \
+ (((u_int64_t)(c)[35]) << 16) | \
+ (((u_int64_t)(c)[36]) << 8) | \
+ (((u_int64_t)(c)[37]) << 0))
+
#define ISP2100_NVRAM_HBA_OPTIONS(c) (c)[70]
#define ISP2100_NVRAM_HBA_DISABLE(c) ISPBSMX(c, 70, 0, 0x01)
#define ISP2100_NVRAM_BIOS_DISABLE(c) ISPBSMX(c, 70, 1, 0x01)
diff --git a/sys/dev/ic/ispvar.h b/sys/dev/ic/ispvar.h
index 09043ba3b11..b87c8e8d1e1 100644
--- a/sys/dev/ic/ispvar.h
+++ b/sys/dev/ic/ispvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ispvar.h,v 1.10 2000/04/06 05:47:00 mjacob Exp $ */
+/* $OpenBSD: ispvar.h,v 1.11 2000/07/06 05:31:49 mjacob Exp $ */
/*
* Soft Definitions for for Qlogic ISP SCSI adapters.
*
@@ -59,7 +59,7 @@
#endif
#define ISP_CORE_VERSION_MAJOR 1
-#define ISP_CORE_VERSION_MINOR 13
+#define ISP_CORE_VERSION_MINOR 16
/*
* Vector for bus specific code to provide specific services.
@@ -76,7 +76,7 @@ struct ispmdvec {
void (*dv_reset0) __P((struct ispsoftc *));
void (*dv_reset1) __P((struct ispsoftc *));
void (*dv_dregs) __P((struct ispsoftc *));
- const u_int16_t *dv_ispfw; /* ptr to f/w */
+ const u_int16_t *dv_ispfw; /* ptr to f/w */
u_int16_t dv_fwlen; /* length of f/w */
u_int16_t dv_codeorg; /* code ORG for f/w */
u_int32_t dv_fwrev; /* f/w revision */
@@ -95,15 +95,7 @@ struct ispmdvec {
#endif
#define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS)
-#ifdef ISP2100_SCCLUN
-#define _ISP_FC_LUN(isp) 65536
-#else
-#define _ISP_FC_LUN(isp) 16
-#endif
-#define _ISP_SCSI_LUN(isp) \
- ((ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(7, 55, 0))? 32 : 8)
-#define ISP_MAX_LUNS(isp) \
- (IS_FC(isp)? _ISP_FC_LUN(isp) : _ISP_SCSI_LUN(isp))
+#define ISP_MAX_LUNS(isp) (isp)->isp_maxluns
/*
@@ -261,11 +253,11 @@ typedef struct {
*/
struct lportdb {
u_int
- loopid : 8,
- : 4,
- fabdev : 1,
- roles : 2,
- valid : 1;
+ loopid : 8,
+ : 4,
+ loggedin : 1,
+ roles : 2,
+ valid : 1;
u_int32_t portid;
u_int64_t node_wwn;
u_int64_t port_wwn;
@@ -323,12 +315,13 @@ struct ispsoftc {
u_int16_t isp_maxcmds; /* max possible I/O cmds */
u_int8_t isp_type; /* HBA Chip Type */
u_int8_t isp_revision; /* HBA Chip H/W Revision */
+ u_int32_t isp_maxluns; /* maximum luns supported */
u_int32_t : 4,
isp_touched : 1, /* board ever seen? */
isp_fast_mttr : 1, /* fast sram */
isp_bustype : 1, /* SBus or PCI */
- isp_dogactive : 1, /* watchdog running */
+ : 1,
isp_dblev : 8, /* debug level */
isp_clock : 8, /* input clock */
isp_confopts : 8; /* config options */
@@ -337,16 +330,18 @@ struct ispsoftc {
* Volatile state
*/
- volatile u_int32_t : 9,
+ volatile u_int32_t
+ isp_mboxbsy : 8, /* mailbox command active */
+ : 1,
isp_state : 3,
isp_sendmarker : 2, /* send a marker entry */
isp_update : 2, /* update parameters */
isp_nactive : 16; /* how many commands active */
-
volatile u_int16_t isp_reqodx; /* index of last ISP pickup */
volatile u_int16_t isp_reqidx; /* index of next request */
volatile u_int16_t isp_residx; /* index of next result */
volatile u_int16_t isp_lasthdls; /* last handle seed */
+ volatile u_int16_t isp_mboxtmp[MAX_MAILBOX];
/*
* Active commands are stored here, indexed by handle functions.