Use a SNS REGISTER FC4 TYPE subcommand to register with the name server.

This means we should be able to work with McData switches now. Change
ISPASYNC_PDB_CHANGED to ISPASYNC_LOGGED_INOUT (more descriptive). Allow
F-Port topologies to use target ids 0..125 to log into fabric devices.
Yet again fool around with defaul WWN stuff.
This commit is contained in:
mjacob 2001-01-09 18:54:06 +00:00
parent 12a0ea436c
commit 81df08ddef
1 changed files with 108 additions and 39 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: isp.c,v 1.68 2000/12/30 19:47:20 mjacob Exp $ */
/* $NetBSD: isp.c,v 1.69 2001/01/09 18:54:06 mjacob Exp $ */
/*
* This driver, which is contained in NetBSD in the files:
*
@ -150,6 +150,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));
@ -177,7 +178,7 @@ isp_reset(isp)
{
mbreg_t mbs;
int loops, i, touched, dodnld = 1;
char *revname;
char *revname = "????";
isp->isp_state = ISP_NILSTATE;
@ -1413,19 +1414,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;
}
@ -1482,7 +1476,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
/*
@ -1500,12 +1494,14 @@ 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:
frange = FC_SNS_ID+1;
prange = 2;
break;
default:
frange = FC_SNS_ID+1;
prange = FL_PORT_ID;
break;
}
@ -1740,7 +1736,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);
}
/*
@ -1755,7 +1751,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));
}
@ -1763,27 +1759,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) {
@ -1944,7 +1952,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:
@ -2024,6 +2032,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.
@ -2079,9 +2120,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) {
@ -2093,7 +2138,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);
@ -2470,10 +2515,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);
}
@ -3064,16 +3110,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:
@ -4291,6 +4337,8 @@ isp_setdfltparm(isp, channel)
if (IS_FC(isp)) {
fcparam *fcp = (fcparam *) isp->isp_param;
int nvfail;
fcp += channel;
if (fcp->isp_gotdparms) {
return;
@ -4322,19 +4370,40 @@ 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;
}
fcp->isp_nodewwn = ISP_NODEWWN(isp);
fcp->isp_portwwn = ISP_PORTWWN(isp);
return;
}