?? isp.c
字號:
(((u_int64_t)(mbs.param[3] >> 8)) << 32) | (((u_int64_t)(mbs.param[6] & 0xff)) << 24) | (((u_int64_t)(mbs.param[6] >> 8)) << 16) | (((u_int64_t)(mbs.param[7] & 0xff)) << 8) | (((u_int64_t)(mbs.param[7] >> 8))); } return (wwn);}/* * Make sure we have good FC link and know our Loop ID. */static intisp_fclink_test(struct ispsoftc *isp, int usdelay){ static char *toponames[] = { "Private Loop", "FL Port", "N-Port to N-Port", "F Port", "F Port (no FLOGI_ACC response)" }; mbreg_t mbs; int count, check_for_fabric; u_int8_t lwfs; fcparam *fcp; struct lportdb *lp; isp_pdb_t pdb; fcp = isp->isp_param; /* * XXX: Here is where we would start a 'loop dead' timeout */ /* * Wait up to N microseconds for F/W to go to a ready state. */ lwfs = FW_CONFIG_WAIT; count = 0; while (count < usdelay) { u_int64_t enano; u_int32_t wrk; NANOTIME_T hra, hrb; GET_NANOTIME(&hra); isp_fw_state(isp); if (lwfs != fcp->isp_fwstate) { isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>", isp2100_fw_statename((int)lwfs), isp2100_fw_statename((int)fcp->isp_fwstate)); lwfs = fcp->isp_fwstate; } if (fcp->isp_fwstate == FW_READY) { break; } GET_NANOTIME(&hrb); /* * Get the elapsed time in nanoseconds. * Always guaranteed to be non-zero. */ enano = NANOTIME_SUB(&hrb, &hra); isp_prt(isp, ISP_LOGDEBUG1, "usec%d: 0x%lx->0x%lx enano 0x%x%08x", count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb), (u_int32_t)(enano >> 32), (u_int32_t)(enano & 0xffffffff)); /* * If the elapsed time is less than 1 millisecond, * delay a period of time up to that millisecond of * waiting. * * 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. */ if (enano < (1000 * 1000)) { count += 1000; enano = (1000 * 1000) - enano; while (enano > (u_int64_t) 4000000000U) { USEC_SLEEP(isp, 4000000); enano -= (u_int64_t) 4000000000U; } wrk = enano; wrk /= 1000; USEC_SLEEP(isp, wrk); } else { while (enano > (u_int64_t) 4000000000U) { count += 4000000; enano -= (u_int64_t) 4000000000U; } wrk = enano; count += (wrk / 1000); } } /* * If we haven't gone to 'ready' state, return. */ if (fcp->isp_fwstate != FW_READY) { return (-1); } /* * Get our Loop ID (if possible). We really need to have it. */ mbs.param[0] = MBOX_GET_LOOP_ID; isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return (-1); } fcp->isp_loopid = mbs.param[1]; if (IS_2200(isp) || IS_23XX(isp)) { 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; } fcp->isp_portid = fcp->isp_alpa = mbs.param[2] & 0xff; /* * Check to see if we're on a fabric by trying to see if we * can talk to the fabric name server. This can be a bit * tricky because if we're a 2100, we should check always * (in case we're connected to an server doing aliasing). */ fcp->isp_onfabric = 0; if (IS_2100(isp)) check_for_fabric = 1; else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) check_for_fabric = 1; else check_for_fabric = 0; if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { int loopid = FL_PORT_ID; if (IS_2100(isp)) { fcp->isp_topo = TOPO_FL_PORT; } if (BITS2WORD(pdb.pdb_portid_bits) == 0) { /* * Crock. */ fcp->isp_topo = TOPO_NL_PORT; goto not_on_fabric; } fcp->isp_portid = mbs.param[2] | ((int) mbs.param[3] << 16); /* * Save the Fabric controller's port database entry. */ lp = &fcp->portdb[loopid]; 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; fcp->isp_onfabric = 1; (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); isp_register_fc4_type(isp); } else {not_on_fabric: fcp->isp_onfabric = 0; fcp->portdb[FL_PORT_ID].valid = 0; } fcp->isp_gbspeed = 1; if (IS_23XX(isp)) { mbs.param[0] = MBOX_GET_SET_DATA_RATE; mbs.param[1] = MBGSD_GET_RATE; /* mbs.param[2] undefined if we're just getting rate */ isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { if (mbs.param[1] == MBGSD_TWOGB) { isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s"); fcp->isp_gbspeed = 2; } } } isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_loopid, fcp->isp_alpa, fcp->isp_portid, fcp->isp_loopstate, toponames[fcp->isp_topo]); /* * Announce ourselves, too. This involves synthesizing an entry. */ if (fcp->isp_iid_set == 0) { fcp->isp_iid_set = 1; fcp->isp_iid = fcp->isp_loopid; lp = &fcp->portdb[fcp->isp_iid]; } else { lp = &fcp->portdb[fcp->isp_iid]; if (fcp->isp_portid != lp->portid || fcp->isp_loopid != lp->loopid || fcp->isp_nodewwn != ISP_NODEWWN(isp) || fcp->isp_portwwn != ISP_PORTWWN(isp)) { lp->valid = 0; count = fcp->isp_iid; (void) isp_async(isp, ISPASYNC_PROMENADE, &count); } } lp->loopid = fcp->isp_loopid; lp->portid = fcp->isp_portid; lp->node_wwn = ISP_NODEWWN(isp); lp->port_wwn = ISP_PORTWWN(isp); switch (isp->isp_role) { case ISP_ROLE_NONE: lp->roles = 0; break; case ISP_ROLE_TARGET: lp->roles = SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT; break; case ISP_ROLE_INITIATOR: lp->roles = SVC3_INI_ROLE >> SVC3_ROLE_SHIFT; break; case ISP_ROLE_BOTH: lp->roles = (SVC3_INI_ROLE|SVC3_TGT_ROLE) >> SVC3_ROLE_SHIFT; break; } lp->loggedin = lp->valid = 1; count = fcp->isp_iid; (void) isp_async(isp, ISPASYNC_PROMENADE, &count); return (0);}static char *isp2100_fw_statename(int state){ switch(state) { case FW_CONFIG_WAIT: return "Config Wait"; case FW_WAIT_AL_PA: return "Waiting for AL_PA"; case FW_WAIT_LOGIN: return "Wait Login"; case FW_READY: return "Ready"; case FW_LOSS_OF_SYNC: return "Loss Of Sync"; case FW_ERROR: return "Error"; case FW_REINIT: return "Re-Init"; case FW_NON_PART: return "Nonparticipating"; default: return "?????"; }}/* * Synchronize our soft copy of the port database with what the f/w thinks * (with a view toward possibly for a specific target....) */static intisp_pdb_sync(struct ispsoftc *isp){ struct lportdb *lp; fcparam *fcp = isp->isp_param; isp_pdb_t pdb; int loopid, base, lim; /* * Make sure we're okay for doing this right now. */ if (fcp->isp_loopstate != LOOP_PDB_RCVD && fcp->isp_loopstate != LOOP_FSCAN_DONE && fcp->isp_loopstate != LOOP_LSCAN_DONE) { return (-1); } if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT || fcp->isp_topo == TOPO_N_PORT) { if (fcp->isp_loopstate < LOOP_LSCAN_DONE) { if (isp_scan_loop(isp) != 0) { return (-1); } } } fcp->isp_loopstate = LOOP_SYNCING_PDB; /* * If we get this far, we've settled our differences with the f/w * (for local loop device) and we can say that the loop state is ready. */ if (fcp->isp_topo == TOPO_NL_PORT) { fcp->loop_seen_once = 1; fcp->isp_loopstate = LOOP_READY; return (0); } /* * Find all Fabric Entities that didn't make it from one scan to the * next and let the world know they went away. Scan the whole database. */ for (lp = &fcp->portdb[0]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { if (lp->was_fabric_dev && lp->fabric_dev == 0) { loopid = lp - fcp->portdb; lp->valid = 0; /* should already be set */ (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); MEMZERO((void *) lp, sizeof (*lp)); continue; } lp->was_fabric_dev = lp->fabric_dev; } if (fcp->isp_topo == TOPO_FL_PORT) base = FC_SNS_ID+1; else base = 0; if (fcp->isp_topo == TOPO_N_PORT) lim = 1; else lim = MAX_FC_TARG; /* * Now log in any fabric devices that the outer layer has * left for us to see. This seems the most sane policy * for the moment. */ for (lp = &fcp->portdb[base]; lp < &fcp->portdb[lim]; 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) { continue; } /* * Don't try to log into yourself. */ 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) { 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->force_logout == 0) { lp->loggedin = lp->valid = 1; isp_prt(isp, ISP_LOGCONFIG, lretained, (int) (lp - fcp->portdb), (int) lp->loopid, lp->portid); continue; } } lp->force_logout = 0; if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_SYNCING_PDB) { return (-1); } /* * Force a logout if we were logged in. */ if (lp->loggedin) { if (isp_getpdb(isp, lp->loopid, &pdb) == 0) { mbs.param[0] = MBOX_FABRIC_LOGOUT; mbs.param[1] = lp->loopid << 8; mbs.param[2] = 0; mbs.param[3] = 0; isp_mboxcmd(isp, &mbs, MBLOGNONE); lp->loggedin = 0; isp_prt(isp, ISP_LOGINFO, plogout, (int) (lp - fcp->portdb), lp->loopid, lp->portid); } lp->loggedin = 0; if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_SYNCING_PDB) { return (-1); } } /* * And log in.... */ loopid = lp - fcp->portdb; lp->loopid = FL_PORT_ID; 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) || IS_23XX(isp)) { /* only issue a PLOGI if not logged in */ mbs.param[1] |= 0x1; } isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED | MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR)); if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_SYNCING_PDB) { return (-1); } switch (mbs.param[0]) { case MBOX_LOOP_ID_USED: /* * Try the next available loop id. */ loopid++; break; case MBOX_PORT_ID_USED: /* * This port is already logged in. * Snaffle the loop id it's using if it's * nonzero, otherwise we're hosed. */ if (mbs.param[1] != 0) { loopid = mbs.param[1]; isp_prt(isp, ISP_LOGINFO, retained, loopid, (int) (lp - fcp->portdb), lp->portid); } else { loopid = MAX_FC_TARG; break; } /* FALLTHROUGH */ case MBOX_COMMAND_COMPLETE: lp->loggedin = 1; lp->loopid = loopid;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -