diff options
author | mjacob <mjacob@FreeBSD.org> | 2001-05-28 21:20:43 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2001-05-28 21:20:43 +0000 |
commit | 19b20edd4063454edfe9d46a08ec2249527d1e8b (patch) | |
tree | 2ff029f1c3035ecb1a70ed1b7e80e5a0ed1b794c | |
parent | f80decdc0cdb69cc9099b1ba2b51651e287082f2 (diff) | |
download | FreeBSD-src-19b20edd4063454edfe9d46a08ec2249527d1e8b.zip FreeBSD-src-19b20edd4063454edfe9d46a08ec2249527d1e8b.tar.gz |
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
-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 */ |