aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/isp/isp.c
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2000-08-27 23:38:44 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2000-08-27 23:38:44 +0000
commitb6b6ad2f237259c8ef225a01a656caee7ca2f60b (patch)
tree2408272da3a6772b62762f956d64d02647e355b1 /sys/dev/isp/isp.c
parent3aa9aaf931d031d04987c886258dd3cd83d399d3 (diff)
Notes
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r--sys/dev/isp/isp.c447
1 files changed, 277 insertions, 170 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 891527c3f817..e477fc8c36a3 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);