From 6d1d7d4c873d3c85566964baceefd79ad9195acb Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Tue, 9 May 2000 01:14:43 +0000 Subject: [PATCH] Fix some breakage about how we build WWNs. Do some other fabric related changes: consider a new PDB entry different if Class 3 service parameter roles change (!!!). Do some checking as we're getting a port database that traps whether things change while we're doing so. Handle N-port and F-ports correctly. Fix the fabric login loop to retain a login/binding if things haven't changed (I mean, why logout a device only to log it back in). No longer accept, after fabric logins, garbage if we can't get a PDB entry that matches the device we've just logged into- if it doesn't, log it out as it is very unlikely to still be what we thought it was. Get rid of some of the debounce loops because we could get stuck there. --- sys/dev/isp/isp.c | 385 +++++++++++++++++++++++++++++----------------- 1 file changed, 248 insertions(+), 137 deletions(-) diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 9658f6ebd4ee..a33ae5d759a7 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -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,7 +1235,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 +1283,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 +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); @@ -1385,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 /* @@ -1400,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. @@ -1414,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; @@ -1429,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...). @@ -1504,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; /* @@ -1557,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 @@ -1635,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; @@ -1651,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; @@ -1668,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)); } /* @@ -1685,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: @@ -1706,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) | @@ -1771,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; @@ -2288,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. + * If we've disabled interrupts, we may get a case where + * 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) { @@ -2759,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; @@ -3877,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; } @@ -3958,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 = @@ -4668,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 =