summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2003-06-06 23:51:13 +0000
committergibbs <gibbs@FreeBSD.org>2003-06-06 23:51:13 +0000
commit702257f6c871de3b19bc127063248269d65886df (patch)
tree4f935003e4e8565ab91de31f0148dbf9350e45c5 /sys
parenta0dd99d2907b324d198967c66253fa32d8d96241 (diff)
downloadFreeBSD-src-702257f6c871de3b19bc127063248269d65886df.zip
FreeBSD-src-702257f6c871de3b19bc127063248269d65886df.tar.gz
Work around SCSI spec violation by the Quantum Atlas 10K.
This drive delays going async after receiving a WDTR message. We now send an SDTR message after a WDTR even if our goal is to go async. This should work even for confused devices. If we get an unexpected busfree when attempting a WDTR or SDTR, only set the goal negotiation parameters we were trying to negotiate to off. This means that should a WDTR message fail, we will still try an SDTR if our goal is non-async. Fix a few more places where we were looking at goal.period instead of goal.offset for determining if we should be negotiating sync. This should not have any impact on our behavior, but the offset is more definitive and should be used.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/aic7xxx/aic79xx.c56
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c50
2 files changed, 70 insertions, 36 deletions
diff --git a/sys/dev/aic7xxx/aic79xx.c b/sys/dev/aic7xxx/aic79xx.c
index 9c908db..cf1007c 100644
--- a/sys/dev/aic7xxx/aic79xx.c
+++ b/sys/dev/aic7xxx/aic79xx.c
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#196 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#197 $
*
* $FreeBSD$
*/
@@ -1880,21 +1880,32 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
tinfo->goal.ppr_options = 0;
ahd_qinfifo_requeue_tail(ahd, scb);
printerror = 0;
- } else if ((ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
- || ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE))
+ } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
&& ppr_busfree == 0) {
/*
- * Negotiation Rejected. Go-async and
+ * Negotiation Rejected. Go-narrow and
* retry command.
*/
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
- printf("Negotiation rejected busfree.\n");
+ printf("WDTR negotiation rejected busfree.\n");
#endif
ahd_set_width(ahd, &devinfo,
MSG_EXT_WDTR_BUS_8_BIT,
AHD_TRANS_CUR|AHD_TRANS_GOAL,
/*paused*/TRUE);
+ ahd_qinfifo_requeue_tail(ahd, scb);
+ printerror = 0;
+ } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
+ && ppr_busfree == 0) {
+ /*
+ * Negotiation Rejected. Go-async and
+ * retry command.
+ */
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
+ printf("SDTR negotiation rejected busfree.\n");
+#endif
ahd_set_syncrate(ahd, &devinfo,
/*period*/0, /*offset*/0,
/*ppr_options*/0,
@@ -3232,6 +3243,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
* may change.
*/
period = tinfo->goal.period;
+ offset = tinfo->goal.offset;
ppr_options = tinfo->goal.ppr_options;
/* Target initiated PPR is not allowed in the SCSI spec */
if (devinfo->role == ROLE_TARGET)
@@ -3239,7 +3251,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
ahd_devlimited_syncrate(ahd, tinfo, &period,
&ppr_options, devinfo->role);
dowide = tinfo->curr.width != tinfo->goal.width;
- dosync = tinfo->curr.period != period;
+ dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
/*
* Only use PPR if we have options that need it, even if the device
* claims to support it. There might be an expander in the way
@@ -3249,7 +3261,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
if (!dowide && !dosync && !doppr) {
dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
- dosync = tinfo->goal.period != 0;
+ dosync = tinfo->goal.offset != 0;
}
if (!dowide && !dosync && !doppr) {
@@ -3983,22 +3995,30 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
response = TRUE;
sending_reply = TRUE;
}
+ /*
+ * After a wide message, we are async, but
+ * some devices don't seem to honor this portion
+ * of the spec. Force a renegotiation of the
+ * sync component of our transfer agreement even
+ * if our goal is async. By updating our width
+ * after forcing the negotiation, we avoid
+ * renegotiating for width.
+ */
+ ahd_update_neg_request(ahd, devinfo, tstate,
+ tinfo, AHD_NEG_ALWAYS);
ahd_set_width(ahd, devinfo, bus_width,
AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
/*paused*/TRUE);
- /* After a wide message, we are async */
- ahd_set_syncrate(ahd, devinfo, /*period*/0,
- /*offset*/0, /*ppr_options*/0,
- AHD_TRANS_ACTIVE, /*paused*/TRUE);
if (sending_reply == FALSE && reject == FALSE) {
- if (tinfo->goal.offset) {
- ahd->msgout_index = 0;
- ahd->msgout_len = 0;
- ahd_build_transfer_msg(ahd, devinfo);
- ahd->msgout_index = 0;
- response = TRUE;
- }
+ /*
+ * We will always have an SDTR to send.
+ */
+ ahd->msgout_index = 0;
+ ahd->msgout_len = 0;
+ ahd_build_transfer_msg(ahd, devinfo);
+ ahd->msgout_index = 0;
+ response = TRUE;
}
done = MSGLOOP_MSGCOMPLETE;
break;
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index d762979..a1e6d90 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#132 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#133 $
*
* $FreeBSD$
*/
@@ -1304,17 +1304,23 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_qinfifo_requeue_tail(ahc, scb);
printerror = 0;
} else if (ahc_sent_msg(ahc, AHCMSG_EXT,
- MSG_EXT_WDTR, FALSE)
- || ahc_sent_msg(ahc, AHCMSG_EXT,
- MSG_EXT_SDTR, FALSE)) {
+ MSG_EXT_WDTR, FALSE)) {
/*
- * Negotiation Rejected. Go-async and
+ * Negotiation Rejected. Go-narrow and
* retry command.
*/
ahc_set_width(ahc, &devinfo,
MSG_EXT_WDTR_BUS_8_BIT,
AHC_TRANS_CUR|AHC_TRANS_GOAL,
/*paused*/TRUE);
+ ahc_qinfifo_requeue_tail(ahc, scb);
+ printerror = 0;
+ } else if (ahc_sent_msg(ahc, AHCMSG_EXT,
+ MSG_EXT_SDTR, FALSE)) {
+ /*
+ * Negotiation Rejected. Go-async and
+ * retry command.
+ */
ahc_set_syncrate(ahc, &devinfo,
/*syncrate*/NULL,
/*period*/0, /*offset*/0,
@@ -2373,6 +2379,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
* may change.
*/
period = tinfo->goal.period;
+ offset = tinfo->goal.offset;
ppr_options = tinfo->goal.ppr_options;
/* Target initiated PPR is not allowed in the SCSI spec */
if (devinfo->role == ROLE_TARGET)
@@ -2380,7 +2387,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
&ppr_options, devinfo->role);
dowide = tinfo->curr.width != tinfo->goal.width;
- dosync = tinfo->curr.period != period;
+ dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
/*
* Only use PPR if we have options that need it, even if the device
* claims to support it. There might be an expander in the way
@@ -3176,23 +3183,30 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
response = TRUE;
sending_reply = TRUE;
}
+ /*
+ * After a wide message, we are async, but
+ * some devices don't seem to honor this portion
+ * of the spec. Force a renegotiation of the
+ * sync component of our transfer agreement even
+ * if our goal is async. By updating our width
+ * after forcing the negotiation, we avoid
+ * renegotiating for width.
+ */
+ ahc_update_neg_request(ahc, devinfo, tstate,
+ tinfo, AHC_NEG_ALWAYS);
ahc_set_width(ahc, devinfo, bus_width,
AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
/*paused*/TRUE);
- /* After a wide message, we are async */
- ahc_set_syncrate(ahc, devinfo,
- /*syncrate*/NULL, /*period*/0,
- /*offset*/0, /*ppr_options*/0,
- AHC_TRANS_ACTIVE, /*paused*/TRUE);
if (sending_reply == FALSE && reject == FALSE) {
- if (tinfo->goal.offset) {
- ahc->msgout_index = 0;
- ahc->msgout_len = 0;
- ahc_build_transfer_msg(ahc, devinfo);
- ahc->msgout_index = 0;
- response = TRUE;
- }
+ /*
+ * We will always have an SDTR to send.
+ */
+ ahc->msgout_index = 0;
+ ahc->msgout_len = 0;
+ ahc_build_transfer_msg(ahc, devinfo);
+ ahc->msgout_index = 0;
+ response = TRUE;
}
done = MSGLOOP_MSGCOMPLETE;
break;
OpenPOWER on IntegriCloud