summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2000-08-27 23:38:44 +0000
committermjacob <mjacob@FreeBSD.org>2000-08-27 23:38:44 +0000
commitbcbec50333d0c724a16c70ce1cf20a68bee1a2c6 (patch)
tree993bb0165c73046e65558d492e5b2433535cd518 /sys
parenteca2daf851d818a319657461a5e5d39ca0950912 (diff)
downloadFreeBSD-src-bcbec50333d0c724a16c70ce1cf20a68bee1a2c6.zip
FreeBSD-src-bcbec50333d0c724a16c70ce1cf20a68bee1a2c6.tar.gz
various fixes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/isp/isp.c447
-rw-r--r--sys/dev/isp/isp_freebsd.c94
-rw-r--r--sys/dev/isp/isp_freebsd.h24
-rw-r--r--sys/dev/isp/isp_inline.h10
-rw-r--r--sys/dev/isp/isp_target.c6
-rw-r--r--sys/dev/isp/ispmbox.h44
-rw-r--r--sys/dev/isp/ispvar.h25
7 files changed, 409 insertions, 241 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 891527c..e477fc8 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -595,7 +595,9 @@ again:
isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure");
return;
}
+ isp->isp_loaded_fw = 1;
} else {
+ isp->isp_loaded_fw = 0;
isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
}
@@ -750,7 +752,7 @@ isp_scsi_init(isp)
/*
* If we have fast memory timing enabled, turn it on.
*/
- if (isp->isp_fast_mttr) {
+ if (sdp_chan0->isp_fast_mttr) {
ISP_WRITE(isp, RISC_MTR, 0x1313);
}
@@ -923,87 +925,51 @@ isp_scsi_channel_init(isp, channel)
if (sdp->isp_devparam[tgt].dev_enable == 0) {
continue;
}
-
+ sdf = DPARM_SAFE_DFLT;
/*
- * If we're in LVD mode, then we pretty much should
- * only disable tagged queuing.
+ * It is not quite clear when this changed over so that
+ * we could force narrow and async for 1000/1020 cards,
+ * but assume that this is only the case for loaded
+ * firmware.
*/
- if (IS_ULTRA2(isp) && sdp->isp_lvdmode) {
- sdf = DPARM_DEFAULT & ~DPARM_TQING;
- } else {
- int rvf = ISP_FW_REVX(isp->isp_fwrev);
- sdf = DPARM_SAFE_DFLT;
-
- /*
- * It is not quite clear when this changed over so that
- * we could force narrow and async, so assume >= 7.55
- * for i/t F/W and = 4.55 for initiator f/w.
- */
- if ((ISP_FW_REV(4, 55, 0) <= rvf &&
- (ISP_FW_REV(5, 0, 0) > rvf)) ||
- (ISP_FW_REV(7, 55, 0) <= rvf)) {
- sdf |= DPARM_NARROW | DPARM_ASYNC;
- }
+ if (isp->isp_loaded_fw) {
+ sdf |= DPARM_NARROW | DPARM_ASYNC;
}
mbs.param[0] = MBOX_SET_TARGET_PARAMS;
mbs.param[1] = (tgt << 8) | (channel << 15);
mbs.param[2] = sdf;
- mbs.param[3] =
- (sdp->isp_devparam[tgt].sync_offset << 8) |
- (sdp->isp_devparam[tgt].sync_period);
+ if ((sdf & DPARM_SYNC) == 0) {
+ mbs.param[3] = 0;
+ } else {
+ mbs.param[3] =
+ (sdp->isp_devparam[tgt].sync_offset << 8) |
+ (sdp->isp_devparam[tgt].sync_period);
+ }
isp_mboxcmd(isp, &mbs, MBLOGALL);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
sdf = DPARM_SAFE_DFLT;
mbs.param[0] = MBOX_SET_TARGET_PARAMS;
mbs.param[1] = (tgt << 8) | (channel << 15);
mbs.param[2] = sdf;
- mbs.param[3] =
- (sdp->isp_devparam[tgt].sync_offset << 8) |
- (sdp->isp_devparam[tgt].sync_period);
+ mbs.param[3] = 0;
isp_mboxcmd(isp, &mbs, MBLOGALL);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
continue;
}
}
-#if 0
- /*
- * We don't update dev_flags with what we've set
- * because that's not the ultimate goal setting.
- * If we succeed with the command, we *do* update
- * cur_dflags by getting target parameters.
- */
- mbs.param[0] = MBOX_GET_TARGET_PARAMS;
- mbs.param[1] = (tgt << 8) | (channel << 15);
- isp_mboxcmd(isp, &mbs, MBLOGALL);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- /*
- * Urrr.... We'll set cur_dflags to DPARM_SAFE_DFLT so
- * we don't try and do tags if tags aren't enabled.
- */
- sdp->isp_devparam[tgt].cur_dflags = DPARM_SAFE_DFLT;
- } else {
- sdp->isp_devparam[tgt].cur_dflags = mbs.param[2];
- sdp->isp_devparam[tgt].cur_offset = mbs.param[3] >> 8;
- sdp->isp_devparam[tgt].cur_period = mbs.param[3] & 0xff;
- }
- isp_prt(isp, ISP_LOGTDEBUG0,
- "set flags 0x%x got 0x%x back for target %d",
- sdf, mbs.param[2], tgt);
-#else
- /*
- * We don't update any information because we need to run
- * at least one command per target to cause a new state
- * to be latched.
- */
-#endif
/*
+ * We don't update any information directly from the f/w
+ * because we need to run at least one command to cause a
+ * new state to be latched up. So, we just assume that we
+ * converge to the values we just had set.
+ *
* Ensure that we don't believe tagged queuing is enabled yet.
* It turns out that sometimes the ISP just ignores our
* attempts to set parameters for devices that it hasn't
* seen yet.
*/
- sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING;
+ sdp->isp_devparam[tgt].cur_dflags = sdf & ~DPARM_TQING;
for (lun = 0; lun < (int) isp->isp_maxluns; lun++) {
mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
mbs.param[1] = (channel << 15) | (tgt << 8) | lun;
@@ -1015,6 +981,13 @@ isp_scsi_channel_init(isp, channel)
}
}
}
+ for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
+ if (sdp->isp_devparam[tgt].dev_refresh) {
+ isp->isp_sendmarker |= (1 << channel);
+ isp->isp_update |= (1 << channel);
+ break;
+ }
+ }
}
/*
@@ -1038,20 +1011,21 @@ isp_fibre_init(isp)
MEMZERO(icbp, sizeof (*icbp));
icbp->icb_version = ICB_VERSION1;
-#ifdef ISP_TARGET_MODE
- fcp->isp_fwoptions = ICBOPT_TGT_ENABLE;
-#else
- fcp->isp_fwoptions = 0;
-#endif
- fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
+
+ /*
+ * Firmware Options are either retrieved from NVRAM or
+ * are patched elsewhere. We check them for sanity here
+ * and make changes based on board revision, but otherwise
+ * let others decide policy.
+ */
+
/*
* If this is a 2100 < revision 5, we have to turn off FAIRNESS.
*/
if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) {
fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS;
}
- fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
- fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
+
/*
* We have to use FULL LOGIN even though it resets the loop too much
* because otherwise port database entries don't get updated after
@@ -1060,11 +1034,11 @@ isp_fibre_init(isp)
if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) {
fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
}
-#ifndef ISP_NO_FASTPOST_FC
- fcp->isp_fwoptions |= ICBOPT_FAST_POST;
-#endif
- if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
- fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
+
+ /*
+ * Insist on Port Database Update Async notifications
+ */
+ fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
/*
* We don't set ICBOPT_PORTNAME because we want our
@@ -1096,7 +1070,10 @@ isp_fibre_init(isp)
icbp->icb_retry_delay = fcp->isp_retry_delay;
icbp->icb_retry_count = fcp->isp_retry_count;
icbp->icb_hardaddr = loopid;
-#ifdef PRET_A_PORTE
+ /*
+ * Right now we just set extended options to prefer point-to-point
+ * over loop based upon some soft config options.
+ */
if (IS_2200(isp)) {
icbp->icb_fwoptions |= ICBOPT_EXTENDED;
/*
@@ -1107,7 +1084,6 @@ isp_fibre_init(isp)
else
icbp->icb_xfwoptions = ICBXOPT_LOOP_2_PTP;
}
-#endif
icbp->icb_logintime = 60; /* 60 second login timeout */
if (fcp->isp_nodewwn) {
@@ -1122,6 +1098,8 @@ isp_fibre_init(isp)
icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_rquest_dma);
icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_result_dma);
icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_result_dma);
+ isp_prt(isp, ISP_LOGDEBUG1,
+ "isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions);
ISP_SWIZZLE_ICB(isp, icbp);
/*
@@ -1293,7 +1271,8 @@ isp_fclink_test(isp, usdelay)
* waiting.
*/
isp_prt(isp, ISP_LOGDEBUG3, "usec%d: 0x%lx->0x%lx enano %u",
- count, GET_NANOSEC(&hra), GET_NANOSEC(&hrb), enano);
+ count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb),
+ enano);
/*
* This peculiar code is an attempt to try and avoid
@@ -2222,6 +2201,10 @@ isp_start(xs)
if (XS_TAG_P(xs)) {
t2reqp->req_flags = XS_TAG_TYPE(xs);
} else {
+ /*
+ * If we don't know what tag to use, use HEAD OF QUEUE
+ * for Request Sense or Ordered (for safety's sake).
+ */
if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */
t2reqp->req_flags = REQFLAG_HTAG;
else
@@ -2381,6 +2364,10 @@ isp_control(isp, ctl, arg)
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
return (0);
}
+ /*
+ * XXX: Look for command in the REQUEST QUEUE. That is,
+ * XXX: It hasen't been picked up by firmware yet.
+ */
break;
case ISPCTL_UPDATE_PARAMS:
@@ -2399,19 +2386,46 @@ isp_control(isp, ctl, arg)
return (isp_pdb_sync(isp, -1));
}
break;
-
#ifdef ISP_TARGET_MODE
case ISPCTL_TOGGLE_TMODE:
+ {
+ int ena = *(int *)arg;
if (IS_SCSI(isp)) {
- int ena = *(int *)arg;
mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
mbs.param[1] = (ena)? ENABLE_TARGET_FLAG : 0;
isp_mboxcmd(isp, &mbs, MBLOGALL);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
break;
}
+ } else {
+ fcparam *fcp = isp->isp_param;
+ /*
+ * We assume somebody has quiesced this bus.
+ */
+ if (ena) {
+ if (fcp->isp_fwoptions & ICBOPT_TGT_ENABLE) {
+ return (0);
+ }
+ fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE;
+ } else {
+ if (!(fcp->isp_fwoptions & ICBOPT_TGT_ENABLE)) {
+ return (0);
+ }
+ fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE;
+ }
+ isp->isp_state = ISP_NILSTATE;
+ isp_reset(isp);
+ if (isp->isp_state != ISP_RESETSTATE) {
+ break;
+ }
+ isp_init(isp);
+ if (isp->isp_state != ISP_INITSTATE) {
+ break;
+ }
+ isp->isp_state = ISP_RUNSTATE;
}
return (0);
+ }
#endif
}
return (-1);
@@ -2590,6 +2604,7 @@ isp_intr(arg)
ISP_UNSWIZZLE_RESPONSE(isp, sp, oop);
if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) {
if (isp_handle_other_response(isp, sp, &optr) == 0) {
+ MEMZERO(sp, sizeof (isphdr_t));
continue;
}
/*
@@ -2600,6 +2615,7 @@ isp_intr(arg)
if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) {
isp_prt(isp, ISP_LOGERR, notresp,
sp->req_header.rqs_entry_type, oop, optr);
+ MEMZERO(sp, sizeof (isphdr_t));
continue;
}
buddaboom = 1;
@@ -2638,6 +2654,7 @@ isp_intr(arg)
#undef _RQS_OFLAGS
}
if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) {
+ MEMZERO(sp, sizeof (isphdr_t));
isp_prt(isp, ISP_LOGERR,
"bad request handle %d", sp->req_handle);
ISP_WRITE(isp, INMAILBOX5, optr);
@@ -2645,6 +2662,7 @@ isp_intr(arg)
}
xs = isp_find_xs(isp, sp->req_handle);
if (xs == NULL) {
+ MEMZERO(sp, sizeof (isphdr_t));
isp_prt(isp, ISP_LOGERR,
"cannot find handle 0x%x in xflist",
sp->req_handle);
@@ -2658,38 +2676,65 @@ isp_intr(arg)
if (buddaboom) {
XS_SETERR(xs, HBA_BOTCH);
}
- *XS_STSP(xs) = sp->req_scsi_status & 0xff;
- if (IS_SCSI(isp)) {
- if (sp->req_state_flags & RQSF_GOT_SENSE) {
- XS_SAVE_SENSE(xs, sp);
- }
+
+ if (IS_FC(isp) && (sp->req_scsi_status & RQCS_SV)) {
/*
- * A new synchronous rate was negotiated for this
- * target. Mark state such that we'll go look up
- * that which has changed later.
+ * Fibre Channel F/W doesn't say we got status
+ * if there's Sense Data instead. I guess they
+ * think it goes w/o saying.
*/
- if (sp->req_status_flags & RQSTF_NEGOTIATION) {
- sdparam *sdp = isp->isp_param;
- sdp += XS_CHANNEL(xs);
- sdp->isp_devparam[XS_TGT(xs)].dev_refresh = 1;
- isp->isp_update |= (1 << XS_CHANNEL(xs));
- }
- } else {
- if (sp->req_scsi_status & RQCS_SV) {
- XS_SAVE_SENSE(xs, sp);
- /* force that we 'got' sense */
- sp->req_state_flags |= RQSF_GOT_SENSE;
- }
+ sp->req_state_flags |= RQSF_GOT_STATUS;
+ }
+ if (sp->req_state_flags & RQSF_GOT_STATUS) {
+ *XS_STSP(xs) = sp->req_scsi_status & 0xff;
}
- if (sp->req_header.rqs_entry_type == RQSTYPE_RESPONSE) {
+ switch (sp->req_header.rqs_entry_type) {
+ case RQSTYPE_RESPONSE:
XS_SET_STATE_STAT(isp, xs, sp);
isp_parse_status(isp, sp, xs);
if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
(*XS_STSP(xs) == SCSI_BUSY)) {
XS_SETERR(xs, HBA_TGTBSY);
}
- } else if (sp->req_header.rqs_entry_type == RQSTYPE_REQUEST) {
+ if (IS_SCSI(isp)) {
+ XS_RESID(xs) = sp->req_resid;
+ if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
+ (*XS_STSP(xs) == SCSI_CHECK) &&
+ (sp->req_state_flags & RQSF_GOT_SENSE)) {
+ XS_SAVE_SENSE(xs, sp);
+ }
+ /*
+ * A new synchronous rate was negotiated for
+ * this target. Mark state such that we'll go
+ * look up that which has changed later.
+ */
+ if (sp->req_status_flags & RQSTF_NEGOTIATION) {
+ int t = XS_TGT(xs);
+ sdparam *sdp = isp->isp_param;
+ sdp += XS_CHANNEL(xs);
+ sdp->isp_devparam[t].dev_refresh = 1;
+ isp->isp_update |=
+ (1 << XS_CHANNEL(xs));
+ }
+ } else {
+ if (sp->req_status_flags & RQSF_XFER_COMPLETE) {
+ XS_RESID(xs) = 0;
+ } else if (sp->req_scsi_status & RQCS_RESID) {
+ XS_RESID(xs) = sp->req_resid;
+ } else {
+ XS_RESID(xs) = 0;
+ }
+ if ((sp->req_state_flags & RQSF_GOT_STATUS) &&
+ (*XS_STSP(xs) == SCSI_CHECK) &&
+ (sp->req_scsi_status & RQCS_SV)) {
+ XS_SAVE_SENSE(xs, sp);
+ }
+ }
+ isp_prt(isp, ISP_LOGDEBUG2, "asked for %d got resid %d",
+ XS_XFRLEN(xs), sp->req_resid);
+ break;
+ case RQSTYPE_REQUEST:
if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
/*
* Force Queue Full status.
@@ -2699,24 +2744,25 @@ isp_intr(arg)
} else if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_BOTCH);
}
- } else {
+ XS_RESID(xs) = XS_XFRLEN(xs);
+ break;
+ default:
isp_prt(isp, ISP_LOGWARN,
"unhandled respose queue type 0x%x",
sp->req_header.rqs_entry_type);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_BOTCH);
}
+ break;
}
- if (IS_SCSI(isp)) {
- XS_RESID(xs) = sp->req_resid;
- } else if (sp->req_scsi_status & RQCS_RV) {
- XS_RESID(xs) = sp->req_resid;
- isp_prt(isp, ISP_LOGDEBUG2, "cnt %d rsd %d",
- XS_XFRLEN(xs), sp->req_resid);
- }
+
+ /*
+ * Free any dma resources. As a side effect, this may
+ * also do any cache flushing necessary for data coherence. */
if (XS_XFRLEN(xs)) {
ISP_DMAFREE(isp, xs, sp->req_handle);
}
+
if (((isp->isp_dblev & (ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
((isp->isp_dblev & ISP_LOGDEBUG1) && !XS_NOERR(xs))) {
char skey;
@@ -2739,6 +2785,7 @@ isp_intr(arg)
if (isp->isp_nactive > 0)
isp->isp_nactive--;
complist[ndone++] = xs; /* defer completion call until later */
+ MEMZERO(sp, sizeof (isphdr_t));
if (ndone == MAX_REQUESTQ_COMPLETIONS) {
break;
}
@@ -2783,8 +2830,6 @@ isp_parse_async(isp, mbox)
}
switch (mbox) {
- case MBOX_COMMAND_COMPLETE: /* sometimes these show up */
- break;
case ASYNC_BUS_RESET:
isp->isp_sendmarker |= (1 << bus);
#ifdef ISP_TARGET_MODE
@@ -2857,23 +2902,23 @@ isp_parse_async(isp, mbox)
switch (mbox & 0x1c00) {
case SXP_PINS_LVD_MODE:
isp_prt(isp, ISP_LOGINFO, "Transition to LVD mode");
- ((sdparam *)isp->isp_param)->isp_diffmode = 0;
- ((sdparam *)isp->isp_param)->isp_ultramode = 0;
- ((sdparam *)isp->isp_param)->isp_lvdmode = 1;
+ SDPARAM(isp)->isp_diffmode = 0;
+ SDPARAM(isp)->isp_ultramode = 0;
+ SDPARAM(isp)->isp_lvdmode = 1;
break;
case SXP_PINS_HVD_MODE:
isp_prt(isp, ISP_LOGINFO,
"Transition to Differential mode");
- ((sdparam *)isp->isp_param)->isp_diffmode = 1;
- ((sdparam *)isp->isp_param)->isp_ultramode = 0;
- ((sdparam *)isp->isp_param)->isp_lvdmode = 0;
+ SDPARAM(isp)->isp_diffmode = 1;
+ SDPARAM(isp)->isp_ultramode = 0;
+ SDPARAM(isp)->isp_lvdmode = 0;
break;
case SXP_PINS_SE_MODE:
isp_prt(isp, ISP_LOGINFO,
"Transition to Single Ended mode");
- ((sdparam *)isp->isp_param)->isp_diffmode = 0;
- ((sdparam *)isp->isp_param)->isp_ultramode = 1;
- ((sdparam *)isp->isp_param)->isp_lvdmode = 0;
+ SDPARAM(isp)->isp_diffmode = 0;
+ SDPARAM(isp)->isp_ultramode = 1;
+ SDPARAM(isp)->isp_lvdmode = 0;
break;
default:
isp_prt(isp, ISP_LOGWARN,
@@ -2895,15 +2940,24 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_CTIO_DONE:
- /* Should only occur when Fast Posting Set for 2100s */
- isp_prt(isp, ISP_LOGDEBUG3, "Fast Posting CTIO done");
+#ifdef ISP_TARGET_MODE
+ /*
+ * Bus gets overloaded with the handle. Dual bus
+ * cards don't put bus# into the handle.
+ */
+ bus = (ISP_READ(isp, OUTMAILBOX2) << 16) |
+ ISP_READ(isp, OUTMAILBOX1);
+ isp_target_async(isp, bus, mbox);
+#else
+ isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done");
+#endif
break;
case ASYNC_LIP_OCCURRED:
- ((fcparam *) isp->isp_param)->isp_lipseq =
+ FCPARAM(isp)->isp_lipseq =
ISP_READ(isp, OUTMAILBOX1);
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
+ FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+ FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
isp->isp_sendmarker = 1;
isp_mark_getpdb_all(isp);
isp_prt(isp, ISP_LOGINFO, "LIP occurred");
@@ -2914,8 +2968,8 @@ isp_parse_async(isp, mbox)
case ASYNC_LOOP_UP:
isp->isp_sendmarker = 1;
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
+ FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+ FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
isp_mark_getpdb_all(isp);
isp_async(isp, ISPASYNC_LOOP_UP, NULL);
#ifdef ISP_TARGET_MODE
@@ -2925,8 +2979,8 @@ isp_parse_async(isp, mbox)
case ASYNC_LOOP_DOWN:
isp->isp_sendmarker = 1;
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL;
+ FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+ FCPARAM(isp)->isp_loopstate = LOOP_NIL;
isp_mark_getpdb_all(isp);
isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
#ifdef ISP_TARGET_MODE
@@ -2936,8 +2990,8 @@ isp_parse_async(isp, mbox)
case ASYNC_LOOP_RESET:
isp->isp_sendmarker = 1;
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL;
+ 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");
#ifdef ISP_TARGET_MODE
@@ -2947,7 +3001,7 @@ isp_parse_async(isp, mbox)
case ASYNC_PDB_CHANGED:
isp->isp_sendmarker = 1;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
+ FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
isp_mark_getpdb_all(isp);
isp_prt(isp, ISP_LOGINFO, "Port Database Changed");
break;
@@ -2957,19 +3011,19 @@ isp_parse_async(isp, mbox)
/*
* Not correct, but it will force us to rescan the loop.
*/
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
+ FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, NULL);
break;
case ASYNC_PTPMODE:
- if (((fcparam *) isp->isp_param)->isp_onfabric)
- ((fcparam *) isp->isp_param)->isp_topo = TOPO_N_PORT;
+ if (FCPARAM(isp)->isp_onfabric)
+ FCPARAM(isp)->isp_topo = TOPO_N_PORT;
else
- ((fcparam *) isp->isp_param)->isp_topo = TOPO_F_PORT;
+ FCPARAM(isp)->isp_topo = TOPO_F_PORT;
isp_mark_getpdb_all(isp);
isp->isp_sendmarker = 1;
- ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
- ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
+ FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+ FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
#ifdef ISP_TARGET_MODE
isp_target_async(isp, bus, mbox);
#endif
@@ -3021,6 +3075,9 @@ isp_handle_other_response(isp, sp, optrp)
u_int16_t *optrp;
{
switch (sp->req_header.rqs_entry_type) {
+ case RQSTYPE_STATUS_CONT:
+ isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response");
+ return (0);
case RQSTYPE_ATIO:
case RQSTYPE_CTIO:
case RQSTYPE_ENABLE_LUN:
@@ -3060,7 +3117,7 @@ isp_parse_status(isp, sp, xs)
case RQCS_INCOMPLETE:
if ((sp->req_state_flags & RQSF_GOT_TARGET) == 0) {
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGDEBUG1,
"Selection Timeout for %d.%d.%d",
XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
if (XS_NOERR(xs)) {
@@ -3163,10 +3220,7 @@ isp_parse_status(isp, sp, xs)
return;
case RQCS_DATA_OVERRUN:
- if (IS_FC(isp)) {
- XS_RESID(xs) = sp->req_resid;
- break;
- }
+ XS_RESID(xs) = sp->req_resid;
isp_prt(isp, ISP_LOGERR, "data overrun for command on %d.%d.%d",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
if (XS_NOERR(xs)) {
@@ -3247,9 +3301,7 @@ isp_parse_status(isp, sp, xs)
break;
case RQCS_DATA_UNDERRUN:
- if (IS_FC(isp)) {
- XS_RESID(xs) = sp->req_resid;
- }
+ XS_RESID(xs) = sp->req_resid;
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_NOERROR);
}
@@ -3414,9 +3466,9 @@ isp_fastpost_complete(isp, fph)
if (XS_XFRLEN(xs)) {
ISP_DMAFREE(isp, xs, fph);
}
- isp_done(xs);
if (isp->isp_nactive)
isp->isp_nactive--;
+ isp_done(xs);
}
#define HIBYT(x) ((x) >> 0x8)
@@ -4040,13 +4092,13 @@ static void
isp_update(isp)
struct ispsoftc *isp;
{
- int bus;
+ int bus, upmask;
- for (bus = 0; isp->isp_update != 0; bus++) {
- if (isp->isp_update & (1 << bus)) {
+ for (bus = 0, upmask = isp->isp_update; upmask != 0; bus++) {
+ if (upmask & (1 << bus)) {
isp_update_bus(isp, bus);
- isp->isp_update ^= (1 << bus);
}
+ upmask &= ~(1 << bus);
}
}
@@ -4059,10 +4111,13 @@ isp_update_bus(isp, bus)
mbreg_t mbs;
sdparam *sdp;
+ isp->isp_update &= ~(1 << bus);
if (IS_FC(isp)) {
+ /*
+ * There are no 'per-bus' settings for Fibre Channel.
+ */
return;
}
-
sdp = isp->isp_param;
sdp += bus;
@@ -4071,35 +4126,57 @@ isp_update_bus(isp, bus)
int get;
if (sdp->isp_devparam[tgt].dev_enable == 0) {
+ sdp->isp_devparam[tgt].dev_update = 0;
+ sdp->isp_devparam[tgt].dev_refresh = 0;
isp_prt(isp, ISP_LOGDEBUG1,
"skipping target %d bus %d update", tgt, bus);
continue;
}
-
/*
* If the goal is to update the status of the device,
* take what's in dev_flags and try and set the device
* toward that. Otherwise, if we're just refreshing the
* current device state, get the current parameters.
*/
- if (sdp->isp_devparam[tgt].dev_update) {
+
+ /*
+ * Refresh overrides set
+ */
+ if (sdp->isp_devparam[tgt].dev_refresh) {
+ mbs.param[0] = MBOX_GET_TARGET_PARAMS;
+ sdp->isp_devparam[tgt].dev_refresh = 0;
+ get = 1;
+ } else if (sdp->isp_devparam[tgt].dev_update) {
mbs.param[0] = MBOX_SET_TARGET_PARAMS;
+ /*
+ * Make sure dev_flags has "Renegotiate on Error"
+ * on and "Freeze Queue on Error" off.
+ */
+ sdp->isp_devparam[tgt].dev_flags |= DPARM_RENEG;
+ sdp->isp_devparam[tgt].dev_flags &= ~DPARM_QFRZ;
+
mbs.param[2] = sdp->isp_devparam[tgt].dev_flags;
+
/*
- * Insist that PARITY must be enabled if SYNC
- * is enabled.
+ * Insist that PARITY must be enabled
+ * if SYNC or WIDE is enabled.
*/
- if (mbs.param[2] & DPARM_SYNC) {
+ if ((mbs.param[2] & (DPARM_SYNC|DPARM_WIDE)) != 0) {
mbs.param[2] |= DPARM_PARITY;
}
- mbs.param[3] =
- (sdp->isp_devparam[tgt].sync_offset << 8) |
- (sdp->isp_devparam[tgt].sync_period);
- sdp->isp_devparam[tgt].dev_update = 0;
+
+ if ((mbs.param[2] & DPARM_SYNC) == 0) {
+ mbs.param[3] = 0;
+ } else {
+ mbs.param[3] =
+ (sdp->isp_devparam[tgt].sync_offset << 8) |
+ (sdp->isp_devparam[tgt].sync_period);
+ }
/*
* A command completion later that has
- * RQSTF_NEGOTIATION set will cause
- * the dev_refresh/announce cycle.
+ * RQSTF_NEGOTIATION set canl cause
+ * the dev_refresh/announce cycle also.
+ &
*
* Note: It is really important to update our current
* flags with at least the state of TAG capabilities-
@@ -4110,16 +4187,13 @@ isp_update_bus(isp, bus)
sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING;
sdp->isp_devparam[tgt].cur_dflags |=
(sdp->isp_devparam[tgt].dev_flags & DPARM_TQING);
- sdp->isp_devparam[tgt].dev_refresh = 1;
isp_prt(isp, ISP_LOGDEBUG2,
"bus %d set tgt %d flags 0x%x off 0x%x period 0x%x",
bus, tgt, mbs.param[2], mbs.param[3] >> 8,
mbs.param[3] & 0xff);
+ sdp->isp_devparam[tgt].dev_update = 0;
+ sdp->isp_devparam[tgt].dev_refresh = 1;
get = 0;
- } else if (sdp->isp_devparam[tgt].dev_refresh) {
- mbs.param[0] = MBOX_GET_TARGET_PARAMS;
- sdp->isp_devparam[tgt].dev_refresh = 0;
- get = 1;
} else {
continue;
}
@@ -4138,6 +4212,14 @@ isp_update_bus(isp, bus)
get = (bus << 16) | tgt;
(void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get);
}
+
+ for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
+ if (sdp->isp_devparam[tgt].dev_update ||
+ sdp->isp_devparam[tgt].dev_refresh) {
+ isp->isp_update |= (1 << bus);
+ break;
+ }
+ }
}
static void
@@ -4158,13 +4240,28 @@ isp_setdfltparm(isp, channel)
fcp->isp_gotdparms = 1;
fcp->isp_maxfrmlen = ICB_DFLT_FRMLEN;
fcp->isp_maxalloc = ICB_DFLT_ALLOC;
- fcp->isp_execthrottle = ICB_DFLT_THROTTLE;
+ fcp->isp_execthrottle = ISP_EXEC_THROTTLE;
fcp->isp_retry_delay = ICB_DFLT_RDELAY;
fcp->isp_retry_count = ICB_DFLT_RCOUNT;
/* Platform specific.... */
fcp->isp_loopid = DEFAULT_LOOPID(isp);
fcp->isp_nodewwn = DEFAULT_NODEWWN(isp);
fcp->isp_portwwn = DEFAULT_PORTWWN(isp);
+ fcp->isp_fwoptions = 0;
+ fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
+ fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
+ fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
+#ifndef ISP_NO_FASTPOST_FC
+ fcp->isp_fwoptions |= ICBOPT_FAST_POST;
+#endif
+ if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
+ fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
+
+ /*
+ * Make sure this is turned off now until we get
+ * extended options from NVRAM
+ */
+ fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
/*
* Now try and read NVRAM
@@ -4256,16 +4353,26 @@ isp_setdfltparm(isp, channel)
ISP_10M_SYNCPARMS >> 8;
sdp->isp_devparam[tgt].sync_period =
ISP_10M_SYNCPARMS & 0xff;
+ } else if (IS_ULTRA3(isp)) {
+ sdp->isp_devparam[tgt].sync_offset =
+ ISP_80M_SYNCPARMS >> 8;
+ sdp->isp_devparam[tgt].sync_period =
+ ISP_80M_SYNCPARMS & 0xff;
} else if (IS_ULTRA2(isp)) {
sdp->isp_devparam[tgt].sync_offset =
ISP_40M_SYNCPARMS >> 8;
sdp->isp_devparam[tgt].sync_period =
ISP_40M_SYNCPARMS & 0xff;
- } else {
+ } else if (IS_1240(isp)) {
sdp->isp_devparam[tgt].sync_offset =
ISP_20M_SYNCPARMS >> 8;
sdp->isp_devparam[tgt].sync_period =
ISP_20M_SYNCPARMS & 0xff;
+ } else {
+ sdp->isp_devparam[tgt].sync_offset =
+ ISP_20M_SYNCPARMS_1040 >> 8;
+ sdp->isp_devparam[tgt].sync_period =
+ ISP_20M_SYNCPARMS_1040 & 0xff;
}
/*
@@ -4313,7 +4420,7 @@ isp_setdfltparm(isp, channel)
}
}
isp_prt(isp, ISP_LOGDEBUG1,
- "bus %d tgt %d flags %x offset %x period %x",
+ "Initial bus %d tgt %d flags %x offset %x period %x",
channel, tgt, sdp->isp_devparam[tgt].dev_flags,
sdp->isp_devparam[tgt].sync_offset,
sdp->isp_devparam[tgt].sync_period);
@@ -4339,7 +4446,7 @@ isp_setdfltparm(isp, channel)
sdp->isp_retry_delay = 2;
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
- sdp->isp_devparam[tgt].exc_throttle = 16;
+ sdp->isp_devparam[tgt].exc_throttle = ISP_EXEC_THROTTLE;
sdp->isp_devparam[tgt].dev_enable = 1;
}
}
@@ -4589,7 +4696,7 @@ isp_parse_nvram_1020(isp, nvram_data)
sdp->isp_max_queue_depth =
ISP_NVRAM_MAX_QUEUE_DEPTH(nvram_data);
- isp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
+ sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
for (i = 0; i < MAX_TARGETS; i++) {
sdp->isp_devparam[i].dev_enable =
ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i);
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 05bd5eb..b38065b 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -2,11 +2,7 @@
/*
* Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
*
- *---------------------------------------
- * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
- * NASA/Ames Research Center
- * All rights reserved.
- *---------------------------------------
+ * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -17,8 +13,6 @@
* 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.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -164,7 +158,9 @@ isp_intr_enable(void *arg)
{
struct ispsoftc *isp = arg;
ENABLE_INTS(isp);
+#ifdef SERVICING_INTERRUPT
isp->isp_osinfo.intsok = 1;
+#endif
/* Release our hook so that the boot can continue. */
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
}
@@ -399,7 +395,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;
+ int bus, frozen = 0;
lun_id_t lun;
target_id_t tgt;
@@ -409,8 +405,45 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
lun = ccb->ccb_h.target_lun;
/*
- * First, check to see if we're enabling on fibre channel
- * and don't yet have a notion of who the heck we are (no
+ * Do some sanity checking first.
+ */
+
+ if (lun < 0 || lun >= (lun_id_t) isp->isp_maxluns) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ return;
+ }
+ if (IS_SCSI(isp)) {
+ if (tgt != CAM_TARGET_WILDCARD &&
+ tgt != ((sdparam *) isp->isp_param)->isp_initiator_id) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ return;
+ }
+ } else {
+ if (tgt != CAM_TARGET_WILDCARD &&
+ tgt != ((fcparam *) isp->isp_param)->isp_loopid) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ return;
+ }
+ }
+
+ /*
+ * If Fibre Channel, stop and drain all activity to this bus.
+ */
+ if (IS_FC(isp)) {
+ ISP_LOCK(isp);
+ frozen = 1;
+ xpt_freeze_simq(isp->isp_sim, 1);
+ isp->isp_osinfo.drain = 1;
+ /* ISP_UNLOCK(isp); XXX NEED CV_WAIT HERE XXX */
+ while (isp->isp_osinfo.drain) {
+ tsleep(&isp->isp_osinfo.drain, PRIBIO, "ispdrain", 0);
+ }
+ ISP_UNLOCK(isp);
+ }
+
+ /*
+ * Check to see if we're enabling on fibre channel and
+ * don't yet have a notion of who the heck we are (no
* loop yet).
*/
if (IS_FC(isp) && cel->enable &&
@@ -425,6 +458,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
xpt_print_path(ccb->ccb_h.path);
printf("link status not good yet\n");
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
ISP_LOCK(isp);
@@ -434,6 +469,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
xpt_print_path(ccb->ccb_h.path);
printf("could not get a good port database read\n");
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
}
@@ -450,6 +487,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
if (cel->enable) {
if (isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) {
ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
ccb->ccb_h.status =
@@ -458,6 +497,8 @@ 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)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
SLIST_INIT(&tptr->atios);
@@ -469,6 +510,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
xpt_free_path(tptr->owner);
ISP_UNLOCK(isp);
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
isp->isp_osinfo.tmflags |= TM_TMODE_ENABLED;
@@ -476,10 +519,14 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
} else {
if ((isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) {
ccb->ccb_h.status = CAM_LUN_INVALID;
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
if (are_any_luns_enabled(isp)) {
ccb->ccb_h.status = CAM_SCSI_BUSY;
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
av = 0;
@@ -488,6 +535,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
if (av) {
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
ISP_UNLOCK(isp);
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
isp->isp_osinfo.tmflags &= ~TM_TMODE_ENABLED;
@@ -496,30 +545,17 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
}
xpt_print_path(ccb->ccb_h.path);
printf(lfmt, (cel->enable) ? "en" : "dis");
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
return;
}
/*
- * Do some sanity checking first.
+ * We can move along now...
*/
- if (lun < 0 || lun >= (lun_id_t) isp->isp_maxluns) {
- ccb->ccb_h.status = CAM_LUN_INVALID;
- return;
- }
- if (IS_SCSI(isp)) {
- if (tgt != CAM_TARGET_WILDCARD &&
- tgt != ((sdparam *) isp->isp_param)->isp_initiator_id) {
- ccb->ccb_h.status = CAM_TID_INVALID;
- return;
- }
- } else {
- if (tgt != CAM_TARGET_WILDCARD &&
- tgt != ((fcparam *) isp->isp_param)->isp_loopid) {
- ccb->ccb_h.status = CAM_TID_INVALID;
- return;
- }
- }
+ if (frozen)
+ xpt_release_simq(isp->isp_sim, 1);
if (cel->enable) {
@@ -1417,7 +1453,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
if (isp->isp_state != ISP_RUNSTATE &&
ccb->ccb_h.func_code == XPT_SCSI_IO) {
ISP_LOCK(isp);
- DISABLE_INTS(isp);
isp_init(isp);
if (isp->isp_state != ISP_INITSTATE) {
ISP_UNLOCK(isp);
@@ -1430,7 +1465,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
return;
}
isp->isp_state = ISP_RUNSTATE;
- ENABLE_INTS(isp);
ISP_UNLOCK(isp);
}
isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 7a88c9f..e376c10 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -1,11 +1,7 @@
/* $FreeBSD$ */
/*
* Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions (CAM version)
- *---------------------------------------
- * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
- * NASA/Ames Research Center
- * All rights reserved.
- *---------------------------------------
+ * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -16,8 +12,6 @@
* 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.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -99,11 +93,15 @@ struct isposinfo {
struct cam_sim *sim2;
struct cam_path *path2;
struct intr_config_hook ehook;
- volatile u_int16_t : 14,
- islocked : 1,
- intsok : 1;
u_int8_t mboxwaiting;
u_int8_t simqfrozen;
+ u_int8_t drain;
+#ifdef SERVICING_INTERRUPT
+ u_int8_t intsok;
+#else
+ u_int8_t padding;
+#endif
+ volatile u_int32_t islocked;
int splsaved;
#ifdef ISP_TARGET_MODE
#define TM_WANTED 0x01
@@ -314,8 +312,7 @@ static INLINE void
isp_lock(struct ispsoftc *isp)
{
int s = splcam();
- if (isp->isp_osinfo.islocked == 0) {
- isp->isp_osinfo.islocked = 1;
+ if (isp->isp_osinfo.islocked++ == 0) {
isp->isp_osinfo.splsaved = s;
} else {
splx(s);
@@ -326,8 +323,7 @@ static INLINE void isp_unlock(struct ispsoftc *);
static INLINE void
isp_unlock(struct ispsoftc *isp)
{
- if (isp->isp_osinfo.islocked) {
- isp->isp_osinfo.islocked = 0;
+ if (--isp->isp_osinfo.islocked == 0) {
splx(isp->isp_osinfo.splsaved);
}
}
diff --git a/sys/dev/isp/isp_inline.h b/sys/dev/isp/isp_inline.h
index 8c086b9..a32461e 100644
--- a/sys/dev/isp/isp_inline.h
+++ b/sys/dev/isp/isp_inline.h
@@ -83,7 +83,7 @@ isp_save_xs(isp, xs, handlep)
*handlep = j+1;
if (++j == isp->isp_maxcmds)
j = 0;
- isp->isp_lasthdls = j;
+ isp->isp_lasthdls = (u_int16_t)j;
return (0);
}
@@ -206,18 +206,20 @@ isp_print_bytes(isp, msg, amt, arg)
u_int8_t *ptr = arg;
int off;
+ if (msg)
+ isp_prt(isp, ISP_LOGALL, "%s:", msg);
off = 0;
+ buf[0] = 0;
while (off < amt) {
int j, to;
to = off;
- SNPRINTF(buf, 128, "<");
for (j = 0; j < 16; j++) {
SNPRINTF(buf, 128, "%s %02x", buf, ptr[off++] & 0xff);
if (off == amt)
break;
}
- isp_prt(isp, ISP_LOGALL,
- "<%s>offset=0x%x:\n%s>", msg, to, buf);
+ isp_prt(isp, ISP_LOGALL, "0x%08x:%s", to, buf);
+ buf[0] = 0;
}
}
#endif /* _ISP_INLINE_H */
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c
index dced16c..b7c4632 100644
--- a/sys/dev/isp/isp_target.c
+++ b/sys/dev/isp/isp_target.c
@@ -525,11 +525,9 @@ isp_target_async(isp, bus, event)
*/
MEMZERO(&msg, sizeof msg);
if (IS_FC(isp)) {
- msg.nt_iid =
- ((fcparam *)isp->isp_param)->isp_loopid;
+ msg.nt_iid = FCPARAM(isp)->isp_loopid;
} else {
- msg.nt_iid =
- ((sdparam *)isp->isp_param)->isp_initiator_id;
+ msg.nt_iid = SDPARAM(isp)->isp_initiator_id;
}
msg.nt_bus = bus;
msg.nt_msg[0] = MSG_BUS_DEV_RESET;
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index dc03a09..e93b947 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -374,7 +374,7 @@ typedef struct {
#define req_response_len req_time /* FC only */
u_int16_t req_sense_len;
u_int32_t req_resid;
- u_int8_t _res1[8];
+ u_int8_t req_response[8]; /* FC only */
u_int8_t req_sense_data[32];
} ispstatusreq_t;
@@ -384,20 +384,25 @@ typedef struct {
*/
#define RQCS_RU 0x800 /* Residual Under */
#define RQCS_RO 0x400 /* Residual Over */
+#define RQCS_RESID (RQCS_RU|RQCS_RO)
#define RQCS_SV 0x200 /* Sense Length Valid */
-#define RQCS_RV 0x100 /* Residual Valid */
+#define RQCS_RV 0x100 /* FCP Response Length Valid */
/*
* Completion Status Codes.
*/
#define RQCS_COMPLETE 0x0000
-#define RQCS_INCOMPLETE 0x0001
#define RQCS_DMA_ERROR 0x0002
-#define RQCS_TRANSPORT_ERROR 0x0003
#define RQCS_RESET_OCCURRED 0x0004
#define RQCS_ABORTED 0x0005
#define RQCS_TIMEOUT 0x0006
#define RQCS_DATA_OVERRUN 0x0007
+#define RQCS_DATA_UNDERRUN 0x0015
+#define RQCS_QUEUE_FULL 0x001C
+
+/* 1X00 Only Completion Codes */
+#define RQCS_INCOMPLETE 0x0001
+#define RQCS_TRANSPORT_ERROR 0x0003
#define RQCS_COMMAND_OVERRUN 0x0008
#define RQCS_STATUS_OVERRUN 0x0009
#define RQCS_BAD_MESSAGE 0x000a
@@ -411,26 +416,24 @@ typedef struct {
#define RQCS_DEVICE_RESET_MSG_FAILED 0x0012
#define RQCS_ID_MSG_FAILED 0x0013
#define RQCS_UNEXP_BUS_FREE 0x0014
-#define RQCS_DATA_UNDERRUN 0x0015
#define RQCS_XACT_ERR1 0x0018
#define RQCS_XACT_ERR2 0x0019
#define RQCS_XACT_ERR3 0x001A
#define RQCS_BAD_ENTRY 0x001B
-#define RQCS_QUEUE_FULL 0x001C
#define RQCS_PHASE_SKIPPED 0x001D
#define RQCS_ARQS_FAILED 0x001E
#define RQCS_WIDE_FAILED 0x001F
#define RQCS_SYNCXFER_FAILED 0x0020
#define RQCS_LVD_BUSERR 0x0021
-/* 2100 Only Completion Codes */
+/* 2X00 Only Completion Codes */
#define RQCS_PORT_UNAVAILABLE 0x0028
#define RQCS_PORT_LOGGED_OUT 0x0029
#define RQCS_PORT_CHANGED 0x002A
#define RQCS_PORT_BUSY 0x002B
/*
- * State Flags (not applicable to 2100)
+ * 1X00 specific State Flags
*/
#define RQSF_GOT_BUS 0x0100
#define RQSF_GOT_TARGET 0x0200
@@ -441,7 +444,7 @@ typedef struct {
#define RQSF_XFER_COMPLETE 0x4000
/*
- * Status Flags (not applicable to 2100)
+ * 1X00 Status Flags
*/
#define RQSTF_DISCONNECT 0x0001
#define RQSTF_SYNCHRONOUS 0x0002
@@ -453,6 +456,29 @@ typedef struct {
#define RQSTF_NEGOTIATION 0x0080
/*
+ * 2X00 specific state flags
+ */
+/* RQSF_SENT_CDB */
+/* RQSF_XFRD_DATA */
+/* RQSF_GOT_STATUS */
+/* RQSF_XFER_COMPLETE */
+
+/*
+ * 2X00 specific status flags
+ */
+/* RQSTF_ABORTED */
+/* RQSTF_TIMEOUT */
+#define RQSTF_DMA_ERROR 0x0080
+#define RQSTF_LOGOUT 0x2000
+
+/*
+ * Miscellaneous
+ */
+#ifndef ISP_EXEC_THROTTLE
+#define ISP_EXEC_THROTTLE 16
+#endif
+
+/*
* FC (ISP2100) specific data structures
*/
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index b846070..0afbfcb 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -153,9 +153,11 @@ struct ispmdvec {
#define ISP_QUEUE_ENTRY(q, idx) ((q) + ((idx) * QENTRY_LEN))
#define ISP_QUEUE_SIZE(n) ((n) * QENTRY_LEN)
#define ISP_NXT_QENTRY(idx, qlen) (((idx) + 1) & ((qlen)-1))
-#define ISP_QAVAIL(in, out, qlen) \
+#define ISP_QFREE(in, out, qlen) \
((in == out)? (qlen - 1) : ((in > out)? \
((qlen - 1) - (in - out)) : (out - in - 1)))
+#define ISP_QAVAIL(isp) \
+ ISP_QFREE(isp->isp_reqidx, isp->isp_reqodx, RQUEST_QUEUE_LEN(isp))
#define ISP_ADD_REQUEST(isp, iptr) \
MEMORYBARRIER(isp, SYNC_REQUEST, iptr, QENTRY_LEN); \
@@ -176,7 +178,7 @@ typedef struct {
isp_ultramode : 1,
isp_diffmode : 1,
isp_lvdmode : 1,
- : 1,
+ isp_fast_mttr : 1, /* fast sram */
isp_initiator_id : 4,
isp_async_data_setup : 4;
u_int16_t isp_selection_timeout;
@@ -211,15 +213,18 @@ typedef struct {
#define DPARM_ARQ 0x0400
#define DPARM_QFRZ 0x0200
#define DPARM_RENEG 0x0100
-#define DPARM_NARROW 0x0080 /* Possibly only available with >= 7.55 fw */
-#define DPARM_ASYNC 0x0040 /* Possibly only available with >= 7.55 fw */
+#define DPARM_NARROW 0x0080
+#define DPARM_ASYNC 0x0040
+#define DPARM_PPR 0x0020
#define DPARM_DEFAULT (0xFF00 & ~DPARM_QFRZ)
#define DPARM_SAFE_DFLT (DPARM_DEFAULT & ~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING))
/* technically, not really correct, as they need to be rated based upon clock */
-#define ISP_40M_SYNCPARMS 0x080a
-#define ISP_20M_SYNCPARMS 0x080c
+#define ISP_80M_SYNCPARMS 0x0c09
+#define ISP_40M_SYNCPARMS 0x0c0a
+#define ISP_20M_SYNCPARMS 0x0c0c
+#define ISP_20M_SYNCPARMS_1040 0x080c
#define ISP_10M_SYNCPARMS 0x0c19
#define ISP_08M_SYNCPARMS 0x0c25
#define ISP_05M_SYNCPARMS 0x0c32
@@ -304,7 +309,7 @@ typedef struct {
/*
* Soft Structure per host adapter
*/
-struct ispsoftc {
+typedef struct ispsoftc {
/*
* Platform (OS) specific data
*/
@@ -330,9 +335,9 @@ struct ispsoftc {
u_int32_t
isp_touched : 1, /* board ever seen? */
- isp_fast_mttr : 1, /* fast sram */
- isp_bustype : 1, /* SBus or PCI */
: 1,
+ isp_bustype : 1, /* SBus or PCI */
+ isp_loaded_fw : 1, /* loaded firmware */
isp_dblev : 12, /* debug log mask */
isp_clock : 8, /* input clock */
isp_confopts : 8; /* config options */
@@ -366,7 +371,7 @@ struct ispsoftc {
caddr_t isp_result;
u_int32_t isp_rquest_dma;
u_int32_t isp_result_dma;
-};
+} ispsoftc_t;
#define SDPARAM(isp) ((sdparam *) (isp)->isp_param)
#define FCPARAM(isp) ((fcparam *) (isp)->isp_param)
OpenPOWER on IntegriCloud