diff options
-rw-r--r-- | sys/dev/isp/isp.c | 17 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 486 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.h | 58 | ||||
-rw-r--r-- | sys/dev/isp/isp_ioctl.h | 76 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 71 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.c | 83 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.h | 10 | ||||
-rw-r--r-- | sys/dev/isp/isp_tpublic.h | 3 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 16 |
9 files changed, 565 insertions, 255 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 351caae..7797a97 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -212,6 +212,9 @@ isp_reset(struct ispsoftc *isp) case ISP_HA_FC_2200: revname = "2200"; break; + case ISP_HA_FC_2300: + revname = "2300"; + break; default: break; } @@ -505,7 +508,7 @@ again: #endif } else { ISP_WRITE(isp, RISC_MTR2100, 0x1212); - if (IS_2200(isp)) { + if (IS_2200(isp) || IS_2300(isp)) { ISP_WRITE(isp, HCCR, HCCR_2X00_DISABLE_PARITY_PAUSE); } } @@ -1135,7 +1138,7 @@ isp_fibre_init(struct ispsoftc *isp) * Right now we just set extended options to prefer point-to-point * over loop based upon some soft config options. */ - if (IS_2200(isp)) { + if (IS_2200(isp) || IS_2300(isp)) { icbp->icb_fwoptions |= ICBOPT_EXTENDED; /* * Prefer or force Point-To-Point instead Loop? @@ -1412,7 +1415,7 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) return (-1); } fcp->isp_loopid = mbs.param[1]; - if (IS_2200(isp)) { + if (IS_2200(isp) || IS_2300(isp)) { int topo = (int) mbs.param[6]; if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) topo = TOPO_PTP_STUB; @@ -1728,7 +1731,7 @@ isp_pdb_sync(struct ispsoftc *isp) mbs.param[1] = loopid << 8; mbs.param[2] = portid >> 16; mbs.param[3] = portid & 0xffff; - if (IS_2200(isp)) { + if (IS_2200(isp) || IS_2300(isp)) { /* only issue a PLOGI if not logged in */ mbs.param[1] |= 0x1; } @@ -2260,7 +2263,6 @@ isp_start(XS_T *xs) XS_INITERR(xs); isp = XS_ISP(xs); - /* * Check to make sure we're supporting initiator role. */ @@ -2949,6 +2951,7 @@ isp_intr(void *arg) isp_prt(isp, ISP_LOGDEBUG2, "bogus intr- isr %x (%x) iptr %x optr %x", isr, junk, iptr, optr); + isp->isp_intbogus++; } while (optr != iptr) { @@ -3336,7 +3339,7 @@ isp_parse_async(struct ispsoftc *isp, int mbox) FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp->isp_sendmarker = 1; isp_mark_getpdb_all(isp); - isp_prt(isp, ISP_LOGINFO, "LIP occurred"); + isp_async(isp, ISPASYNC_LIP, NULL); #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); #endif @@ -3369,7 +3372,7 @@ isp_parse_async(struct ispsoftc *isp, int mbox) FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_NIL; isp_mark_getpdb_all(isp); - isp_prt(isp, ISP_LOGINFO, "Loop RESET"); + isp_async(isp, ISPASYNC_LOOP_RESET, NULL); #ifdef ISP_TARGET_MODE isp_target_async(isp, bus, mbox); #endif diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 2a11c54..008da7b 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -26,17 +26,43 @@ * SUCH DAMAGE. */ #include <dev/isp/isp_freebsd.h> +#include <sys/unistd.h> +#include <sys/kthread.h> #include <machine/stdarg.h> /* for use by isp_prt below */ +#include <sys/conf.h> +#include <sys/ioccom.h> +#include <dev/isp/isp_ioctl.h> +static d_ioctl_t ispioctl; static void isp_intr_enable(void *); static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *); static void isp_poll(struct cam_sim *); +#if 0 static void isp_relsim(void *); +#endif static timeout_t isp_watchdog; +static void isp_kthread(void *); static void isp_action(struct cam_sim *, union ccb *); +#define ISP_CDEV_MAJOR 248 +static struct cdevsw isp_cdevsw = { + /* open */ nullopen, + /* close */ nullclose, + /* read */ noread, + /* write */ nowrite, + /* ioctl */ ispioctl, + /* poll */ nopoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "isp", + /* maj */ ISP_CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ D_TAPE, +}; + static struct ispsoftc *isplist = NULL; void @@ -91,6 +117,7 @@ isp_attach(struct ispsoftc *isp) CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, TRUE); + config_intrhook_disestablish(&isp->isp_osinfo.ehook); return; } @@ -102,6 +129,23 @@ isp_attach(struct ispsoftc *isp) xpt_action((union ccb *)&csa); isp->isp_sim = sim; isp->isp_path = path; + /* + * Create a kernel thread for fibre channel instances. We + * don't have dual channel FC cards. + */ + if (IS_FC(isp)) { + cv_init(&isp->isp_osinfo.kthread_cv, "isp_kthread_cv"); + if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc, + RFHIGHPID, "%s: fc_thrd", + device_get_nameunit(isp->isp_dev))) { + isp_prt(isp, ISP_LOGERR, "could not create kthread"); + xpt_bus_deregister(cam_sim_path(sim)); + cam_sim_free(sim, TRUE); + config_intrhook_disestablish(&isp->isp_osinfo.ehook); + return; + } + } + /* * If we have a second channel, construct SIM entry for that. @@ -113,12 +157,14 @@ isp_attach(struct ispsoftc *isp) xpt_bus_deregister(cam_sim_path(isp->isp_sim)); xpt_free_path(isp->isp_path); cam_simq_free(devq); + config_intrhook_disestablish(&isp->isp_osinfo.ehook); return; } if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) { xpt_bus_deregister(cam_sim_path(isp->isp_sim)); xpt_free_path(isp->isp_path); cam_sim_free(sim, TRUE); + config_intrhook_disestablish(&isp->isp_osinfo.ehook); return; } @@ -128,6 +174,7 @@ isp_attach(struct ispsoftc *isp) xpt_free_path(isp->isp_path); xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, TRUE); + config_intrhook_disestablish(&isp->isp_osinfo.ehook); return; } @@ -140,6 +187,13 @@ isp_attach(struct ispsoftc *isp) isp->isp_sim2 = sim; isp->isp_path2 = path; } + + /* + * Create device nodes + */ + (void) make_dev(&isp_cdevsw, device_get_unit(isp->isp_dev), UID_ROOT, + GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev)); + if (isp->isp_role != ISP_ROLE_NONE) { isp->isp_state = ISP_RUNSTATE; ENABLE_INTS(isp); @@ -153,6 +207,89 @@ isp_attach(struct ispsoftc *isp) } tmp->isp_osinfo.next = isp; } + +} + +static int +ispioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) +{ + struct ispsoftc *isp; + int retval = ENOTTY; + + isp = isplist; + while (isp) { + if (minor(dev) == device_get_unit(isp->isp_dev)) { + break; + } + isp = isp->isp_osinfo.next; + } + if (isp == NULL) + return (ENXIO); + + switch (cmd) { + case ISP_SDBLEV: + { + int olddblev = isp->isp_dblev; + isp->isp_dblev = *(int *)addr; + *(int *)addr = olddblev; + retval = 0; + break; + } + case ISP_RESETHBA: + ISP_LOCK(isp); + isp_reinit(isp); + ISP_UNLOCK(isp); + retval = 0; + break; + case ISP_FC_RESCAN: + if (IS_FC(isp)) { + ISP_LOCK(isp); + if (isp_fc_runstate(isp, 5 * 1000000)) { + retval = EIO; + } else { + retval = 0; + } + ISP_UNLOCK(isp); + } + break; + case ISP_FC_LIP: + if (IS_FC(isp)) { + ISP_LOCK(isp); + if (isp_control(isp, ISPCTL_SEND_LIP, 0)) { + retval = EIO; + } else { + retval = 0; + } + ISP_UNLOCK(isp); + } + break; + case ISP_FC_GETDINFO: + { + struct isp_fc_device *ifc = (struct isp_fc_device *) addr; + struct lportdb *lp; + + if (ifc->loopid < 0 || ifc->loopid >= MAX_FC_TARG) { + retval = EINVAL; + break; + } + ISP_LOCK(isp); + lp = &FCPARAM(isp)->portdb[ifc->loopid]; + if (lp->valid) { + ifc->loopid = lp->loopid; + ifc->portid = lp->portid; + ifc->node_wwn = lp->node_wwn; + ifc->port_wwn = lp->port_wwn; + retval = 0; + } else { + retval = ENODEV; + } + ISP_UNLOCK(isp); + break; + } + default: + break; + } + return (retval); } static void @@ -198,7 +335,6 @@ static __inline int is_lun_enabled(struct ispsoftc *isp, int bus, lun_id_t lun) { tstate_t *tptr; - ISP_LOCK(isp); tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)]; if (tptr == NULL) { ISP_UNLOCK(isp); @@ -210,7 +346,6 @@ is_lun_enabled(struct ispsoftc *isp, int bus, lun_id_t lun) return (1); } } while ((tptr = tptr->next) != NULL); - ISP_UNLOCK(isp); return (0); } @@ -238,28 +373,23 @@ get_lun_statep(struct ispsoftc *isp, int bus, lun_id_t lun) { tstate_t *tptr; - ISP_LOCK(isp); if (lun == CAM_LUN_WILDCARD) { tptr = &isp->isp_osinfo.tsdflt[bus]; tptr->hold++; - ISP_UNLOCK(isp); return (tptr); } else { tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)]; } if (tptr == NULL) { - ISP_UNLOCK(isp); return (NULL); } do { if (tptr->lun == lun && tptr->bus == bus) { tptr->hold++; - ISP_UNLOCK(isp); return (tptr); } } while ((tptr = tptr->next) != NULL); - ISP_UNLOCK(isp); return (tptr); } @@ -273,28 +403,23 @@ rls_lun_statep(struct ispsoftc *isp, tstate_t *tptr) static __inline int isp_psema_sig_rqe(struct ispsoftc *isp) { - ISP_LOCK(isp); while (isp->isp_osinfo.tmflags & TM_BUSY) { isp->isp_osinfo.tmflags |= TM_WANTED; if (tsleep(&isp->isp_osinfo.tmflags, PRIBIO|PCATCH, "i0", 0)) { - ISP_UNLOCK(isp); return (-1); } isp->isp_osinfo.tmflags |= TM_BUSY; } - ISP_UNLOCK(isp); return (0); } static __inline int isp_cv_wait_timed_rqe(struct ispsoftc *isp, int timo) { - ISP_LOCK(isp); if (tsleep(&isp->isp_osinfo.rstatus, PRIBIO, "qt1", timo)) { ISP_UNLOCK(isp); return (-1); } - ISP_UNLOCK(isp); return (0); } @@ -308,13 +433,11 @@ isp_cv_signal_rqe(struct ispsoftc *isp, int status) static __inline void isp_vsema_rqe(struct ispsoftc *isp) { - ISP_LOCK(isp); if (isp->isp_osinfo.tmflags & TM_WANTED) { isp->isp_osinfo.tmflags &= ~TM_WANTED; wakeup(&isp->isp_osinfo.tmflags); } isp->isp_osinfo.tmflags &= ~TM_BUSY; - ISP_UNLOCK(isp); } static cam_status @@ -351,7 +474,6 @@ create_lun_state(struct ispsoftc *isp, int bus, new->hold = 1; hfx = LUN_HASH_FUNC(isp, new->bus, new->lun); - ISP_LOCK(isp); tptr = isp->isp_osinfo.lun_hash[hfx]; if (tptr == NULL) { isp->isp_osinfo.lun_hash[hfx] = new; @@ -360,7 +482,6 @@ create_lun_state(struct ispsoftc *isp, int bus, tptr = tptr->next; tptr->next = new; } - ISP_UNLOCK(isp); *rslt = new; return (CAM_REQ_CMP); } @@ -372,14 +493,11 @@ destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr) tstate_t *lw, *pw; hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun); - ISP_LOCK(isp); if (tptr->hold) { - ISP_UNLOCK(isp); return; } pw = isp->isp_osinfo.lun_hash[hfx]; if (pw == NULL) { - ISP_UNLOCK(isp); return; } else if (pw->lun == tptr->lun && pw->bus == tptr->bus) { isp->isp_osinfo.lun_hash[hfx] = pw->next; @@ -400,9 +518,11 @@ destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr) } } free(tptr, M_DEVBUF); - ISP_UNLOCK(isp); } +/* + * we enter with our locks held. + */ static void isp_en_lun(struct ispsoftc *isp, union ccb *ccb) { @@ -410,7 +530,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) struct ccb_en_lun *cel = &ccb->cel; tstate_t *tptr; u_int16_t rstat; - int bus, frozen = 0; + int bus, cmd, frozen = 0; lun_id_t lun; target_id_t tgt; @@ -461,9 +581,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) xpt_freeze_simq(isp->isp_sim, 1); isp->isp_osinfo.drain = 1; while (isp->isp_osinfo.drain) { - (void) msleep(&isp->isp_osinfo.drain, - &isp->isp_osinfo.lock, PRIBIO, - "ispdrain", 10 * hz); + (void) msleep(&isp->isp_osinfo.drain, &isp->isp_lock, + PRIBIO, "ispdrain", 10 * hz); } ISP_UNLOCK(isp); } @@ -479,17 +598,18 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) fcparam *fcp = isp->isp_param; int rv; - ISP_LOCK(isp); rv = isp_fc_runstate(isp, 2 * 1000000); - ISP_UNLOCK(isp); if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGWARN, "could not get a good port database read"); ccb->ccb_h.status = CAM_REQ_CMP_ERR; - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } } @@ -506,8 +626,11 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) if (cel->enable) { if (isp->isp_osinfo.tmflags & (1 << bus)) { ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } ccb->ccb_h.status = @@ -516,56 +639,68 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) xpt_path_target_id(ccb->ccb_h.path), xpt_path_lun_id(ccb->ccb_h.path)); if (ccb->ccb_h.status != CAM_REQ_CMP) { - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } SLIST_INIT(&tptr->atios); SLIST_INIT(&tptr->inots); av |= ENABLE_TARGET_FLAG; - ISP_LOCK(isp); av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); if (av) { ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; xpt_free_path(tptr->owner); - ISP_UNLOCK(isp); - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } isp->isp_osinfo.tmflags |= (1 << bus); - ISP_UNLOCK(isp); } else { if ((isp->isp_osinfo.tmflags & (1 << bus)) == 0) { ccb->ccb_h.status = CAM_LUN_INVALID; - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } if (are_any_luns_enabled(isp, bus)) { ccb->ccb_h.status = CAM_SCSI_BUSY; - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } - ISP_LOCK(isp); av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); if (av) { ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - ISP_UNLOCK(isp); - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } isp->isp_osinfo.tmflags &= ~(1 << bus); - ISP_UNLOCK(isp); ccb->ccb_h.status = CAM_REQ_CMP; } xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGINFO, "Target Mode %sabled on channel %d", (cel->enable) ? "en" : "dis", bus); - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } return; } @@ -573,8 +708,11 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) * We can move along now... */ - if (frozen) + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } if (cel->enable) { @@ -599,11 +737,24 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) return; } - ISP_LOCK(isp); if (cel->enable) { u_int32_t seq = isp->isp_osinfo.rollinfo++; + int c, n, ulun = lun; + + cmd = RQSTYPE_ENABLE_LUN; + c = DFLT_CMND_CNT; + n = DFLT_INOT_CNT; + if (IS_FC(isp) && lun != 0) { + cmd = RQSTYPE_MODIFY_LUN; + n = 0; + /* + * For SCC firmware, we only deal with setting + * (enabling or modifying) lun 0. + */ + ulun = 0; + } rstat = LUN_ERR; - if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, tgt, lun, seq)) { + if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq)) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGWARN, "isp_lun_cmd failed"); goto out; @@ -611,23 +762,35 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) if (isp_cv_wait_timed_rqe(isp, 30 * hz)) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGERR, - "wait for ENABLE LUN timed out"); + "wait for ENABLE/MODIFY LUN timed out"); goto out; } rstat = isp->isp_osinfo.rstatus; if (rstat != LUN_OK) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGERR, - "ENABLE LUN returned 0x%x", rstat); + "ENABLE/MODIFY LUN returned 0x%x", rstat); goto out; } } else { + int c, n, ulun = lun; u_int32_t seq; - seq = isp->isp_osinfo.rollinfo++; rstat = LUN_ERR; + seq = isp->isp_osinfo.rollinfo++; + cmd = -RQSTYPE_MODIFY_LUN; - if (isp_lun_cmd(isp, -RQSTYPE_MODIFY_LUN, bus, tgt, lun, seq)) { + c = DFLT_CMND_CNT; + n = DFLT_INOT_CNT; + if (IS_FC(isp) && lun != 0) { + n = 0; + /* + * For SCC firmware, we only deal with setting + * (enabling or modifying) lun 0. + */ + ulun = 0; + } + if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq)) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed"); goto out; @@ -645,10 +808,15 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) "MODIFY LUN returned 0x%x", rstat); goto out; } - rstat = LUN_ERR; + if (IS_FC(isp) && lun) { + goto out; + } + seq = isp->isp_osinfo.rollinfo++; - if (isp_lun_cmd(isp, -RQSTYPE_ENABLE_LUN, bus, tgt, lun, seq)) { + rstat = LUN_ERR; + cmd = -RQSTYPE_ENABLE_LUN; + if (isp_lun_cmd(isp, cmd, bus, tgt, lun, 0, 0, seq)) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed"); goto out; @@ -656,20 +824,19 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) if (isp_cv_wait_timed_rqe(isp, 30 * hz)) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGERR, - "wait for ENABLE LUN timed out"); + "wait for DISABLE LUN timed out"); goto out; } rstat = isp->isp_osinfo.rstatus; if (rstat != LUN_OK) { xpt_print_path(ccb->ccb_h.path); isp_prt(isp, ISP_LOGWARN, - "ENABLE LUN returned 0x%x", rstat); + "DISABLE LUN returned 0x%x", rstat); goto out; } } out: isp_vsema_rqe(isp); - ISP_UNLOCK(isp); if (rstat != LUN_OK) { xpt_print_path(ccb->ccb_h.path); @@ -867,7 +1034,7 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) cto->ct_timeout = 10; hp = &cto->ct_syshandle; ccb->ccb_h.flags &= ~CAM_SEND_SENSE; - if (cto->ct_flags & CT_SENDSTATUS) + if (cto->ct_flags & CT_SENDSTATUS) cto->ct_flags |= CT_CCINCR; } @@ -1005,9 +1172,7 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) * If QLTM_SVALID is set, the firware has recommended Sense Data. * * If the DISCONNECTS DISABLED bit is set in the flags field, - * we're still connected on the SCSI bus - i.e. the initiator - * did not set DiscPriv in the identify message. We don't care - * about this so it's ignored. + * we're still connected on the SCSI bus. */ status = aep->at_status; if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) { @@ -1021,15 +1186,13 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) return (0); } if ((status & ~QLTM_SVALID) != AT_CDB) { - isp_prt(isp, - ISP_LOGWARN, "bogus atio (0x%x) leaked to platform", + isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform", status); isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); return (0); } - bus = aep->at_iid >> 7; - aep->at_iid &= 0x7f; + bus = GET_BUS_VAL(aep->at_iid); tptr = get_lun_statep(isp, bus, aep->at_lun); if (tptr == NULL) { tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD); @@ -1062,7 +1225,7 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) xpt_print_path(tptr->owner); isp_prt(isp, ISP_LOGWARN, "no ATIOS for lun %d from initiator %d on channel %d", - aep->at_lun, aep->at_iid, bus); + aep->at_lun, GET_IID_VAL(aep->at_iid), bus); rls_lun_statep(isp, tptr); if (aep->at_flags & AT_TQAE) isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0); @@ -1089,7 +1252,7 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) atiop->sense_len = 0; } - atiop->init_id = aep->at_iid & 0x7f; + atiop->init_id = GET_IID_VAL(aep->at_iid); atiop->cdb_len = aep->at_cdblen; MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen); atiop->ccb_h.status = CAM_CDB_RECVD; @@ -1104,10 +1267,11 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) } xpt_done((union ccb*)atiop); isp_prt(isp, ISP_LOGTDEBUG1, - "ATIO[%x] CDB=0x%x iid%d->lun%d tag 0x%x ttype 0x%x %s", - aep->at_handle, aep->at_cdb[0] & 0xff, aep->at_iid, aep->at_lun, - aep->at_tag_val & 0xff, aep->at_tag_type, - (aep->at_flags & AT_NODISC)? "nondisc" : "disconnecting"); + "ATIO[%x] CDB=0x%x bus %d iid%d->lun%d tag 0x%x ttype 0x%x %s", + aep->at_handle, aep->at_cdb[0] & 0xff, GET_BUS_VAL(aep->at_iid), + GET_IID_VAL(aep->at_iid), aep->at_lun, aep->at_tag_val & 0xff, + aep->at_tag_type, (aep->at_flags & AT_NODISC)? + "nondisc" : "disconnecting"); rls_lun_statep(isp, tptr); return (0); } @@ -1280,8 +1444,9 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, sentstatus? "FIN" : "MID"); notify_cam = ct->ct_header.rqs_seqno & 0x1; - if (ct->ct_flags & CT2_DATAMASK) + if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { resid = ct->ct_resid; + } } else { ct_entry_t *ct = arg; sentstatus = ct->ct_flags & CT_SENDSTATUS; @@ -1302,7 +1467,7 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) * the auto-replenish feature for CTIOs. */ notify_cam = ct->ct_header.rqs_seqno & 0x1; - if (ct->ct_status & QLTM_SVALID) { + if (ct->ct_status & QLTM_SVALID) { char *sp = (char *)ct; sp += CTIO_SENSE_OFFSET; ccb->csio.sense_len = @@ -1310,8 +1475,9 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len); ccb->ccb_h.status |= CAM_AUTOSNS_VALID; } - if (ct->ct_flags & CT_DATAMASK) + if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { resid = ct->ct_resid; + } } ccb->csio.resid += resid; @@ -1397,6 +1563,7 @@ isp_poll(struct cam_sim *sim) ISP_UNLOCK(isp); } +#if 0 static void isp_relsim(void *arg) { @@ -1412,6 +1579,7 @@ isp_relsim(void *arg) } ISP_UNLOCK(isp); } +#endif static void isp_watchdog(void *arg) @@ -1497,6 +1665,61 @@ isp_watchdog(void *arg) ISP_UNLOCK(isp); } +#ifdef ISP_SMPLOCK +static void +isp_kthread(void *arg) +{ + int wasfrozen; + struct ispsoftc *isp = arg; + + mtx_lock(&isp->isp_lock); + for (;;) { + isp_prt(isp, ISP_LOGDEBUG0, "kthread checking FC state"); + while (isp_fc_runstate(isp, 2 * 1000000) != 0) { +#if 0 + msleep(&lbolt, &isp->isp_lock, + PRIBIO, "isp_fcthrd", 0); +#else + msleep(isp_kthread, &isp->isp_lock, + PRIBIO, "isp_fcthrd", hz); +#endif + } + wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; + isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; + if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { + isp_prt(isp, ISP_LOGDEBUG0, "kthread up release simq"); + ISPLOCK_2_CAMLOCK(isp); + xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } + cv_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock); + } +} +#else +static void +isp_kthread(void *arg) +{ + int wasfrozen; + struct ispsoftc *isp = arg; + + mtx_lock(&Giant); + for (;;) { + isp_prt(isp, ISP_LOGDEBUG0, "kthread checking FC state"); + while (isp_fc_runstate(isp, 2 * 1000000) != 0) { + tsleep(isp_kthread, PRIBIO, "isp_fcthrd", hz); + } + wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; + isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; + if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { + isp_prt(isp, ISP_LOGDEBUG0, "kthread up release simq"); + ISPLOCK_2_CAMLOCK(isp); + xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } + tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "isp_fc_worker", 0); + } +} +#endif static void isp_action(struct cam_sim *sim, union ccb *ccb) { @@ -1511,7 +1734,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.sim_priv.entries[1].ptr = isp; if (isp->isp_state != ISP_RUNSTATE && ccb->ccb_h.func_code == XPT_SCSI_IO) { - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { ISP_UNLOCK(isp); @@ -1524,10 +1747,11 @@ isp_action(struct cam_sim *sim, union ccb *ccb) return; } isp->isp_state = ISP_RUNSTATE; - ISP_UNLOCK(isp); + ISPLOCK_2_CAMLOCK(isp); } isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code); + switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: /* Execute the requested I/O operation */ /* @@ -1555,9 +1779,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } #endif ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK; - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); error = isp_start((XS_T *) ccb); - ISP_UNLOCK(isp); switch (error) { case CMD_QUEUED: ccb->ccb_h.status |= CAM_SIM_QUEUED; @@ -1578,14 +1801,27 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } else { callout_handle_init(&ccb->ccb_h.timeout_ch); } + ISPLOCK_2_CAMLOCK(isp); break; case CMD_RQLATER: +#ifdef ISP_SMPLOCK + cv_signal(&isp->isp_osinfo.kthread_cv); +#else + wakeup(&isp->isp_osinfo.kthread_cv); +#endif if (isp->isp_osinfo.simqfrozen == 0) { isp_prt(isp, ISP_LOGDEBUG2, "RQLATER freeze simq"); +#if 0 isp->isp_osinfo.simqfrozen |= SIMQFRZ_TIMED; timeout(isp_relsim, isp, 500); +#else + isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN; +#endif + ISPLOCK_2_CAMLOCK(isp); xpt_freeze_simq(sim, 1); + } else { + ISPLOCK_2_CAMLOCK(isp); } XS_SETERR(ccb, CAM_REQUEUE_REQ); xpt_done(ccb); @@ -1598,12 +1834,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; XS_SETERR(ccb, CAM_REQUEUE_REQ); + ISPLOCK_2_CAMLOCK(isp); xpt_done(ccb); break; case CMD_COMPLETE: - ISP_LOCK(isp); isp_done((struct ccb_scsiio *) ccb); - ISP_UNLOCK(isp); + ISPLOCK_2_CAMLOCK(isp); break; default: isp_prt(isp, ISP_LOGERR, @@ -1611,12 +1847,15 @@ isp_action(struct cam_sim *sim, union ccb *ccb) error, __LINE__, __FILE__); XS_SETERR(ccb, CAM_REQ_CMP_ERR); xpt_done(ccb); + ISPLOCK_2_CAMLOCK(isp); } break; #ifdef ISP_TARGET_MODE case XPT_EN_LUN: /* Enable LUN as a target */ + CAMLOCK_2_ISPLOCK(isp); isp_en_lun(isp, ccb); + ISPLOCK_2_CAMLOCK(isp); xpt_done(ccb); break; @@ -1633,7 +1872,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } ccb->ccb_h.sim_priv.entries[0].field = 0; ccb->ccb_h.sim_priv.entries[1].ptr = isp; - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h, sim_links.sle); @@ -1641,14 +1880,14 @@ isp_action(struct cam_sim *sim, union ccb *ccb) SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle); } - ISP_UNLOCK(isp); rls_lun_statep(isp, tptr); ccb->ccb_h.status = CAM_REQ_INPROG; + ISPLOCK_2_CAMLOCK(isp); break; } case XPT_CONT_TARGET_IO: { - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); ccb->ccb_h.status = isp_target_start_ctio(isp, ccb); if (ccb->ccb_h.status != CAM_REQ_INPROG) { if (isp->isp_osinfo.simqfrozen == 0) { @@ -1659,11 +1898,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; XS_SETERR(ccb, CAM_REQUEUE_REQ); + ISPLOCK_2_CAMLOCK(isp); xpt_done(ccb); } else { + ISPLOCK_2_CAMLOCK(isp); ccb->ccb_h.status |= CAM_SIM_QUEUED; } - ISP_UNLOCK(isp); break; } #endif @@ -1673,9 +1913,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb) tgt = ccb->ccb_h.target_id; tgt |= (bus << 16); - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); error = isp_control(isp, ISPCTL_RESET_DEV, &tgt); - ISP_UNLOCK(isp); + ISPLOCK_2_CAMLOCK(isp); if (error) { ccb->ccb_h.status = CAM_REQ_CMP_ERR; } else { @@ -1686,6 +1926,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) case XPT_ABORT: /* Abort the specified CCB */ { union ccb *accb = ccb->cab.abort_ccb; + CAMLOCK_2_ISPLOCK(isp); switch (accb->ccb_h.func_code) { #ifdef ISP_TARGET_MODE case XPT_ACCEPT_TARGET_IO: @@ -1698,9 +1939,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) break; #endif case XPT_SCSI_IO: - ISP_LOCK(isp); error = isp_control(isp, ISPCTL_ABORT_CMD, ccb); - ISP_UNLOCK(isp); if (error) { ccb->ccb_h.status = CAM_UA_ABORT; } else { @@ -1711,6 +1950,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.status = CAM_REQ_INVALID; break; } + ISPLOCK_2_CAMLOCK(isp); xpt_done(ccb); break; } @@ -1718,7 +1958,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) cts = &ccb->cts; tgt = cts->ccb_h.target_id; - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); if (IS_SCSI(isp)) { sdparam *sdp = isp->isp_param; u_int16_t *dptr; @@ -1795,7 +2035,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) sdp->isp_devparam[tgt].dev_update = 1; isp->isp_update |= (1 << bus); } - ISP_UNLOCK(isp); + ISPLOCK_2_CAMLOCK(isp); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -1823,14 +2063,13 @@ isp_action(struct cam_sim *sim, union ccb *ccb) u_int16_t dval, pval, oval; int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); + CAMLOCK_2_ISPLOCK(isp); sdp += bus; if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) { - ISP_LOCK(isp); sdp->isp_devparam[tgt].dev_refresh = 1; isp->isp_update |= (1 << bus); (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL); - ISP_UNLOCK(isp); dval = sdp->isp_devparam[tgt].cur_dflags; oval = sdp->isp_devparam[tgt].cur_offset; pval = sdp->isp_devparam[tgt].cur_period; @@ -1840,7 +2079,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb) pval = sdp->isp_devparam[tgt].sync_period; } - ISP_LOCK(isp); cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); if (dval & DPARM_DISC) { @@ -1864,7 +2102,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID; } - ISP_UNLOCK(isp); + ISPLOCK_2_CAMLOCK(isp); isp_prt(isp, ISP_LOGDEBUG0, "%d.%d get %s period 0x%x offset 0x%x flags 0x%x", bus, tgt, (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? @@ -1905,9 +2143,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } case XPT_RESET_BUS: /* Reset the specified bus */ bus = cam_sim_bus(sim); - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); error = isp_control(isp, ISPCTL_RESET_BUS, &bus); - ISP_UNLOCK(isp); + ISPLOCK_2_CAMLOCK(isp); if (error) ccb->ccb_h.status = CAM_REQ_CMP_ERR; else { @@ -2050,15 +2288,9 @@ isp_done(struct ccb_scsiio *sccb) "finished command on borrowed time"); } XS_CMD_S_CLEAR(sccb); - ISP_UNLOCK(isp); -#ifdef ISP_SMPLOCK - mtx_lock(&Giant); - xpt_done((union ccb *) sccb); - mtx_unlock(&Giant); -#else + ISPLOCK_2_CAMLOCK(isp); xpt_done((union ccb *) sccb); -#endif - ISP_LOCK(isp); + CAMLOCK_2_ISPLOCK(isp); } } @@ -2109,7 +2341,9 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x", bus, tgt, neg.sync_period, neg.sync_offset, flags); xpt_setup_ccb(&neg.ccb_h, tmppath, 1); + ISPLOCK_2_CAMLOCK(isp); xpt_async(AC_TRANSFER_NEG, tmppath, &neg); + CAMLOCK_2_ISPLOCK(isp); xpt_free_path(tmppath); break; } @@ -2118,33 +2352,60 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected", bus); if (bus > 0 && isp->isp_path2) { + ISPLOCK_2_CAMLOCK(isp); xpt_async(AC_BUS_RESET, isp->isp_path2, NULL); + CAMLOCK_2_ISPLOCK(isp); } else if (isp->isp_path) { + ISPLOCK_2_CAMLOCK(isp); xpt_async(AC_BUS_RESET, isp->isp_path, NULL); + CAMLOCK_2_ISPLOCK(isp); } break; + case ISPASYNC_LIP: + if (isp->isp_path) { + if (isp->isp_osinfo.simqfrozen == 0) { + isp_prt(isp, ISP_LOGDEBUG0, "LIP freeze simq"); + ISPLOCK_2_CAMLOCK(isp); + xpt_freeze_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } + isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN; + } + isp_prt(isp, ISP_LOGINFO, "LIP Received"); + break; + case ISPASYNC_LOOP_RESET: + if (isp->isp_path) { + if (isp->isp_osinfo.simqfrozen == 0) { + isp_prt(isp, ISP_LOGDEBUG0, + "Loop Reset freeze simq"); + ISPLOCK_2_CAMLOCK(isp); + xpt_freeze_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } + isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN; + } + isp_prt(isp, ISP_LOGINFO, "Loop Reset Received"); + break; case ISPASYNC_LOOP_DOWN: if (isp->isp_path) { if (isp->isp_osinfo.simqfrozen == 0) { - isp_prt(isp, ISP_LOGDEBUG2, + isp_prt(isp, ISP_LOGDEBUG0, "loop down freeze simq"); + ISPLOCK_2_CAMLOCK(isp); xpt_freeze_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); } isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN; } isp_prt(isp, ISP_LOGINFO, "Loop DOWN"); break; case ISPASYNC_LOOP_UP: - if (isp->isp_path) { - int wasfrozen = - isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; - isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; - if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { - xpt_release_simq(isp->isp_sim, 1); - isp_prt(isp, ISP_LOGDEBUG2, - "loop up release simq"); - } - } + /* + * Now we just note that Loop has come up. We don't + * actually do anything because we're waiting for a + * Change Notify before activating the FC cleanup + * thread to look at the state of the loop again. + */ isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; case ISPASYNC_PROMENADE: @@ -2175,6 +2436,11 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) isp_prt(isp, ISP_LOGINFO, "Name Server Database Changed"); } +#ifdef ISP_SMPLOCK + cv_signal(&isp->isp_osinfo.kthread_cv); +#else + wakeup(&isp->isp_osinfo.kthread_cv); +#endif break; case ISPASYNC_FABRIC_DEV: { diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 4598db7..0e25d91 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -33,12 +33,7 @@ /* * We're not ready for primetime yet */ -#if 0 -#if ((ISP_PLATFORM_VERSION_MAJOR * 10) + ISP_PLATFORM_VERSION_MINOR) >= 54 #define ISP_SMPLOCK 1 -#endif -#endif - #include <sys/param.h> #include <sys/param.h> @@ -48,6 +43,7 @@ #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mutex.h> +#include <sys/condvar.h> #include <sys/proc.h> #include <sys/bus.h> @@ -70,6 +66,8 @@ #include "opt_ddb.h" #include "opt_isp.h" +#define HANDLE_LOOPSTATE_IN_OUTER_LAYERS 1 + typedef void ispfwfunc __P((int, int, int, const u_int16_t **)); #ifdef ISP_TARGET_MODE @@ -104,12 +102,9 @@ struct isposinfo { u_int8_t simqfrozen; u_int8_t drain; u_int8_t intsok; -#ifdef ISP_SMPLOCK struct mtx lock; -#else - volatile u_int32_t islocked; - int splsaved; -#endif + struct cv kthread_cv; + struct proc *kproc; #ifdef ISP_TARGET_MODE #define TM_WANTED 0x80 #define TM_BUSY 0x40 @@ -122,19 +117,26 @@ struct isposinfo { #endif }; +#define isp_lock isp_osinfo.lock + /* * Locking macros... */ #ifdef ISP_SMPLOCK -#define ISP_LOCK(x) mtx_lock(&(x)->isp_osinfo.lock) -#define ISP_UNLOCK(x) mtx_unlock(&(x)->isp_osinfo.lock) +#define ISP_LOCK(x) mtx_lock(&(x)->isp_lock) +#define ISP_UNLOCK(x) mtx_unlock(&(x)->isp_lock) +#define ISPLOCK_2_CAMLOCK(isp) \ + mtx_unlock(&(isp)->isp_lock); mtx_lock(&Giant) +#define CAMLOCK_2_ISPLOCK(isp) \ + mtx_unlock(&Giant); mtx_lock(&(isp)->isp_lock) #else -#define ISP_LOCK isp_lock -#define ISP_UNLOCK isp_unlock +#define ISP_LOCK(x) +#define ISP_UNLOCK(x) +#define ISPLOCK_2_CAMLOCK(x) +#define CAMLOCK_2_ISPLOCK(x) #endif - /* * Required Macros/Defines */ @@ -319,30 +321,6 @@ extern void isp_uninit(struct ispsoftc *); /* * Platform specific inline functions */ -#ifndef ISP_SMPLOCK -static INLINE void isp_lock(struct ispsoftc *); -static INLINE void -isp_lock(struct ispsoftc *isp) -{ - int s = splcam(); - if (isp->isp_osinfo.islocked++ == 0) { - isp->isp_osinfo.splsaved = s; - } else { - splx(s); - } -} - -static INLINE void isp_unlock(struct ispsoftc *); -static INLINE void -isp_unlock(struct ispsoftc *isp) -{ - if (isp->isp_osinfo.islocked) { - if (--isp->isp_osinfo.islocked == 0) { - splx(isp->isp_osinfo.splsaved); - } - } -} -#endif static INLINE void isp_mbox_wait_complete(struct ispsoftc *); static INLINE void @@ -352,7 +330,7 @@ isp_mbox_wait_complete(struct ispsoftc *isp) isp->isp_osinfo.mboxwaiting = 1; #ifdef ISP_SMPLOCK (void) msleep(&isp->isp_osinfo.mboxwaiting, - &isp->isp_osinfo.lock, PRIBIO, "isp_mboxwaiting", 10 * hz); + &isp->isp_lock, PRIBIO, "isp_mboxwaiting", 10 * hz); #else (void) tsleep(&isp->isp_osinfo.mboxwaiting, PRIBIO, "isp_mboxwaiting", 10 * hz); diff --git a/sys/dev/isp/isp_ioctl.h b/sys/dev/isp/isp_ioctl.h new file mode 100644 index 0000000..5ed8a91 --- /dev/null +++ b/sys/dev/isp/isp_ioctl.h @@ -0,0 +1,76 @@ +/* $FreeBSD$ */ +/* + * Copyright (c) 2001 by Matthew Jacob + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Alternatively, this software may be distributed under the terms of the + * the GNU Public License ("GPL", Library, Version 2). + * + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Matthew Jacob <mjacob@feral.com) + * + */ +/* + * ioctl definitions for Qlogic FC/SCSI HBA driver + */ +#define ISP_IOC (021) /* 'Ctrl-Q' */ + +/* + * This ioctl sets/retrieves the debugging level for this hba instance. + * Note that this is not a simple integer level- see ispvar.h for definitions. + * + * The arguments is a pointer to an integer with the new debugging level. + * The old value is written into this argument. + */ + +#define ISP_SDBLEV _IOWR(ISP_IOC, 0, int) + +/* + * This ioctl resets the HBA. Use with caution. + */ +#define ISP_RESETHBA _IO(ISP_IOC, 1) + +/* + * This ioctl performs a fibre chanel rescan. + */ +#define ISP_FC_RESCAN _IO(ISP_IOC, 2) + +/* + * Initiate a LIP + */ +#define ISP_FC_LIP _IO(ISP_IOC, 3) + +/* + * Return the Port Database structure for the named device, or ENODEV if none. + * Caller fills in virtual loopid (0..255), aka 'target'. The driver returns + * ENODEV (if nothing valid there) or the actual loopid (for local loop devices + * only), 24 bit Port ID and Node and Port WWNs. + */ +struct isp_fc_device { + u_int32_t loopid; /* 0..255 */ + u_int32_t portid; /* 24 bit Port ID */ + u_int64_t node_wwn; + u_int64_t port_wwn; +}; + +#define ISP_FC_GETDINFO _IOWR(ISP_IOC, 4, struct isp_fc_device) diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index d16b111..7c01f86 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -304,9 +304,7 @@ isp_pci_attach(device_t dev) struct ispmdvec *mdvp; bus_size_t lim; char *sptr; -#ifdef ISP_SMPLOCK int locksetup = 0; -#endif /* * Figure out if we're supposed to skip this one. @@ -611,23 +609,19 @@ isp_pci_attach(device_t dev) (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &isp_debug); -#ifdef ISP_SMPLOCK /* Make sure the lock is set up. */ mtx_init(&isp->isp_osinfo.lock, "isp", MTX_DEF); locksetup++; - if (bus_setup_intr(dev, irq, INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY, - isp_pci_intr, isp, &pcs->ih)) { - device_printf(dev, "could not setup interrupt\n"); - goto bad; - } +#ifdef ISP_SMPLOCK +#define INTR_FLAGS INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY #else - if (bus_setup_intr(dev, irq, INTR_TYPE_CAM | INTR_ENTROPY, - isp_pci_intr, isp, &pcs->ih)) { +#define INTR_FLAGS INTR_TYPE_CAM | INTR_ENTROPY +#endif + if (bus_setup_intr(dev, irq, INTR_FLAGS, isp_pci_intr, isp, &pcs->ih)) { device_printf(dev, "could not setup interrupt\n"); goto bad; } -#endif /* * Set up logging levels. @@ -674,11 +668,9 @@ bad: (void) bus_teardown_intr(dev, irq, pcs->ih); } -#ifdef ISP_SMPLOCK if (locksetup && isp) { mtx_destroy(&isp->isp_osinfo.lock); } -#endif if (irq) { (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq); @@ -1280,7 +1272,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) u_int16_t scsi_status, send_status, send_sense, handle; u_int32_t totxfr, datalen; u_int8_t sense[QLTM_SENSELEN]; - int nctios; + int nctios, j; mp = (mush_t *) arg; if (error) { @@ -1309,9 +1301,9 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) */ cto->ct_flags |= CT2_NO_DATA; if (cto->ct_resid > 0) - cto->ct_flags |= CT2_DATA_UNDER; + cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; else if (cto->ct_resid < 0) - cto->ct_flags |= CT2_DATA_OVER; + cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER; cto->ct_seg_count = 0; cto->ct_reloff = 0; ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto); @@ -1351,9 +1343,10 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) handle = cto->ct_syshandle; cto->ct_syshandle = 0; + send_status = (cto->ct_flags & CT2_SENDSTATUS) != 0; - if ((send_status = (cto->ct_flags & CT2_SENDSTATUS)) != 0) { - cto->ct_flags &= ~CT2_SENDSTATUS; + if (send_status) { + cto->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR); /* * Preserve residual, which is actually the total count. @@ -1385,7 +1378,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) totxfr = cto->ct_resid = 0; cto->rsp.m0.ct_scsi_status = 0; - bzero(&cto->rsp, sizeof (cto->rsp)); + MEMZERO(&cto->rsp, sizeof (cto->rsp)); pci = (struct isp_pcisoftc *)mp->isp; dp = &pci->dmaps[isp_handle_index(handle)]; @@ -1456,8 +1449,13 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) cto->ct_header.rqs_seqno = 1; if (send_status) { + /* + * Get 'real' residual and set flags based + * on it. + */ + cto->ct_resid = datalen - totxfr; if (send_sense) { - bcopy(sense, cto->rsp.m1.ct_resp, + MEMCPY(cto->rsp.m1.ct_resp, sense, QLTM_SENSELEN); cto->rsp.m1.ct_senselen = QLTM_SENSELEN; @@ -1466,21 +1464,26 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) scsi_status; cto->ct_flags &= CT2_FLAG_MMASK; cto->ct_flags |= CT2_FLAG_MODE1 | - CT2_NO_DATA| CT2_SENDSTATUS; + CT2_NO_DATA | CT2_SENDSTATUS | + CT2_CCINCR; + if (cto->ct_resid > 0) + cto->rsp.m1.ct_scsi_status |= + CT2_DATA_UNDER; + else if (cto->ct_resid < 0) + cto->rsp.m1.ct_scsi_status |= + CT2_DATA_OVER; } else { cto->rsp.m0.ct_scsi_status = scsi_status; - cto->ct_flags |= CT2_SENDSTATUS; + cto->ct_flags |= + CT2_SENDSTATUS | CT2_CCINCR; + if (cto->ct_resid > 0) + cto->rsp.m0.ct_scsi_status |= + CT2_DATA_UNDER; + else if (cto->ct_resid < 0) + cto->rsp.m0.ct_scsi_status |= + CT2_DATA_OVER; } - /* - * Get 'real' residual and set flags based - * on it. - */ - cto->ct_resid = datalen - totxfr; - if (cto->ct_resid > 0) - cto->ct_flags |= CT2_DATA_UNDER; - else if (cto->ct_resid < 0) - cto->ct_flags |= CT2_DATA_OVER; } ISP_TDQE(mp->isp, "last dma2_tgt_fc", *mp->iptrp, cto); isp_prt(mp->isp, ISP_LOGTDEBUG1, @@ -1509,6 +1512,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) */ cto = (ct2_entry_t *) ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp); + j = *mp->iptrp; *mp->iptrp = ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN(isp)); if (*mp->iptrp == mp->optr) { @@ -1540,8 +1544,9 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) * just finished filling out. */ cto->ct_reloff += octo->rsp.m0.ct_xfrlen; - bzero(&cto->rsp, sizeof (cto->rsp)); - ISP_SWIZ_CTIO2(isp, cto, cto); + MEMZERO(&cto->rsp, sizeof (cto->rsp)); + ISP_SWIZ_CTIO2(isp, octo, octo); + ISP_ADD_REQUEST(mp->isp, j); } } } diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index 518b4cb..86ab25b 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -266,7 +266,7 @@ isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp) */ int isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun, - u_int32_t opaque) + int cmd_cnt, int inot_cnt, u_int32_t opaque) { lun_entry_t el; u_int16_t iptr, optr; @@ -277,8 +277,8 @@ isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun, if (IS_DUALBUS(isp)) { el.le_rsvd = (bus & 0x1) << 7; } - el.le_cmd_count = DFLT_CMD_CNT; - el.le_in_count = DFLT_INOTIFY; + el.le_cmd_count = cmd_cnt; + el.le_in_count = inot_cnt; if (cmd == RQSTYPE_ENABLE_LUN) { if (IS_SCSI(isp)) { el.le_flags = LUN_TQAE|LUN_DISAD; @@ -438,7 +438,7 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) } if (aep->at_datalen) { cto->ct_resid = aep->at_datalen; - cto->ct_flags |= CT2_DATA_UNDER; + cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; } if ((sts & 0xff) == SCSI_CHECK && (sts & ECMD_SVALID)) { cto->rsp.m1.ct_resp[0] = 0xf0; @@ -447,7 +447,7 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl) cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; cto->rsp.m1.ct_senselen = 16; - cto->ct_flags |= CT2_SNSLEN_VALID; + cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; } cto->ct_syshandle = hdl; } else { @@ -958,16 +958,7 @@ isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) case CT_NOACK: if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); -#if 0 - if (status & SENSEVALID) { - bcopy((caddr_t) (cep + CTIO_SENSE_OFFSET), - (caddr_t) &cdp->cd_sensedata, - sizeof(scsi_sense_t)); - cdp->cd_flags |= CDF_SENSEVALID; - } -#endif break; default: isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", @@ -997,11 +988,11 @@ isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); } } else { - /* - * Final CTIO completed. Release DMA resources and - * notify platform dependent layers. - */ - if (ct->ct_flags & CT_DATAMASK) { + /* + * Final CTIO completed. Release DMA resources and + * notify platform dependent layers. + */ + if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { ISP_DMAFREE(isp, xs, ct->ct_syshandle); } isp_prt(isp, pl, "final CTIO complete"); @@ -1028,6 +1019,11 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) } switch(ct->ct_status & ~QLTM_SVALID) { + case CT_BUS_ERROR: + isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); + /* FALL Through */ + case CT_DATA_OVER: + case CT_DATA_UNDER: case CT_OK: /* * There are generally 2 possibilities as to why we'd get @@ -1040,19 +1036,18 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) case CT_BDR_MSG: /* - * Bus Device Reset message received or the SCSI Bus has - * been Reset; the firmware has gone to Bus Free. + * Target Reset function received. * * The firmware generates an async mailbox interupt to * notify us of this and returns outstanding CTIOs with this * status. These CTIOs are handled in that same way as * CT_ABORTED ones, so just fall through here. */ - fmsg = "Bus Device Reset"; + fmsg = "TARGET RESET Task Management Function Received"; /*FALLTHROUGH*/ case CT_RESET: if (fmsg == NULL) - fmsg = "Bus Reset"; + fmsg = "LIP Reset"; /*FALLTHROUGH*/ case CT_ABORTED: /* @@ -1061,7 +1056,7 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) * set, then sends us an Immediate Notify entry. */ if (fmsg == NULL) - fmsg = "ABORT TASK sent by Initiator"; + fmsg = "ABORT Task Management Function Received"; isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg); break; @@ -1073,38 +1068,18 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data directiond"); break; - case CT_NOPATH: - /* - * CTIO rejected by the firmware due "no path for the - * nondisconnecting nexus specified". This means that - * we tried to access the bus while a non-disconnecting - * command is in process. - */ - isp_prt(isp, ISP_LOGERR, - "Firmware rejected CTIO2 for bad nexus %d->%d", - ct->ct_iid, ct->ct_lun); - break; - case CT_RSELTMO: - fmsg = "Reselection"; + fmsg = "failure to reconnect to initiator"; /*FALLTHROUGH*/ case CT_TIMEOUT: if (fmsg == NULL) - fmsg = "Command"; + fmsg = "command"; isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); break; case CT_ERR: fmsg = "Completed with Error"; /*FALLTHROUGH*/ - case CT_PHASE_ERROR: /* Bus phase sequence error */ - if (fmsg == NULL) - fmsg = "Phase Sequence Error"; - /*FALLTHROUGH*/ - case CT_TERMINATED: - if (fmsg == NULL) - fmsg = "terminated by TERMINATE TRANSFER"; - /*FALLTHROUGH*/ case CT_LOGOUT: if (fmsg == NULL) fmsg = "Port Logout"; @@ -1112,19 +1087,13 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) case CT_PORTNOTAVAIL: if (fmsg == NULL) fmsg = "Port not available"; + case CT_PORTCHANGED: + if (fmsg == NULL) + fmsg = "Port Changed"; case CT_NOACK: if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); -#if 0 - if (status & SENSEVALID) { - bcopy((caddr_t) (cep + CTIO_SENSE_OFFSET), - (caddr_t) &cdp->cd_sensedata, - sizeof(scsi_sense_t)); - cdp->cd_flags |= CDF_SENSEVALID; - } -#endif break; case CT_INVRXID: @@ -1164,6 +1133,9 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); } } else { + if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { + ISP_DMAFREE(isp, xs, ct->ct_syshandle); + } if (ct->ct_flags & CT_SENDSTATUS) { /* * Sent status and command complete. @@ -1180,7 +1152,6 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) * notify platform dependent layers. */ isp_prt(isp, pl, "data CTIO complete"); - ISP_DMAFREE(isp, xs, ct->ct_syshandle); } (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); /* diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h index fde87ce..c94bda8 100644 --- a/sys/dev/isp/isp_target.h +++ b/sys/dev/isp/isp_target.h @@ -361,13 +361,16 @@ typedef struct { #define CT_INVAL 0x06 /* request for disabled lun */ #define CT_NOPATH 0x07 /* invalid ITL nexus */ #define CT_INVRXID 0x08 /* (FC only) Invalid RX_ID */ +#define CT_DATA_OVER 0x09 /* (FC only) Data Overrun */ #define CT_RSELTMO 0x0A /* reselection timeout after 2 tries */ #define CT_TIMEOUT 0x0B /* timed out */ #define CT_RESET 0x0E /* SCSI Bus Reset occurred */ #define CT_PARITY 0x0F /* Uncorrectable Parity Error */ +#define CT_BUS_ERROR 0x10 /* (FC Only) DMA PCI Error */ #define CT_PANIC 0x13 /* Unrecoverable Error */ #define CT_PHASE_ERROR 0x14 /* Bus phase sequence error */ #define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */ +#define CT_DATA_UNDER 0x15 /* (FC only) Data Underrun */ #define CT_TERMINATED 0x19 /* due to Terminate Transfer mbox cmd */ #define CT_PORTNOTAVAIL 0x28 /* port not available */ #define CT_LOGOUT 0x29 /* port logout */ @@ -682,10 +685,11 @@ int isp_target_notify(struct ispsoftc *, void *, u_int16_t *); /* * Enable/Disable/Modify a logical unit. + * (softc, cmd, bus, tgt, lun, cmd_cnt, inotify_cnt, opaque) */ -#define DFLT_CMD_CNT 32 /* XX */ -#define DFLT_INOTIFY (4) -int isp_lun_cmd(struct ispsoftc *, int, int, int, int, u_int32_t); +#define DFLT_CMND_CNT 32 +#define DFLT_INOT_CNT 4 +int isp_lun_cmd(struct ispsoftc *, int, int, int, int, int, int, u_int32_t); /* * General request queue 'put' routine for target mode entries. diff --git a/sys/dev/isp/isp_tpublic.h b/sys/dev/isp/isp_tpublic.h index 03f832d..4a03c99 100644 --- a/sys/dev/isp/isp_tpublic.h +++ b/sys/dev/isp/isp_tpublic.h @@ -223,11 +223,12 @@ typedef struct tmd_cmd { u_int8_t cd_reserved[_TMD_PAD_LEN]; } tmd_cmd_t; -#define CDFL_BUSY 0x01 /* this command is not on a free list */ +#define CDFL_SNSVALID 0x01 /* sense data (from f/w) valid */ #define CDFL_NODISC 0x02 /* disconnects disabled */ #define CDFL_SENTSENSE 0x04 /* last action sent sense data */ #define CDFL_SENTSTATUS 0x08 /* last action sent status */ #define CDFL_ERROR 0x10 /* last action ended in error */ +#define CDFL_BUSY 0x40 /* this command is not on a free list */ #define CDFL_PRIVATE_0 0x80 /* private layer flags */ #define CDFH_SNSVALID 0x01 /* sense data valid */ diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index fa30e61..35c778a 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -469,6 +469,7 @@ typedef struct ispsoftc { #define ISP_HA_FC 0xf0 #define ISP_HA_FC_2100 0x10 #define ISP_HA_FC_2200 0x20 +#define ISP_HA_FC_2300 0x30 #define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI) #define IS_1240(isp) (isp->isp_type == ISP_HA_SCSI_1240) @@ -481,9 +482,13 @@ typedef struct ispsoftc { #define IS_ULTRA2(isp) (IS_1080(isp) || IS_1280(isp) || IS_12160(isp)) #define IS_ULTRA3(isp) (IS_12160(isp)) -#define IS_FC(isp) (isp->isp_type & ISP_HA_FC) -#define IS_2100(isp) (isp->isp_type == ISP_HA_FC_2100) -#define IS_2200(isp) (isp->isp_type == ISP_HA_FC_2200) +#define IS_FC(isp) ((isp)->isp_type & ISP_HA_FC) +#define IS_2100(isp) ((isp)->isp_type == ISP_HA_FC_2100) +#define IS_2200(isp) ((isp)->isp_type == ISP_HA_FC_2200) +#define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300) + +/* 2300 Support isn't ready yet */ +#define ISP_DISABLE_2300_SUPPORT 1 /* * DMA cookie macros @@ -628,6 +633,8 @@ typedef enum { ISPASYNC_BUS_RESET, /* Bus Was Reset */ ISPASYNC_LOOP_DOWN, /* FC Loop Down */ ISPASYNC_LOOP_UP, /* FC Loop Up */ + ISPASYNC_LIP, /* LIP Received */ + ISPASYNC_LOOP_RESET, /* Loop Reset Received */ ISPASYNC_CHANGE_NOTIFY, /* FC Change Notification */ ISPASYNC_FABRIC_DEV, /* FC Fabric Device Arrival */ ISPASYNC_PROMENADE, /* FC Objects coming && going */ @@ -780,7 +787,6 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); * ISP_SWIZZLE_SNS_REQ * ISP_UNSWIZZLE_SNS_RSP * ISP_SWIZZLE_NVRAM_WORD - * - * */ + #endif /* _ISPVAR_H */ |