Apply the following change made 06/06/2003 23:51:13 by gibbs to the

FreeBSD ahd driver:

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.
This commit is contained in:
thorpej 2003-08-29 03:41:28 +00:00
parent 6336835ec0
commit 720b377380
1 changed files with 44 additions and 24 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: aic79xx.c,v 1.15 2003/08/29 02:38:58 thorpej Exp $ */
/* $NetBSD: aic79xx.c,v 1.16 2003/08/29 03:41:28 thorpej Exp $ */
/*
* Core routines and tables shareable across OS platforms.
@ -39,9 +39,9 @@
* 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: src/sys/dev/aic7xxx/aic79xx.c,v 1.18 2003/06/06 23:48:18 gibbs Exp $
* $FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.19 2003/06/06 23:51:13 gibbs Exp $
*/
/*
* Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc.
@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: aic79xx.c,v 1.15 2003/08/29 02:38:58 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: aic79xx.c,v 1.16 2003/08/29 03:41:28 thorpej Exp $");
#include <dev/ic/aic79xx_osm.h>
#include <dev/ic/aic79xx_inline.h>
@ -1904,8 +1904,23 @@ 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-narrow and
* retry command.
*/
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
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
@ -1913,12 +1928,8 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
*/
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
printf("Negotiation rejected busfree.\n");
printf("SDTR 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_set_syncrate(ahd, &devinfo,
/*period*/0, /*offset*/0,
/*ppr_options*/0,
@ -3262,6 +3273,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)
@ -3269,7 +3281,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
@ -3279,7 +3291,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) {
@ -4013,22 +4025,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;