Update from Matthew Jacob:

Correctly account for F-port vs. F-port (no FLOGI_ACC) topologies.
  Make sure we get a port database entry for the fabric name server.
  Preserve fabric logins if the device didn't change across fabric
  or port database changes, or the device has already logged into
  us (e.g., for target/initiator dual role devices like Veritas
  SANbox). Propagate class 3 service parameter changes where devices
  can change roles.

  Fix all occurrences of setting a sendmarker so that setting it
  for one bus on dual bus cards doesn't wipe a pending sendmarker
  for other busses on the same card :-;.

  Comments added and clarifications made in some of the target mode code.
This commit is contained in:
he 2000-05-13 16:53:03 +00:00
parent dd7aa6db1b
commit 084953b8f7
8 changed files with 369 additions and 193 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: isp.c,v 1.51 2000/02/21 19:18:53 mjacob Exp $ */
/* $NetBSD: isp.c,v 1.52 2000/05/13 16:53:03 he Exp $ */
/*
* Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
* All rights reserved.
@ -1025,7 +1025,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 +1079,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,10 +1235,11 @@ 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, topo = -1;
int count;
u_int8_t lwfs;
fcparam *fcp;
#if defined(ISP2100_FABRIC)
@ -1300,53 +1283,74 @@ isp_fclink_test(isp, waitdelay)
}
fcp->isp_loopid = mbs.param[1];
if (IS_2200(isp)) {
topo = (int) mbs.param[6];
if (topo < 0 || topo > 3)
topo = 0;
int topo = (int) mbs.param[6];
if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
topo = TOPO_PTP_STUB;
fcp->isp_topo = topo;
} else {
topo = 0;
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))
topo = 1;
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[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,
toponames[topo]);
{
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);
}
@ -1364,7 +1368,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);
@ -1384,7 +1388,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
/*
@ -1399,6 +1403,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.
@ -1413,12 +1430,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;
@ -1428,9 +1450,14 @@ 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...).
@ -1503,7 +1530,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;
/*
@ -1556,10 +1583,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
@ -1634,7 +1658,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;
@ -1650,13 +1674,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;
@ -1667,16 +1691,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));
}
/*
@ -1684,16 +1753,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:
@ -1705,49 +1773,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)
continue;
} while (lp->loopid == 0 && loopid < MAX_FC_TARG);
lp->valid = 1;
lp->fabdev = 1;
/*
* If we get here and we haven't set a Loop ID,
* we failed to log into this device.
*/
if (lp->loopid == 0) {
continue;
}
/*
* 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) |
@ -1770,13 +1860,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;
@ -1905,13 +1997,24 @@ ispscsicmd(xs)
fcparam *fcp = isp->isp_param;
struct lportdb *lp;
#if defined(ISP2100_FABRIC)
if (target >= FL_PORT_ID) {
/*
* If we're not on a Fabric, we can't have a target
* above FL_PORT_ID-1. If we're on a fabric, we
* can't have a target less than FC_SNS_ID+1.
*/
if (fcp->isp_onfabric == 0 || target <= FC_SNS_ID) {
/*
* 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.
*/
if (fcp->isp_onfabric == 0) {
if (target >= FL_PORT_ID) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
} else {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
if (fcp->isp_topo == TOPO_F_PORT &&
target < FL_PORT_ID) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
@ -2170,7 +2273,7 @@ isp_control(isp, ctl, arg)
mbs.param[1] = 10;
bus = 0;
}
isp->isp_sendmarker = 1 << bus;
isp->isp_sendmarker |= (1 << bus);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_dumpregs(isp, "isp_control SCSI bus reset failed");
@ -2194,7 +2297,7 @@ isp_control(isp, ctl, arg)
}
PRINTF("%s: Target %d on Bus %d Reset Succeeded\n",
isp->isp_name, tgt, bus);
isp->isp_sendmarker = 1 << bus;
isp->isp_sendmarker |= (1 << bus);
return (0);
case ISPCTL_ABORT_CMD:
@ -2276,17 +2379,14 @@ 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 isr, sema;
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.
* isr isn't set, but sema is.
*/
do {
isr = ISP_READ(isp, BIU_ISR);
isrb = ISP_READ(isp, BIU_ISR);
} while (isr != isrb);
isr = ISP_READ(isp, BIU_ISR);
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) {
@ -2570,7 +2670,7 @@ isp_parse_async(isp, mbox)
case MBOX_COMMAND_COMPLETE: /* sometimes these show up */
break;
case ASYNC_BUS_RESET:
isp->isp_sendmarker = (1 << bus);
isp->isp_sendmarker |= (1 << bus);
#ifdef ISP_TARGET_MODE
isp_target_async(isp, bus, mbox);
#endif
@ -2604,7 +2704,7 @@ isp_parse_async(isp, mbox)
case ASYNC_TIMEOUT_RESET:
PRINTF("%s: timeout initiated SCSI bus reset of bus %d\n",
isp->isp_name, bus);
isp->isp_sendmarker = (1 << bus);
isp->isp_sendmarker |= (1 << bus);
#ifdef ISP_TARGET_MODE
isp_target_async(isp, bus, mbox);
#endif
@ -2612,7 +2712,7 @@ isp_parse_async(isp, mbox)
case ASYNC_DEVICE_RESET:
PRINTF("%s: device reset on bus %d\n", isp->isp_name, bus);
isp->isp_sendmarker = 1 << bus;
isp->isp_sendmarker |= (1 << bus);
#ifdef ISP_TARGET_MODE
isp_target_async(isp, bus, mbox);
#endif
@ -2669,7 +2769,7 @@ isp_parse_async(isp, mbox)
* XXX: Set up to renegotiate again!
*/
/* Can only be for a 1080... */
isp->isp_sendmarker = (1 << bus);
isp->isp_sendmarker |= (1 << bus);
break;
case ASYNC_CMD_CMPLT:
@ -2720,7 +2820,7 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_LOOP_RESET:
isp->isp_sendmarker = 1 << bus;
isp->isp_sendmarker = 1;
((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL;
isp_mark_getpdb_all(isp);
@ -2747,6 +2847,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;
@ -3865,15 +3976,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;
}
@ -3946,7 +4065,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 =
@ -4656,39 +4776,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 =

View File

@ -1,4 +1,4 @@
/* $NetBSD: isp_netbsd.c,v 1.24 2000/03/23 07:01:31 thorpej Exp $ */
/* $NetBSD: isp_netbsd.c,v 1.25 2000/05/13 16:53:03 he Exp $ */
/*
* Platform (NetBSD) dependent common attachment code for Qlogic adapters.
* Matthew Jacob <mjacob@nas.nasa.gov>
@ -101,8 +101,7 @@ isp_attach(isp)
isp->isp_osinfo._link.type = BUS_SCSI;
/*
* Send a SCSI Bus Reset (used to be done as part of attach,
* but now left to the OS outer layers).
* Send a SCSI Bus Reset.
*/
if (IS_SCSI(isp)) {
int bus = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: isp_target.c,v 1.3 2000/02/19 01:50:57 mjacob Exp $ */
/* $NetBSD: isp_target.c,v 1.4 2000/05/13 16:53:04 he Exp $ */
/*
* Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
*
@ -672,6 +672,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 +685,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);
@ -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

View File

@ -1,4 +1,4 @@
/* $NetBSD: isp_target.h,v 1.3 2000/02/19 01:50:25 mjacob Exp $ */
/* $NetBSD: isp_target.h,v 1.4 2000/05/13 16:53:04 he Exp $ */
/*
* Qlogic Target Mode Structure and Flag Definitions
*
@ -186,6 +186,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 +625,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 +637,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
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: isp_tpublic.h,v 1.2 2000/02/19 01:50:03 mjacob Exp $ */
/* $NetBSD: isp_tpublic.h,v 1.3 2000/05/13 16:53:04 he 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;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ispmbox.h,v 1.22 2000/02/19 01:49:47 mjacob Exp $ */
/* $NetBSD: ispmbox.h,v 1.23 2000/05/13 16:53:04 he Exp $ */
/*
* Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
* All rights reserved.
@ -561,7 +561,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];

View File

@ -1,4 +1,4 @@
/* $NetBSD: ispreg.h,v 1.19 2000/02/12 02:28:32 mjacob Exp $ */
/* $NetBSD: ispreg.h,v 1.20 2000/05/13 16:53:04 he Exp $ */
/* release_6_5_99 */
/*
* Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
@ -889,7 +889,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) | \
@ -898,8 +898,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)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ispvar.h,v 1.29 2000/02/12 02:29:00 mjacob Exp $ */
/* $NetBSD: ispvar.h,v 1.30 2000/05/13 16:53:04 he Exp $ */
/*
* Copyright (C) 1999 National Aeronautics & Space Administration
* All rights reserved.
@ -56,7 +56,7 @@
#endif
#define ISP_CORE_VERSION_MAJOR 1
#define ISP_CORE_VERSION_MINOR 12
#define ISP_CORE_VERSION_MINOR 14
/*
* Vector for bus specific code to provide specific services.
@ -228,11 +228,12 @@ typedef struct {
typedef struct {
u_int32_t isp_fwoptions : 16,
: 7,
: 4,
loop_seen_once : 1,
isp_loopstate : 3, /* Current Loop State */
isp_fwstate : 3, /* ISP F/W state */
isp_gotdparms : 1,
isp_topo : 3,
isp_onfabric : 1;
u_int8_t isp_loopid; /* hard loop id */
u_int8_t isp_alpa; /* ALPA */
@ -257,11 +258,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;
@ -288,6 +289,12 @@ typedef struct {
#define LOOP_PDB_RCVD 2
#define LOOP_READY 7
#define TOPO_NL_PORT 0
#define TOPO_FL_PORT 1
#define TOPO_N_PORT 2
#define TOPO_F_PORT 3
#define TOPO_PTP_STUB 4
/*
* Soft Structure per host adapter
*/