diff options
| -rw-r--r-- | sys/dev/isp/isp.c | 209 |
1 files changed, 134 insertions, 75 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 1e3407417f04..f7e0b232be4f 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -203,7 +203,8 @@ isp_reset(isp) DISABLE_INTS(isp); /* - * Put the board into PAUSE mode (so we can read the SXP registers). + * Put the board into PAUSE mode (so we can read the SXP registers + * or write FPM/FBM registers). */ ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); @@ -218,6 +219,14 @@ isp_reset(isp) default: break; } + /* + * While we're paused, reset the FPM module and FBM fifos. + */ + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); + ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); + ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); } else if (IS_1240(isp)) { sdparam *sdp = isp->isp_param; revname = "1240"; @@ -461,6 +470,8 @@ again: */ ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); USEC_DELAY(100); + /* Clear semaphore register (just to be sure) */ + ISP_WRITE(isp, BIU_SEMA, 0); /* * Establish some initial burst rate stuff. @@ -498,6 +509,9 @@ again: #endif } else { ISP_WRITE(isp, RISC_MTR2100, 0x1212); + if (IS_2200(isp)) { + ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE); + } } ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); /* release paused processor */ @@ -729,12 +743,10 @@ isp_init(isp) if (IS_DUALBUS(isp)) { isp_setdfltparm(isp, 1); } - if ((isp->isp_confopts & ISP_CFG_NOINIT) == 0) { - if (IS_FC(isp)) { - isp_fibre_init(isp); - } else { - isp_scsi_init(isp); - } + if (IS_FC(isp)) { + isp_fibre_init(isp); + } else { + isp_scsi_init(isp); } } @@ -751,6 +763,13 @@ isp_scsi_init(isp) sdp_chan1++; } + /* + * If we have no role (neither target nor initiator), return. + */ + if (isp->isp_role == ISP_ROLE_NONE) { + return; + } + /* First do overall per-card settings. */ /* @@ -1012,6 +1031,20 @@ isp_fibre_init(isp) fcp = isp->isp_param; + /* + * Do this *before* initializing the firmware. + */ + isp_mark_getpdb_all(isp); + fcp->isp_fwstate = FW_CONFIG_WAIT; + fcp->isp_loopstate = LOOP_NIL; + + /* + * If we have no role (neither target nor initiator), return. + */ + if (isp->isp_role == ISP_ROLE_NONE) { + return; + } + loopid = DEFAULT_LOOPID(isp); icbp = (isp_icb_t *) fcp->isp_scratch; MEMZERO(icbp, sizeof (*icbp)); @@ -1051,6 +1084,19 @@ isp_fibre_init(isp) * Node Name && Port Names to be distinct. */ + + /* + * Make sure that target role reflects into fwoptions. + */ + if (isp->isp_role & ISP_ROLE_TARGET) { + fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE; + } else { + fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE; + } + + /* + * Propagate all of this into the ICB structure. + */ icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || @@ -1127,13 +1173,10 @@ isp_fibre_init(isp) "isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions); ISP_SWIZZLE_ICB(isp, icbp); + /* - * Do this *before* initializing the firmware. + * Init the firmware */ - isp_mark_getpdb_all(isp); - fcp->isp_fwstate = FW_CONFIG_WAIT; - fcp->isp_loopstate = LOOP_NIL; - mbs.param[0] = MBOX_INIT_FIRMWARE; mbs.param[1] = 0; mbs.param[2] = DMA_MSW(fcp->isp_scdma); @@ -1170,7 +1213,7 @@ isp_mark_getpdb_all(isp) fcparam *fcp = (fcparam *) isp->isp_param; int i; for (i = 0; i < MAX_FC_TARG; i++) { - fcp->portdb[i].valid = 0; + fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0; } } @@ -1353,6 +1396,7 @@ isp_fclink_test(isp, usdelay) fcp->isp_onfabric = 0; if (fcp->isp_topo != TOPO_N_PORT && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { + int loopid = FL_PORT_ID; struct lportdb *lp; if (IS_2100(isp)) { fcp->isp_topo = TOPO_FL_PORT; @@ -1363,7 +1407,7 @@ isp_fclink_test(isp, usdelay) /* * Save the Fabric controller's port database entry. */ - lp = &fcp->portdb[FL_PORT_ID]; + lp = &fcp->portdb[loopid]; lp->node_wwn = (((u_int64_t)pdb.pdb_nodename[0]) << 56) | (((u_int64_t)pdb.pdb_nodename[1]) << 48) | @@ -1387,6 +1431,7 @@ isp_fclink_test(isp, usdelay) lp->portid = BITS2WORD(pdb.pdb_portid_bits); lp->loopid = pdb.pdb_loopid; lp->loggedin = lp->valid = 1; + (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &loopid); isp_register_fc4_type(isp); } else #endif @@ -1480,6 +1525,12 @@ isp_pdb_sync(isp, target) } /* + * make sure the temp port database is clean... + */ + MEMZERO((void *)fcp->tport, sizeof (fcp->tport)); + tport = fcp->tport; + + /* * Run through the local loop ports and get port database info * for each loop ID. * @@ -1487,13 +1538,6 @@ isp_pdb_sync(isp, target) * the wrong database entity- if that happens, just restart (up to * FL_PORT_ID times). */ - tport = fcp->tport; - - /* - * make sure the temp port database is clean... - */ - MEMZERO((void *) tport, sizeof (tport)); - for (lim = loopid = 0; loopid < prange; loopid++) { lp = &tport[loopid]; lp->node_wwn = isp_get_portname(isp, loopid, 1); @@ -1583,7 +1627,7 @@ isp_pdb_sync(isp, target) /* * Mark all of the permanent local loop database entries as invalid. */ - for (loopid = 0; loopid < FL_PORT_ID; loopid++) { + for (loopid = 0; loopid < prange; loopid++) { fcp->portdb[loopid].valid = 0; } @@ -1717,8 +1761,9 @@ isp_pdb_sync(isp, target) * notify the outer layers that they're gone. */ for (lp = fcp->portdb; lp < &fcp->portdb[prange]; lp++) { - if (lp->valid || lp->port_wwn == 0) + if (lp->valid || lp->port_wwn == 0) { continue; + } /* * Tell the outside world we've gone away. @@ -1730,10 +1775,23 @@ isp_pdb_sync(isp, target) #ifdef ISP2100_FABRIC /* + * Find all Fabric Entities that didn't make it from one scan to the + * next and let the world know they went away.. + */ + for (lp = &fcp->portdb[frange]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { + if (lp->was_fabric_dev && lp->fabric_dev == 0) { + loopid = lp - fcp->portdb; + (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &loopid); + MEMZERO((void *) lp, sizeof (*lp)); + continue; + } + lp->was_fabric_dev = lp->fabric_dev; + } + + /* * Now log in any fabric devices */ - for (lp = &fcp->portdb[frange]; - lp < &fcp->portdb[MAX_FC_TARG]; lp++) { + for (lp = &fcp->portdb[frange]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { u_int32_t portid; mbreg_t mbs; @@ -1806,21 +1864,25 @@ isp_pdb_sync(isp, target) * Force a logout if we were logged in. */ 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, MBLOGNONE); + 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; - isp_prt(isp, ISP_LOGINFO, plogout, - (int) (lp - fcp->portdb), lp->loopid, lp->portid); } /* * And log in.... */ loopid = lp - fcp->portdb; - lp->loopid = 0; + lp->loopid = FL_PORT_ID; do { mbs.param[0] = MBOX_FABRIC_LOGIN; mbs.param[1] = loopid << 8; @@ -1868,14 +1930,15 @@ isp_pdb_sync(isp, target) loopid = MAX_FC_TARG; break; } - } while (lp->loopid == 0 && loopid < MAX_FC_TARG); + } 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 == 0) { + if (lp->loopid == FL_PORT_ID) { + lp->loopid = 0; continue; } @@ -1954,17 +2017,21 @@ isp_scan_fabric(isp) struct ispsoftc *isp; { fcparam *fcp = isp->isp_param; - u_int32_t portid, first_nz_portid; + u_int32_t portid, first_portid; sns_screq_t *reqp; sns_scrsp_t *resp; mbreg_t mbs; - int hicap; + int hicap, first_portid_seen; reqp = (sns_screq_t *) fcp->isp_scratch; resp = (sns_scrsp_t *) (&((char *)fcp->isp_scratch)[0x100]); - first_nz_portid = portid = fcp->isp_portid; + /* + * Since Port IDs are 24 bits, we can check against having seen + * anything yet with this value. + */ + first_portid = portid = fcp->isp_portid; - for (hicap = 0; hicap < 1024; hicap++) { + for (first_portid_seen = hicap = 0; hicap < 1024; hicap++) { MEMZERO((void *) reqp, SNS_GAN_REQ_SIZE); reqp->snscb_rblen = SNS_GAN_RESP_SIZE >> 1; reqp->snscb_addr[RQRSP_ADDR0015] = @@ -1993,10 +2060,7 @@ isp_scan_fabric(isp) if (isp_async(isp, ISPASYNC_FABRIC_DEV, resp)) { return (-1); } - if (first_nz_portid == 0 && portid) { - first_nz_portid = portid; - } - if (first_nz_portid == portid) { + if (first_portid == portid) { return (0); } } @@ -2035,7 +2099,7 @@ isp_register_fc4_type(struct ispsoftc *isp) 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"); + isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded"); } } #endif @@ -2061,6 +2125,19 @@ isp_start(xs) XS_INITERR(xs); isp = XS_ISP(xs); + + /* + * Check to make sure we're supporting initiator role. + */ + if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_COMPLETE); + } + + /* + * Now make sure we're running. + */ + if (isp->isp_state != ISP_RUNSTATE) { isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE"); XS_SETERR(xs, HBA_BOTCH); @@ -2329,8 +2406,9 @@ isp_start(xs) } XS_SETERR(xs, HBA_NOERROR); isp_prt(isp, ISP_LOGDEBUG2, - "START cmd for %d.%d.%d cmd 0x%x datalen %d", - XS_CHANNEL(xs), target, XS_LUN(xs), XS_CDBP(xs)[0], XS_XFRLEN(xs)); + "START cmd for %d.%d.%d cmd 0x%x datalen %ld", + XS_CHANNEL(xs), target, XS_LUN(xs), XS_CDBP(xs)[0], + (long) XS_XFRLEN(xs)); ISP_ADD_REQUEST(isp, iptr); isp->isp_nactive++; if (isp->isp_sendmarker) @@ -2459,6 +2537,11 @@ isp_control(isp, ctl, arg) case ISPCTL_TOGGLE_TMODE: { int ena = *(int *)arg; + + /* + * We don't check/set against role here- that's the + * responsibility for the outer layer to coordinate. + */ if (IS_SCSI(isp)) { mbs.param[0] = MBOX_ENABLE_TARGET_MODE; mbs.param[1] = (ena)? ENABLE_TARGET_FLAG : 0; @@ -2466,33 +2549,6 @@ isp_control(isp, ctl, arg) if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { break; } - } else { - fcparam *fcp = isp->isp_param; - /* - * We assume somebody has quiesced this bus. - */ - if (ena) { - if (fcp->isp_fwoptions & ICBOPT_TGT_ENABLE) { - return (0); - } - fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE; - } else { - if (!(fcp->isp_fwoptions & ICBOPT_TGT_ENABLE)) { - return (0); - } - fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE; - } - isp->isp_state = ISP_NILSTATE; - isp_reset(isp); - if (isp->isp_state != ISP_RESETSTATE) { - break; - } - isp_init(isp); - if ((isp->isp_confopts & ISP_CFG_NOINIT) == 0) { - if (isp->isp_state == ISP_INITSTATE) { - isp->isp_state = ISP_RUNSTATE; - } - } } return (0); } @@ -2808,8 +2864,9 @@ isp_intr(arg) XS_SAVE_SENSE(xs, sp); } } - isp_prt(isp, ISP_LOGDEBUG2, "asked for %d got resid %d", - XS_XFRLEN(xs), sp->req_resid); + isp_prt(isp, ISP_LOGDEBUG2, + "asked for %ld got resid %ld", (long) XS_XFRLEN(xs), + (long) sp->req_resid); break; case RQSTYPE_REQUEST: if (sp->req_header.rqs_flags & RQSFLAG_FULL) { @@ -4060,6 +4117,8 @@ isp_mboxcmd(isp, mbp, logmask) isp->isp_mboxtmp[box] = mbp->param[box] = 0; } + isp->isp_lastmbxcmd = opcode; + /* * We assume that we can't overwrite a previous command. */ |
