Work around an ambiguity in the SCSI spec. Some implementations,

particularly older ones, don't do a SAVE DATA POINTER before disconnecting.
When the driver reconnects, it does an implicit RESTORE POINTERS, and
restores the data pointer from *before* the last transfer.  If the driver
calculates the residual using the data pointer and doesn't account for
this, the residual will be wrong.

What we do is test for the SDEV_AUTOSAVE quirk when we see a disconnect
message, falling through to do a SAVE DATA POINTER if the quirk applies
to this target.

The workaround was suggested by Mycroft, who also provided the explanation
of the problem.  Actual code was (mostly) ripped off from the 53C9x driver.
This commit is contained in:
scottr 1997-03-27 07:30:40 +00:00
parent b81091e992
commit b316767c92

View File

@ -1,4 +1,4 @@
/* $NetBSD: ncr5380sbc.c,v 1.19 1997/03/27 01:16:01 gwr Exp $ */
/* $NetBSD: ncr5380sbc.c,v 1.20 1997/03/27 07:30:40 scottr Exp $ */
/*
* Copyright (c) 1995 David Jones, Gordon W. Ross
@ -1539,6 +1539,7 @@ ncr5380_msg_in(sc)
register struct ncr5380_softc *sc;
{
struct sci_req *sr = sc->sc_current;
struct scsi_xfer *xs = sr->sr_xs;
int n, phase;
int act_flags;
register u_char icmd;
@ -1658,12 +1659,6 @@ have_msg:
act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
break;
case MSG_DISCONNECT:
NCR_TRACE("msg_in: DISCONNECT\n", 0);
/* Target is about to disconnect. */
act_flags |= ACT_DISCONNECT;
break;
case MSG_PARITY_ERROR:
NCR_TRACE("msg_in: PARITY_ERROR\n", 0);
/* Resend the last message. */
@ -1687,6 +1682,14 @@ have_msg:
NCR_TRACE("msg_in: NOOP\n", 0);
break;
case MSG_DISCONNECT:
NCR_TRACE("msg_in: DISCONNECT\n", 0);
/* Target is about to disconnect. */
act_flags |= ACT_DISCONNECT;
if ((xs->sc_link->quirks & SDEV_AUTOSAVE) == 0)
break;
/*FALLTHROUGH*/
case MSG_SAVEDATAPOINTER:
NCR_TRACE("msg_in: SAVE_PTRS\n", 0);
sr->sr_dataptr = sc->sc_dataptr;