summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authormjacob <mjacob@cvs.openbsd.org>2001-01-09 03:26:19 +0000
committermjacob <mjacob@cvs.openbsd.org>2001-01-09 03:26:19 +0000
commit3b18fa22dba8c7eb2142e175986d94e2ba76edae (patch)
treeea9d3d522ca4591520dc6b98c0906edc1a70c36c /sys/dev/ic
parent60bb69464a7dfbd8ebd85dffe08e7b0d82e0bff8 (diff)
Make some strings constant (from Bill Sommerfeld @ NetBSD). Clean up some
wwn handling. Do a Register FC4 Type (so that we can work with McData switches). Allow F-port topologies to use the target range 0..125 for logging in fabric devices. We changed ISPASYNC_PDB_CHANGED to ISPASYNC_LOGGED_INOUT and now use ISPASYNC_CHANGE_NOTIFY for both loop && fabric events.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/isp.c213
1 files changed, 142 insertions, 71 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c
index ef4c101a4dd..727e1d6e654 100644
--- a/sys/dev/ic/isp.c
+++ b/sys/dev/ic/isp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp.c,v 1.18 2000/12/06 01:07:21 mjacob Exp $ */
+/* $OpenBSD: isp.c,v 1.19 2001/01/09 03:26:18 mjacob Exp $ */
/*
* Machine and OS Independent (well, as best as possible)
* code for the Qlogic ISP SCSI adapters.
@@ -64,43 +64,43 @@
/*
* Local static data
*/
-static char *warnlun =
+static const char warnlun[] =
"WARNING- cannot determine Expanded LUN capability- limiting to one LUN";
-static char *portshift =
+static const char portshift[] =
"Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)";
-static char *portdup =
+static const char portdup[] =
"Target %d duplicates Target %d- killing off both";
-static char *retained =
+static const char retained[] =
"Retaining Loop ID 0x%x for Target %d (Port 0x%x)";
#ifdef ISP2100_FABRIC
-static char *lretained =
+static const char lretained[] =
"Retained login of Target %d (Loop ID 0x%x) Port 0x%x";
-static char *plogout =
+static const char plogout[] =
"Logging out Target %d at Loop ID 0x%x (Port 0x%x)";
-static char *plogierr =
+static const char plogierr[] =
"Command Error in PLOGI for Port 0x%x (0x%x)";
-static char *nopdb =
+static const char nopdb[] =
"Could not get PDB for Device @ Port 0x%x";
-static char *pdbmfail1 =
+static const char pdbmfail1[] =
"PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)";
-static char *pdbmfail2 =
+static const char pdbmfail2[] =
"PDB Port info for Device @ Port 0x%x does not match up (0x%x)";
-static char *ldumped =
+static const char ldumped[] =
"Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch";
#endif
-static char *notresp =
+static const char notresp[] =
"Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
-static char *xact1 =
+static const char xact1[] =
"HBA attempted queued transaction with disconnect not set for %d.%d.%d";
-static char *xact2 =
+static const char xact2[] =
"HBA attempted queued transaction to target routine %d on target %d bus %d";
-static char *xact3 =
+static const char xact3[] =
"HBA attempted queued cmd for %d.%d.%d when queueing disabled";
-static char *pskip =
+static const char pskip[] =
"SCSI phase skipped for target %d.%d.%d";
-static char *topology =
+static const char topology[] =
"Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'";
-static char *finmsg =
+static const char finmsg[] =
"(%d.%d.%d): FIN dl%d resid%d STS 0x%x SKEY %c XS_ERR=0x%x";
/*
* Local function prototypes.
@@ -123,6 +123,7 @@ static int isp_same_lportdb __P((struct lportdb *, struct lportdb *));
static int isp_pdb_sync __P((struct ispsoftc *, int));
#ifdef ISP2100_FABRIC
static int isp_scan_fabric __P((struct ispsoftc *));
+static void isp_register_fc4_type __P((struct ispsoftc *));
#endif
static void isp_fw_state __P((struct ispsoftc *));
static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *, int));
@@ -150,7 +151,7 @@ isp_reset(isp)
{
mbreg_t mbs;
int loops, i, touched, dodnld = 1;
- char *revname;
+ char *revname = "????";
isp->isp_state = ISP_NILSTATE;
@@ -186,7 +187,7 @@ isp_reset(isp)
*/
ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
mbs.param[0] = MBOX_ABOUT_FIRMWARE;
- isp_mboxcmd(isp, &mbs, MBLOGNONE);
+ isp_mboxcmd(isp, &mbs, MBOX_COMMAND_ERROR);
/*
* This *shouldn't* fail.....
*/
@@ -207,13 +208,12 @@ isp_reset(isp)
ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
if (IS_FC(isp)) {
- revname = "2X00";
switch (isp->isp_type) {
case ISP_HA_FC_2100:
- revname[1] = '1';
+ revname = "2100";
break;
case ISP_HA_FC_2200:
- revname[1] = '2';
+ revname = "2200";
break;
default:
break;
@@ -229,7 +229,7 @@ isp_reset(isp)
* XXX: Should probably do some bus sensing.
*/
} else if (IS_ULTRA2(isp)) {
- static char *m = "bus %d is in %s Mode";
+ static const char m[] = "bus %d is in %s Mode";
u_int16_t l;
sdparam *sdp = isp->isp_param;
@@ -729,10 +729,12 @@ isp_init(isp)
if (IS_DUALBUS(isp)) {
isp_setdfltparm(isp, 1);
}
- if (IS_FC(isp)) {
- isp_fibre_init(isp);
- } else {
- isp_scsi_init(isp);
+ if ((isp->isp_confopts & ISP_CFG_NOINIT) == 0) {
+ if (IS_FC(isp)) {
+ isp_fibre_init(isp);
+ } else {
+ isp_scsi_init(isp);
+ }
}
}
@@ -1288,16 +1290,16 @@ isp_fclink_test(isp, usdelay)
*/
enano = NANOTIME_SUB(&hrb, &hra);
+ isp_prt(isp, ISP_LOGDEBUG3, "usec%d: 0x%lx->0x%lx enano %lu",
+ count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb),
+ (enano > ((u_int64_t)0xffffffff))? 0xffffffff :
+ (unsigned long) (enano & 0xffffffff));
+
/*
* If the elapsed time is less than 1 millisecond,
* delay a period of time up to that millisecond of
* waiting.
- */
- isp_prt(isp, ISP_LOGDEBUG3, "usec%d: 0x%lx->0x%lx enano %u",
- count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb),
- enano);
-
- /*
+ *
* This peculiar code is an attempt to try and avoid
* invoking u_int64_t math support functions for some
* platforms where linkage is a problem.
@@ -1385,19 +1387,12 @@ isp_fclink_test(isp, usdelay)
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
+ isp_register_fc4_type(isp);
} else
#endif
{
fcp->isp_portid = mbs.param[2];
fcp->isp_onfabric = 0;
-#if 0
- isp->isp_rfabric = 0;
-#endif
fcp->portdb[FL_PORT_ID].valid = 0;
}
@@ -1454,7 +1449,7 @@ isp_pdb_sync(isp, target)
struct lportdb *lp, *tport;
fcparam *fcp = isp->isp_param;
isp_pdb_t pdb;
- int loopid, prange, lim;
+ int loopid, frange, prange, lim;
#ifdef ISP2100_FABRIC
/*
@@ -1472,12 +1467,13 @@ isp_pdb_sync(isp, target)
switch (fcp->isp_topo) {
case TOPO_F_PORT:
case TOPO_PTP_STUB:
- prange = 0;
+ frange = prange = 0;
break;
case TOPO_N_PORT:
prange = 2;
break;
default:
+ frange = FC_SNS_ID+1;
prange = FL_PORT_ID;
break;
}
@@ -1712,7 +1708,7 @@ isp_pdb_sync(isp, target)
/*
* Tell the outside world we've arrived.
*/
- (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &i);
+ (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &i);
}
/*
@@ -1727,7 +1723,7 @@ isp_pdb_sync(isp, target)
* Tell the outside world we've gone away.
*/
loopid = lp - fcp->portdb;
- (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid);
+ (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &loopid);
MEMZERO((void *) lp, sizeof (*lp));
}
@@ -1735,27 +1731,39 @@ isp_pdb_sync(isp, target)
/*
* Now log in any fabric devices
*/
- for (lp = &fcp->portdb[FC_SNS_ID+1];
+ for (lp = &fcp->portdb[frange];
lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
u_int32_t portid;
mbreg_t mbs;
+ loopid = lp - fcp->portdb;
+ if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) {
+ continue;
+ }
+
/*
* Anything here?
*/
- if (lp->port_wwn == 0)
+ if (lp->port_wwn == 0) {
continue;
+ }
/*
* Don't try to log into yourself.
*/
- if ((portid = lp->portid) == fcp->isp_portid)
+ 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..
+ *
+ * Unfortunately, our charming Qlogic f/w has decided to
+ * return a valid port database entry for a fabric device
+ * that has, in fact, gone away. And it hangs trying to
+ * log it out.
*/
if (lp->loggedin &&
isp_getpdb(isp, lp->loopid, &pdb) == 0) {
@@ -1916,7 +1924,7 @@ isp_pdb_sync(isp, target)
if (lp->node_wwn && lp->port_wwn) {
lp->valid = 1;
loopid = lp - fcp->portdb;
- (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid);
+ (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &loopid);
continue;
}
dump_em:
@@ -1996,6 +2004,39 @@ isp_scan_fabric(isp)
*/
return (0);
}
+
+static void
+isp_register_fc4_type(struct ispsoftc *isp)
+{
+ fcparam *fcp = isp->isp_param;
+ sns_screq_t *reqp;
+ mbreg_t mbs;
+
+ reqp = (sns_screq_t *) fcp->isp_scratch;
+ MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE);
+ reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1;
+ reqp->snscb_addr[RQRSP_ADDR0015] = DMA_LSW(fcp->isp_scdma + 0x100);
+ reqp->snscb_addr[RQRSP_ADDR1631] = DMA_MSW(fcp->isp_scdma + 0x100);
+ reqp->snscb_sblen = 22;
+ reqp->snscb_data[0] = SNS_RFT;
+ reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
+ reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
+ reqp->snscb_data[6] = 0x100; /* SCS - FCP */
+#if 0
+ reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */
+#endif
+ ISP_SWIZZLE_SNS_REQ(isp, reqp);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_RFT_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_MSW(fcp->isp_scdma);
+ mbs.param[3] = DMA_LSW(fcp->isp_scdma);
+ mbs.param[6] = 0;
+ mbs.param[7] = 0;
+ isp_mboxcmd(isp, &mbs, MBLOGALL);
+ if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGINFO, "Register FC4 types succeeded");
+ }
+}
#endif
/*
* Start a command. Locking is assumed done in the caller.
@@ -2051,9 +2092,13 @@ isp_start(xs)
#if defined(ISP2100_FABRIC)
/*
* If we're not on a Fabric, we can't have a target
- * above FL_PORT_ID-1. If we're on a fabric and
- * connected as an F-port, we can't have a target
- * less than FC_SNS_ID+1.
+ * above FL_PORT_ID-1.
+ *
+ * If we're on a fabric and *not* connected as an F-port,
+ * we can't have a target less than FC_SNS_ID+1. This
+ * keeps us from having to sort out the difference between
+ * local public loop devices and those which we might get
+ * from a switch's database.
*/
if (fcp->isp_onfabric == 0) {
if (target >= FL_PORT_ID) {
@@ -2065,7 +2110,7 @@ isp_start(xs)
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
- if (fcp->isp_topo == TOPO_F_PORT &&
+ if (fcp->isp_topo != TOPO_F_PORT &&
target < FL_PORT_ID) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
@@ -2442,10 +2487,11 @@ isp_control(isp, ctl, arg)
break;
}
isp_init(isp);
- if (isp->isp_state != ISP_INITSTATE) {
- break;
+ if ((isp->isp_confopts & ISP_CFG_NOINIT) == 0) {
+ if (isp->isp_state == ISP_INITSTATE) {
+ isp->isp_state = ISP_RUNSTATE;
+ }
}
- isp->isp_state = ISP_RUNSTATE;
}
return (0);
}
@@ -2531,7 +2577,7 @@ isp_intr(arg)
int obits, i = 0;
if ((obits = isp->isp_mboxbsy) != 0) {
isp->isp_mboxtmp[i++] = mbox;
- for (i = 1; i < 8; i++) {
+ for (i = 1; i < MAX_MAILBOX; i++) {
if ((obits & (1 << i)) == 0) {
continue;
}
@@ -3036,16 +3082,16 @@ isp_parse_async(isp, mbox)
isp->isp_sendmarker = 1;
FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
isp_mark_getpdb_all(isp);
- isp_prt(isp, ISP_LOGINFO, "Port Database Changed");
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, (void *) 0);
break;
case ASYNC_CHANGE_NOTIFY:
- isp_mark_getpdb_all(isp);
/*
* Not correct, but it will force us to rescan the loop.
*/
FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, NULL);
+ isp_mark_getpdb_all(isp);
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, (void *) 1);
break;
case ASYNC_PTPMODE:
@@ -4263,6 +4309,8 @@ isp_setdfltparm(isp, channel)
if (IS_FC(isp)) {
fcparam *fcp = (fcparam *) isp->isp_param;
+ int nvfail;
+
fcp += channel;
if (fcp->isp_gotdparms) {
return;
@@ -4294,16 +4342,39 @@ isp_setdfltparm(isp, channel)
fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
/*
- * Now try and read NVRAM
+ * Now try and read NVRAM unless told to not do so.
+ * This will set fcparam's isp_nodewwn && isp_portwwn.
*/
- if ((isp->isp_confopts & (ISP_CFG_NONVRAM|ISP_CFG_OWNWWN)) ||
- (isp_read_nvram(isp))) {
- isp_prt(isp, ISP_LOGINFO,
- "Node WWN 0x%08x%08x, Port WWN 0x%08x%08x",
- (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));
+ if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
+ nvfail = isp_read_nvram(isp);
+ if (nvfail)
+ isp->isp_confopts |= ISP_CFG_NONVRAM;
+ } else {
+ nvfail = 1;
+ }
+ /*
+ * Set node && port to override platform set defaults
+ * unless the nvram read failed (or none was done),
+ * or the platform code wants to use what had been
+ * set in the defaults.
+ */
+ if (nvfail || (isp->isp_confopts & ISP_CFG_OWNWWN)) {
+ isp_prt(isp, ISP_LOGCONFIG,
+ "Using Node WWN 0x%08x%08x, Port WWN 0x%08x%08x",
+ (u_int32_t) (DEFAULT_NODEWWN(isp) >> 32),
+ (u_int32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff),
+ (u_int32_t) (DEFAULT_PORTWWN(isp) >> 32),
+ (u_int32_t) (DEFAULT_PORTWWN(isp) & 0xffffffff));
+ isp->isp_confopts |= ISP_CFG_OWNWWN;
+ ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
+ ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
+ } else {
+ /*
+ * We always start out with values derived
+ * from NVRAM or our platform default.
+ */
+ ISP_NODEWWN(isp) = fcp->isp_nodewwn;
+ ISP_PORTWWN(isp) = fcp->isp_portwwn;
}
return;
}