aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2007-10-02 13:53:04 -0700
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:45 -0400
commit2db78dd302d26d242d3e8e5c4c5024b6c3ea93c2 (patch)
tree3d1b15c4314568dd7ccedb43a406060d5b6093be /drivers/ata
parentlibata: correct handling of SRST reset sequences (diff)
downloadlinux-dev-2db78dd302d26d242d3e8e5c4c5024b6c3ea93c2.tar.xz
linux-dev-2db78dd302d26d242d3e8e5c4c5024b6c3ea93c2.zip
libata_scsi: Fix ATAPI transfer lengths
Some controller variants snoop the ATAPI length value for Packet transfers to do state machine and FIFO management. Thus we want to set it properly, even for cases where it is otherwise meaningless. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-scsi.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index df2e05738f3b..ea53e6a570b4 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2305,8 +2305,8 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_PKT_DMA;
} else {
qc->tf.protocol = ATA_PROT_ATAPI;
- qc->tf.lbam = (8 * 1024) & 0xff;
- qc->tf.lbah = (8 * 1024) >> 8;
+ qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
+ qc->tf.lbah = 0;
}
qc->nbytes = SCSI_SENSE_BUFFERSIZE;
@@ -2415,6 +2415,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
struct ata_device *dev = qc->dev;
int using_pio = (dev->flags & ATA_DFLAG_PIO);
int nodata = (scmd->sc_data_direction == DMA_NONE);
+ unsigned int nbytes;
memset(qc->cdb, 0, dev->cdb_len);
memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
@@ -2434,14 +2435,20 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
if (!using_pio && ata_check_atapi_dma(qc))
using_pio = 1;
+ /* Some controller variants snoop this value for Packet transfers
+ to do state machine and FIFO management. Thus we want to set it
+ properly, and for DMA where it is effectively meaningless */
+ nbytes = min(qc->nbytes, (unsigned int)63 * 1024);
+
+ qc->tf.lbam = (nbytes & 0xFF);
+ qc->tf.lbah = (nbytes >> 8);
+
if (using_pio || nodata) {
/* no data, or PIO data xfer */
if (nodata)
qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
else
qc->tf.protocol = ATA_PROT_ATAPI;
- qc->tf.lbam = (8 * 1024) & 0xff;
- qc->tf.lbah = (8 * 1024) >> 8;
} else {
/* DMA data xfer */
qc->tf.protocol = ATA_PROT_ATAPI_DMA;
@@ -2452,6 +2459,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_DMADIR;
}
+
+ /* FIXME: We need to translate 0x05 READ_BLOCK_LIMITS to a MODE_SENSE
+ as ATAPI tape drives don't get this right otherwise */
return 0;
}