diff options
author | mjacob <mjacob@FreeBSD.org> | 2006-11-02 03:21:32 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2006-11-02 03:21:32 +0000 |
commit | 120271c1a6f4c81a9b617be188799604cfca7bdd (patch) | |
tree | 51750d8ca50a883d32c721be30cbb55cbe2c28c8 /sys/dev/isp/isp_freebsd.c | |
parent | 2904312753a5ab37478b957ab4ad51612d8a6dd9 (diff) | |
download | FreeBSD-src-120271c1a6f4c81a9b617be188799604cfca7bdd.zip FreeBSD-src-120271c1a6f4c81a9b617be188799604cfca7bdd.tar.gz |
Add 4Gb (24XX) support and lay the foundation for a lot of new stuff.
Diffstat (limited to 'sys/dev/isp/isp_freebsd.c')
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 475 |
1 files changed, 238 insertions, 237 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 5e1d8ce..2750969 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$"); MODULE_VERSION(isp, 1); MODULE_DEPEND(isp, cam, 1, 1, 1); int isp_announced = 0; +int isp_fabric_hysteresis = 5; +int isp_loop_down_limit = 300; /* default loop down limit */ +int isp_quickboot_time = 5; /* don't wait more than N secs for loop up */ static d_ioctl_t ispioctl; static void isp_intr_enable(void *); @@ -242,7 +245,7 @@ isp_attach(ispsoftc_t *isp) if (isp->isp_role != ISP_ROLE_NONE) { isp->isp_state = ISP_RUNSTATE; - ENABLE_INTS(isp); + ISP_ENABLE_INTS(isp); } if (isplist == NULL) { isplist = isp; @@ -387,7 +390,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td) case ISP_FC_GETDINFO: { struct isp_fc_device *ifc = (struct isp_fc_device *) addr; - struct lportdb *lp; + fcportdb_t *lp; if (IS_SCSI(isp)) { break; @@ -398,9 +401,9 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td) } ISP_LOCK(isp); lp = &FCPARAM(isp)->portdb[ifc->loopid]; - if (lp->valid) { + if (lp->state == FC_PORTDB_STATE_VALID) { ifc->role = lp->roles; - ifc->loopid = lp->loopid; + ifc->loopid = lp->handle; ifc->portid = lp->portid; ifc->node_wwn = lp->node_wwn; ifc->port_wwn = lp->port_wwn; @@ -566,7 +569,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td) memset(&mbs, 0, sizeof (mbs)); needmarker = retval = 0; loopid = fct->loopid; - if (IS_2KLOGIN(isp) == 0) { + if (FCPARAM(isp)->isp_2klogin == 0) { loopid <<= 8; } switch (fct->action) { @@ -657,10 +660,7 @@ isp_intr_enable(void *arg) { ispsoftc_t *isp = arg; if (isp->isp_role != ISP_ROLE_NONE) { - ENABLE_INTS(isp); -#if 0 - isp->isp_osinfo.intsok = 1; -#endif + ISP_ENABLE_INTS(isp); } /* Release our hook so that the boot can continue. */ config_intrhook_disestablish(&isp->isp_osinfo.ehook); @@ -911,7 +911,7 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb) /* * This is as a good a place as any to check f/w capabilities. */ - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) == 0) { + if (FCPARAM(isp)->isp_tmode == 0) { isp_prt(isp, ISP_LOGERR, "firmware does not support target mode"); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; @@ -921,9 +921,8 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb) * XXX: We *could* handle non-SCCLUN f/w, but we'd have to * XXX: dorks with our already fragile enable/disable code. */ - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { - isp_prt(isp, ISP_LOGERR, - "firmware not SCCLUN capable"); + if (FCPARAM(isp)->isp_sccfw == 0) { + isp_prt(isp, ISP_LOGERR, "firmware not SCCLUN capable"); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; return (-1); } @@ -1280,8 +1279,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) { void *qe; struct ccb_scsiio *cso = &ccb->csio; - uint16_t *hp, save_handle; - uint16_t nxti, optr; + uint32_t nxti, optr, handle; uint8_t local[QENTRY_LEN]; @@ -1303,11 +1301,11 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { ((ct2e_entry_t *)cto)->ct_iid = cso->init_id; } else { cto->ct_iid = cso->init_id; - if (!(FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)) { + if (FCPARAM(isp)->isp_sccfw == 0) { cto->ct_lun = ccb->ccb_h.target_lun; } } @@ -1386,7 +1384,6 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) atp->state = ATPD_STATE_CTIO; } cto->ct_timeout = 10; - hp = &cto->ct_syshandle; } else { ct_entry_t *cto = (ct_entry_t *) local; @@ -1422,10 +1419,9 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) } ccb->ccb_h.flags &= ~CAM_SEND_SENSE; cto->ct_timeout = 10; - hp = &cto->ct_syshandle; } - if (isp_save_xs_tgt(isp, ccb, hp)) { + if (isp_save_xs_tgt(isp, ccb, &handle)) { xpt_print_path(ccb->ccb_h.path); printf("No XFLIST pointers for isp_target_start_ctio\n"); XS_SETERR(ccb, CAM_REQUEUE_REQ); @@ -1442,7 +1438,13 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) * format. */ - save_handle = *hp; + if (IS_FC(isp)) { + ct2_entry_t *cto = (ct2_entry_t *) local; + cto->ct_syshandle = handle; + } else { + ct_entry_t *cto = (ct_entry_t *) local; + cto->ct_syshandle = handle; + } switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) { case CMD_QUEUED: @@ -1457,7 +1459,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) default: break; } - isp_destroy_tgt_handle(isp, save_handle); + isp_destroy_tgt_handle(isp, handle); out: ISPLOCK_2_CAMLOCK(isp); @@ -1478,7 +1480,7 @@ isp_target_putback_atio(union ccb *ccb) { ispsoftc_t *isp; struct ccb_scsiio *cso; - uint16_t nxti, optr; + uint32_t nxti, optr; void *qe; isp = XS_ISP(ccb); @@ -1496,7 +1498,7 @@ isp_target_putback_atio(union ccb *ccb) MEMZERO(at, sizeof (at2_entry_t)); at->at_header.rqs_entry_type = RQSTYPE_ATIO2; at->at_header.rqs_entry_count = 1; - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) { + if (FCPARAM(isp)->isp_sccfw) { at->at_scclun = (uint16_t) ccb->ccb_h.target_lun; } else { at->at_lun = (uint8_t) ccb->ccb_h.target_lun; @@ -1685,7 +1687,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) return (0); } - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) { + if (FCPARAM(isp)->isp_sccfw) { lun = aep->at_scclun; } else { lun = aep->at_lun; @@ -1731,8 +1733,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) lun, tptr->atio_count); if (tptr == &isp->isp_osinfo.tsdflt[0]) { - atiop->ccb_h.target_id = - ((fcparam *)isp->isp_param)->isp_loopid; + atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid; atiop->ccb_h.target_lun = lun; } /* @@ -2004,7 +2005,8 @@ static void isp_poll(struct cam_sim *sim) { ispsoftc_t *isp = cam_sim_softc(sim); - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; ISP_LOCK(isp); if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { @@ -2020,7 +2022,6 @@ isp_watchdog(void *arg) XS_T *xs = arg; ispsoftc_t *isp = XS_ISP(xs); uint32_t handle; - int iok; /* * We've decided this command is dead. Make sure we're not trying @@ -2028,11 +2029,10 @@ isp_watchdog(void *arg) * and seeing whether it's still alive. */ ISP_LOCK(isp); - iok = isp->isp_osinfo.intsok; - isp->isp_osinfo.intsok = 0; handle = isp_find_handle(isp, xs); if (handle) { - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; if (XS_CMD_DONE_P(xs)) { isp_prt(isp, ISP_LOGDEBUG1, @@ -2077,28 +2077,14 @@ isp_watchdog(void *arg) XS_CMD_C_WDOG(xs); isp_done(xs); } else { - uint16_t nxti, optr; - ispreq_t local, *mp= &local, *qe; - XS_CMD_C_WDOG(xs); xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz); - if (isp_getrqentry(isp, &nxti, &optr, (void **) &qe)) { - ISP_UNLOCK(isp); - return; - } XS_CMD_S_GRACE(xs); - MEMZERO((void *) mp, sizeof (*mp)); - mp->req_header.rqs_entry_count = 1; - mp->req_header.rqs_entry_type = RQSTYPE_MARKER; - mp->req_modifier = SYNC_ALL; - mp->req_target = XS_CHANNEL(xs) << 7; - isp_put_request(isp, mp, qe); - ISP_ADD_REQUEST(isp, nxti); + isp->isp_sendmarker |= 1 << XS_CHANNEL(xs); } } else { isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command"); } - isp->isp_osinfo.intsok = iok; ISP_UNLOCK(isp); } @@ -2106,13 +2092,13 @@ static void isp_kthread(void *arg) { ispsoftc_t *isp = arg; + int slp; #if __FreeBSD_version < 500000 int s; s = splcam(); - isp->isp_osinfo.intsok = 1; #else #ifdef ISP_SMPLOCK mtx_lock(&isp->isp_lock); @@ -2125,32 +2111,63 @@ isp_kthread(void *arg) * gotten good fibre channel state. */ for (;;) { - int wasfrozen; + int wasfrozen, lb; isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state"); - while (isp_fc_runstate(isp, 2 * 1000000) != 0) { - isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state ungood"); - if (FCPARAM(isp)->isp_fwstate != FW_READY || - FCPARAM(isp)->isp_loopstate < LOOP_PDB_RCVD) { - if (FCPARAM(isp)->loop_seen_once == 0 || - isp->isp_osinfo.ktmature == 0) { - break; - } + lb = isp_fc_runstate(isp, 250000); + if (lb) { + unsigned int inc = 1; + + if (lb < 0) { + isp_prt(isp, ISP_LOGDEBUG0, + "kthread: FC loop not up (down count %d)", + isp->isp_osinfo.loop_down_time); + } else { + isp_prt(isp, ISP_LOGDEBUG0, + "kthread: FC got to %d (down count %d)", + lb, isp->isp_osinfo.loop_down_time); } -#ifdef ISP_SMPLOCK - msleep(isp_kthread, &isp->isp_lock, - PRIBIO, "isp_fcthrd", hz); -#else - (void) tsleep(isp_kthread, PRIBIO, "isp_fcthrd", hz); -#endif + + + /* + * If we've never seen loop up and we've waited longer + * than quickboot time, give up and go to sleep until + * loop comes up. Otherwise, increment the loop down + * time and figure out how long to sleep to the next + * check. + */ + if (FCPARAM(isp)->loop_seen_once == 0 && + isp->isp_osinfo.loop_down_time >= + isp_quickboot_time) { + isp->isp_osinfo.loop_down_time = 0xffff; + slp = 0; + } else if (isp->isp_osinfo.loop_down_time > 30) { + inc = 30; + slp = 30 * hz; + } else if (isp->isp_osinfo.loop_down_time > 1) { + slp = hz; + } else { + slp = 1; + } + + inc += isp->isp_osinfo.loop_down_time; + if (inc < 0xffff) { + isp->isp_osinfo.loop_down_time = inc; + } else { + isp->isp_osinfo.loop_down_time = 0xfffe; + } + } else { + isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state OK"); + isp->isp_osinfo.loop_down_time = 0; + slp = 0; } /* - * Even if we didn't get good loop state we may be - * unfreezing the SIMQ so that we can kill off - * commands (if we've never seen loop before, for example). + * If we'd frozen the simq, unfreeze it now so that CAM + * can start sending us commands. If the FC state isn't + * okay yet, they'll hit that in isp_start which will + * freeze the queue again. */ - isp->isp_osinfo.ktmature = 1; wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { @@ -2159,16 +2176,26 @@ isp_kthread(void *arg) xpt_release_simq(isp->isp_sim, 1); CAMLOCK_2_ISPLOCK(isp); } - isp_prt(isp, ISP_LOGDEBUG0, "kthread: waiting until called"); #if __FreeBSD_version < 500000 - tsleep(&isp->isp_osinfo.kproc, PRIBIO, "isp_fc_worker", 0); + tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp); #else #ifdef ISP_SMPLOCK - cv_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock); + cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock, slp); #else - (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "fc_cv", 0); + (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf", slp); #endif #endif + /* + * If slp is zero, we're waking up for the first time after + * things have been okay. In this case, we set a deferral state + * for all commands and delay hysteresis seconds before starting + * the FC state evaluation. This gives the loop/fabric a chance + * to settle. + */ + if (slp == 0 && isp->isp_osinfo.hysteresis) { + (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT", + (isp->isp_osinfo.hysteresis * hz)); + } } } @@ -2260,8 +2287,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb) * This can only happen for Fibre Channel */ KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only")); - if (FCPARAM(isp)->loop_seen_once == 0 && - isp->isp_osinfo.ktmature) { + /* + * If we've exceeded the loop down limit start + * failing commands. + */ + if (isp->isp_osinfo.loop_down_time > + isp->isp_osinfo.loop_down_limit) { ISPLOCK_2_CAMLOCK(isp); XS_SETERR(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); @@ -2303,25 +2334,22 @@ isp_action(struct cam_sim *sim, union ccb *ccb) #ifdef ISP_TARGET_MODE case XPT_EN_LUN: /* Enable LUN as a target */ { - int seq, iok, i; + int seq, i; CAMLOCK_2_ISPLOCK(isp); - iok = isp->isp_osinfo.intsok; - isp->isp_osinfo.intsok = 0; seq = isp_en_lun(isp, ccb); if (seq < 0) { - isp->isp_osinfo.intsok = iok; ISPLOCK_2_CAMLOCK(isp); xpt_done(ccb); break; } for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) { - uint16_t isr, sema, mbox; + uint32_t isr; + uint16_t sema, mbox; if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { isp_intr(isp, isr, sema, mbox); } DELAY(1000); } - isp->isp_osinfo.intsok = iok; ISPLOCK_2_CAMLOCK(isp); break; } @@ -2519,7 +2547,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) else fc->bitrate = 100000; if (tgt > 0 && tgt < MAX_FC_TARG) { - struct lportdb *lp = &fcp->portdb[tgt]; + fcportdb_t *lp = &fcp->portdb[tgt]; fc->wwnn = lp->node_wwn; fc->wwpn = lp->port_wwn; fc->port = lp->portid; @@ -2767,6 +2795,19 @@ int isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) { int bus, rv = 0; + static const char *roles[4] = { + "(none)", "Target", "Initiator", "Target/Initiator" + }; + static const char prom[] = + "PortID 0x%06x handle 0x%x role %s %s\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + static const char prom2[] = + "PortID 0x%06x handle 0x%x role %s %s tgt %u\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + target_id_t tgt; + fcportdb_t *lp; + struct cam_path *tmppath; + switch (cmd) { case ISPASYNC_NEW_TGT_PARAMS: { @@ -2775,7 +2816,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) int flags, tgt; sdparam *sdp = isp->isp_param; struct ccb_trans_settings cts; - struct cam_path *tmppath; memset(&cts, 0, sizeof (struct ccb_trans_settings)); @@ -2876,59 +2916,127 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) */ isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; - case ISPASYNC_PROMENADE: - { - const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x " - "(role %s) %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x"; - static const char *roles[4] = { - "(none)", "Target", "Initiator", "Target/Initiator" - }; - fcparam *fcp = isp->isp_param; - int tgt = *((int *) arg); + case ISPASYNC_DEV_ARRIVED: + lp = arg; + + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "arrived at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); #if __FreeBSD_version >= 500000 - int is_tgt_mask = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); - struct cam_path *tmppath; + ISPLOCK_2_CAMLOCK(isp); + if (xpt_create_path(&tmppath, NULL, + cam_sim_path(isp->isp_sim), tgt, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + CAMLOCK_2_ISPLOCK(isp); + break; + } + xpt_async(AC_FOUND_DEVICE, tmppath, NULL); + xpt_free_path(tmppath); + CAMLOCK_2_ISPLOCK(isp); #endif - struct lportdb *lp = &fcp->portdb[tgt]; - - isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid, - roles[lp->roles & 0x3], - (lp->valid)? "Arrived" : "Departed", - (uint32_t) (lp->port_wwn >> 32), - (uint32_t) (lp->port_wwn & 0xffffffffLL), - (uint32_t) (lp->node_wwn >> 32), - (uint32_t) (lp->node_wwn & 0xffffffffLL)); - - ISPLOCK_2_CAMLOCK(isp); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "arrived", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } + break; + case ISPASYNC_DEV_CHANGED: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "changed at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "changed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } + break; + case ISPASYNC_DEV_STAYED: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "stayed at", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "stayed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } + break; + case ISPASYNC_DEV_GONE: + lp = arg; + if (lp->ini_map_idx) { + tgt = lp->ini_map_idx - 1; + isp_prt(isp, ISP_LOGCONFIG, prom2, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "departed from", tgt, + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); #if __FreeBSD_version >= 500000 - if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), - (target_id_t)tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - CAMLOCK_2_ISPLOCK(isp); - break; - } - /* - * Policy: only announce targets. - */ - if (lp->roles & is_tgt_mask) { - if (lp->valid) { - xpt_async(AC_FOUND_DEVICE, tmppath, NULL); - } else { - xpt_async(AC_LOST_DEVICE, tmppath, NULL); + ISPLOCK_2_CAMLOCK(isp); + if (xpt_create_path(&tmppath, NULL, + cam_sim_path(isp->isp_sim), tgt, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + CAMLOCK_2_ISPLOCK(isp); + break; } - } - xpt_free_path(tmppath); + xpt_async(AC_LOST_DEVICE, tmppath, NULL); + xpt_free_path(tmppath); + CAMLOCK_2_ISPLOCK(isp); #endif - CAMLOCK_2_ISPLOCK(isp); + } else { + isp_prt(isp, ISP_LOGCONFIG, prom, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "departed", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); + } break; - } case ISPASYNC_CHANGE_NOTIFY: + { + char *msg; if (arg == ISPASYNC_CHANGE_PDB) { - isp_prt(isp, ISP_LOGINFO, - "Port Database Changed"); + msg = "Port Database Changed"; } else if (arg == ISPASYNC_CHANGE_SNS) { - isp_prt(isp, ISP_LOGINFO, - "Name Server Database Changed"); + msg = "Name Server Database Changed"; + } else { + msg = "Other Change Notify"; } + isp_prt(isp, ISP_LOGINFO, msg); + isp_freeze_loopdown(isp, msg); #if __FreeBSD_version < 500000 wakeup(&isp->isp_osinfo.kproc); #else @@ -2939,117 +3047,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) #endif #endif break; - case ISPASYNC_FABRIC_DEV: - { - int target, base, lim; - fcparam *fcp = isp->isp_param; - struct lportdb *lp = NULL; - struct lportdb *clp = (struct lportdb *) arg; - char *pt; - - switch (clp->port_type) { - case 1: - pt = " N_Port"; - break; - case 2: - pt = " NL_Port"; - break; - case 3: - pt = "F/NL_Port"; - break; - case 0x7f: - pt = " Nx_Port"; - break; - case 0x81: - pt = " F_port"; - break; - case 0x82: - pt = " FL_Port"; - break; - case 0x84: - pt = " E_port"; - break; - default: - pt = " "; - break; - } - - isp_prt(isp, ISP_LOGINFO, - "%s Fabric Device @ PortID 0x%x", pt, clp->portid); - - /* - * If we don't have an initiator role we bail. - * - * We just use ISPASYNC_FABRIC_DEV for announcement purposes. - */ - - if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { - break; - } - - /* - * Is this entry for us? If so, we bail. - */ - - if (fcp->isp_portid == clp->portid) { - break; - } - - /* - * Else, the default policy is to find room for it in - * our local port database. Later, when we execute - * the call to isp_pdb_sync either this newly arrived - * or already logged in device will be (re)announced. - */ - - 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; - - /* - * Is it already in our list? - */ - for (target = base; target < lim; target++) { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - continue; - } - lp = &fcp->portdb[target]; - if (lp->port_wwn == clp->port_wwn && - lp->node_wwn == clp->node_wwn) { - lp->fabric_dev = 1; - break; - } - } - if (target < lim) { - break; - } - for (target = base; target < lim; target++) { - if (target >= FL_PORT_ID && target <= FC_SNS_ID) { - continue; - } - lp = &fcp->portdb[target]; - if (lp->port_wwn == 0) { - break; - } - } - if (target == lim) { - isp_prt(isp, ISP_LOGWARN, - "out of space for fabric devices"); - break; - } - lp->port_type = clp->port_type; - lp->fc4_type = clp->fc4_type; - lp->node_wwn = clp->node_wwn; - lp->port_wwn = clp->port_wwn; - lp->portid = clp->portid; - lp->fabric_dev = 1; - break; } #ifdef ISP_TARGET_MODE case ISPASYNC_TARGET_NOTIFY: @@ -3136,8 +3133,12 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) void isp_uninit(ispsoftc_t *isp) { - ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); - DISABLE_INTS(isp); + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET); + } else { + ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); + } + ISP_DISABLE_INTS(isp); } void |