summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/isp/isp.c17
-rw-r--r--sys/dev/isp/isp_freebsd.c486
-rw-r--r--sys/dev/isp/isp_freebsd.h58
-rw-r--r--sys/dev/isp/isp_ioctl.h76
-rw-r--r--sys/dev/isp/isp_pci.c71
-rw-r--r--sys/dev/isp/isp_target.c83
-rw-r--r--sys/dev/isp/isp_target.h10
-rw-r--r--sys/dev/isp/isp_tpublic.h3
-rw-r--r--sys/dev/isp/ispvar.h16
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 */
OpenPOWER on IntegriCloud