?? isp.c
字號:
break; case MBOX_COMMAND_ERROR: isp_prt(isp, ISP_LOGINFO, plogierr, portid, mbs.param[1]); /* FALLTHROUGH */ case MBOX_ALL_IDS_USED: /* We're outta IDs */ default: loopid = MAX_FC_TARG; break; } } while (lp->loopid == FL_PORT_ID && loopid < MAX_FC_TARG); /* * If we get here and we haven't set a Loop ID, * we failed to log into this device. */ if (lp->loopid == FL_PORT_ID) { lp->loopid = 0; continue; } /* * Make sure we can get the approriate port information. */ if (isp_getpdb(isp, lp->loopid, &pdb) != 0) { isp_prt(isp, ISP_LOGWARN, nopdb, lp->portid); goto dump_em; } if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_SYNCING_PDB) { return (-1); } if (pdb.pdb_loopid != lp->loopid) { isp_prt(isp, ISP_LOGWARN, pdbmfail1, lp->portid, pdb.pdb_loopid); goto dump_em; } if (lp->portid != (u_int32_t) BITS2WORD(pdb.pdb_portid_bits)) { isp_prt(isp, ISP_LOGWARN, pdbmfail2, lp->portid, BITS2WORD(pdb.pdb_portid_bits)); goto dump_em; } lp->roles = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; 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])); /* * 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_PROMENADE, &loopid); continue; }dump_em: lp->valid = 0; isp_prt(isp, ISP_LOGINFO, ldumped, loopid, 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, MBLOGNONE); if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_SYNCING_PDB) { return (-1); } } /* * If we get here, we've for sure seen not only a valid loop * but know what is or isn't on it, so mark this for usage * in isp_start. */ fcp->loop_seen_once = 1; fcp->isp_loopstate = LOOP_READY; return (0);}static intisp_scan_loop(struct ispsoftc *isp){ struct lportdb *lp; fcparam *fcp = isp->isp_param; isp_pdb_t pdb; int loopid, lim, hival; switch (fcp->isp_topo) { case TOPO_NL_PORT: hival = FL_PORT_ID; break; case TOPO_N_PORT: hival = 2; break; case TOPO_FL_PORT: hival = FC_PORT_ID; break; default: fcp->isp_loopstate = LOOP_LSCAN_DONE; return (0); } fcp->isp_loopstate = LOOP_SCANNING_LOOP; /* * make sure the temp port database is clean... */ MEMZERO((void *)fcp->tport, sizeof (fcp->tport)); /* * Run through the local loop ports and get port database info * for each loop ID. * * There's a somewhat unexplained situation where the f/w passes back * the wrong database entity- if that happens, just restart (up to * FL_PORT_ID times). */ for (lim = loopid = 0; loopid < hival; loopid++) { lp = &fcp->tport[loopid]; /* * Don't even try for ourselves... */ if (loopid == fcp->isp_loopid) continue; lp->node_wwn = isp_get_portname(isp, loopid, 1); if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) return (-1); if (lp->node_wwn == 0) continue; lp->port_wwn = isp_get_portname(isp, loopid, 0); if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) return (-1); if (lp->port_wwn == 0) { lp->node_wwn = 0; continue; } /* * Get an entry.... */ if (isp_getpdb(isp, loopid, &pdb) != 0) { if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) return (-1); continue; } if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) { return (-1); } /* * If the returned database element doesn't match what we * asked for, restart the process entirely (up to a point...). */ if (pdb.pdb_loopid != loopid) { loopid = 0; if (lim++ < hival) { continue; } isp_prt(isp, ISP_LOGWARN, "giving up on synchronizing the port database"); return (-1); } /* * Save the pertinent info locally. */ 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; } /* * Mark all of the permanent local loop database entries as invalid * (except our own entry). */ for (loopid = 0; loopid < hival; loopid++) { if (loopid == fcp->isp_iid) { fcp->portdb[loopid].valid = 1; fcp->portdb[loopid].loopid = fcp->isp_loopid; continue; } fcp->portdb[loopid].valid = 0; } /* * 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 < hival; loopid++) { int i; /* * If we don't have a non-zero Port WWN, we're not here. */ if (fcp->tport[loopid].port_wwn == 0) { continue; } /* * Skip ourselves. */ if (loopid == fcp->isp_iid) { continue; } /* * For the purposes of deciding whether this is the * 'same' device or not, we only search for an identical * Port WWN. Node WWNs may or may not be the same as * the Port WWN, and there may be multiple different * Port WWNs with the same Node WWN. It would be chaos * to have multiple identical Port WWNs, so we don't * allow that. */ for (i = 0; i < hival; i++) { int j; if (fcp->portdb[i].port_wwn == 0) continue; if (fcp->portdb[i].port_wwn != fcp->tport[loopid].port_wwn) continue; /* * We found this WWN elsewhere- it's changed * loopids then. We don't change it's actual * position in our cached port database- we * just change the actual loop ID we'd use. */ if (fcp->portdb[i].loopid != loopid) { isp_prt(isp, ISP_LOGINFO, portshift, i, fcp->portdb[i].loopid, fcp->portdb[i].portid, loopid, fcp->tport[loopid].portid); } fcp->portdb[i].portid = fcp->tport[loopid].portid; fcp->portdb[i].loopid = loopid; fcp->portdb[i].valid = 1; fcp->portdb[i].roles = fcp->tport[loopid].roles; /* * Now make sure this Port WWN doesn't exist elsewhere * in the port database. */ for (j = i+1; j < hival; j++) { if (fcp->portdb[i].port_wwn != fcp->portdb[j].port_wwn) { continue; } isp_prt(isp, ISP_LOGWARN, portdup, j, i); /* * Invalidate the 'old' *and* 'new' ones. * This is really harsh and not quite right, * but if this happens, we really don't know * who is what at this point. */ fcp->portdb[i].valid = 0; fcp->portdb[j].valid = 0; } break; } /* * If we didn't traverse the entire port database, * then we found (and remapped) an existing entry. * No need to notify anyone- go for the next one. */ if (i < hival) { isp_prt(isp, ISP_LOGINFO, retained, fcp->portdb[i].loopid, i, fcp->portdb[i].portid); continue; } /* * We've not found this Port WWN anywhere. It's a new entry. * See if we can leave it where it is (with target == loopid). */ if (fcp->portdb[loopid].port_wwn != 0) { for (lim = 0; lim < hival; lim++) { if (fcp->portdb[lim].port_wwn == 0) break; } /* "Cannot Happen" */ if (lim == hival) { isp_prt(isp, ISP_LOGWARN, "Remap Overflow"); continue; } i = lim; } else { i = loopid; } /* * NB: The actual loopid we use here is loopid- we may * in fact be at a completely different index (target). */ fcp->portdb[i].loopid = loopid; fcp->portdb[i].port_wwn = fcp->tport[loopid].port_wwn; fcp->portdb[i].node_wwn = fcp->tport[loopid].node_wwn; fcp->portdb[i].roles = fcp->tport[loopid].roles; fcp->portdb[i].portid = fcp->tport[loopid].portid; fcp->portdb[i].valid = 1; /* * Tell the outside world we've arrived. */ (void) isp_async(isp, ISPASYNC_PROMENADE, &i); } /* * Now find all previously used targets that are now invalid and * notify the outer layers that they're gone. */ for (lp = &fcp->portdb[0]; lp < &fcp->portdb[hival]; lp++) { if (lp->valid || lp->port_wwn == 0) { continue; } /* * Tell the outside world we've gone * away and erase our pdb entry. * */ loopid = lp - fcp->portdb; (void) isp_async(isp, ISPASYNC_PROMENADE, &loopid); MEMZERO((void *) lp, sizeof (*lp)); } fcp->isp_loopstate = LOOP_LSCAN_DONE; return (0);}static intisp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp){ isp_mboxcmd(isp, mbp, MBLOGNONE); if (mbp->param[0] != MBOX_COMMAND_COMPLETE) { if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) { FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; } if (mbp->param[0] == MBOX_COMMAND_ERROR) { char tbuf[16]; char *m; switch (mbp->param[1]) { case 1: m = "No Loop"; break; case 2: m = "Failed to allocate IOCB buffer"; break; case 3: m = "Failed to allocate XCB buffer"; break; case 4: m = "timeout or transmit failed"; break; case 5: m = "no fabric loop"; break; case 6: m = "remote device not a target"; break; default: SNPRINTF(tbuf, sizeof tbuf, "%x", mbp->param[1]); m = tbuf; break; } isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m); } return (-1); } if (FCPARAM(isp)->isp_fwstate != FW_READY || FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) { return (-1); } return(0);}#ifdef ISP_USE_GA_NXTstatic intisp_scan_fabric(struct ispsoftc *isp, int ftype){ fcparam *fcp = isp->isp_param; u_int32_t portid, first_portid, last_portid; int hicap, last_port_same; if (fcp->isp_onfabric == 0) { fcp->isp_loopstate = LOOP_FSCAN_DONE; return (0); } FC_SCRATCH_ACQUIRE(isp); /* * Since Port IDs are 24 bits, we can check against having seen * anything yet with this value. */ last_port_same = 0; last_portid = 0xffffffff; /* not a port */ first_portid = portid = fcp->isp_portid; fcp->isp_loopstate = LOOP_SCANNING_FABRIC; for (hicap = 0; hicap < GA_NXT_MAX; hicap++) { mbreg_t mbs; sns_screq_t *rq; sns_ga_nxt_rsp_t *rs0, *rs1; struct lportdb lcl; u_int8_t sc[SNS_GA_NXT_RESP_SIZE]; rq = (sns_screq_t *)sc; MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE); rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1; rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100); rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100); rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100); rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100); rq->snscb_sblen = 6; rq->snscb_data[0] = SNS_GA_NXT; rq->snscb_data[4] = portid & 0xffff; rq->snscb_data[5] = (portid >> 16) & 0xff; isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch); MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); /* * Leave 4 and 5 alone */ mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); if (isp_fabric_mbox_cmd(isp, &mbs)) { if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) { fcp->isp_loopstate = LOOP_PDB_RCVD; } FC_SCRATCH_RELEASE(isp); return (-1); } MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE); rs1 = (sns_ga_nxt_rsp_t *) sc; rs0 = (sns_ga_nxt_
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -