summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-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.