summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2016-01-03 16:05:27 +1100
committerMartin K. Petersen <martin.petersen@oracle.com>2016-01-06 21:42:57 -0500
commita2edc4a63b4f89016053fe5da3fdac3798f3e2ae (patch)
tree9dc473baef6c61e8cf4e8093d068bc21298a58bf
parent686f3990e6a9111f97f2d385f4d1c1a5b0628c15 (diff)
ncr5380: Fix NCR5380_transfer_pio() result
According to the SCSI-2 draft revision 10L, atari_NCR5380.c is correct when it says that the phase lines are valid up until ACK is negated following the transmission of the last byte in MESSAGE IN phase. This is true for all information transfer phases, from target to initiator. Sample the phase bits in STATUS_REG so that NCR5380_transfer_pio() can return the correct result. The return value is presently unused (perhaps because of bugs like this) but this change at least fixes the caller's phase variable, which is passed by reference. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Ondrej Zary <linux@rainbow-software.org> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/NCR5380.c12
-rw-r--r--drivers/scsi/atari_NCR5380.c11
2 files changed, 15 insertions, 8 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 23bb7fe8b13b..9b437e19b7a1 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -1393,8 +1393,10 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
}
- /* FIXME - if this fails bus reset ?? */
- NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 5*HZ);
+ if (NCR5380_poll_politely(instance,
+ STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
+ break;
+
dprintk(NDEBUG_HANDSHAKE, "scsi%d : req false, handshake complete\n", instance->host_no);
/*
@@ -1421,7 +1423,11 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
*count = c;
*data = d;
tmp = NCR5380_read(STATUS_REG);
- if (tmp & SR_REQ)
+ /* The phase read from the bus is valid if either REQ is (already)
+ * asserted or if ACK hasn't been released yet. The latter applies if
+ * we're in MSG IN, DATA IN or STATUS and all bytes have been received.
+ */
+ if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0))
*phase = tmp & PHASE_MASK;
else
*phase = PHASE_UNKNOWN;
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index dc283f50e4ac..ca39dc623c34 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -1776,8 +1776,9 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
}
- while (NCR5380_read(STATUS_REG) & SR_REQ)
- ;
+ if (NCR5380_poll_politely(instance,
+ STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
+ break;
dprintk(NDEBUG_HANDSHAKE, "scsi%d: req false, handshake complete\n", HOSTNO);
@@ -1806,10 +1807,10 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
*data = d;
tmp = NCR5380_read(STATUS_REG);
/* The phase read from the bus is valid if either REQ is (already)
- * asserted or if ACK hasn't been released yet. The latter is the case if
- * we're in MSGIN and all wanted bytes have been received.
+ * asserted or if ACK hasn't been released yet. The latter applies if
+ * we're in MSG IN, DATA IN or STATUS and all bytes have been received.
*/
- if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
+ if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0))
*phase = tmp & PHASE_MASK;
else
*phase = PHASE_UNKNOWN;