diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2007-10-02 13:53:04 -0700 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-12 14:55:45 -0400 |
commit | 2db78dd302d26d242d3e8e5c4c5024b6c3ea93c2 (patch) | |
tree | 3d1b15c4314568dd7ccedb43a406060d5b6093be /drivers/ata | |
parent | 681c80b5d96076f447e8101ac4325c82d8dce508 (diff) | |
download | linux-3.10-2db78dd302d26d242d3e8e5c4c5024b6c3ea93c2.tar.gz linux-3.10-2db78dd302d26d242d3e8e5c4c5024b6c3ea93c2.tar.bz2 linux-3.10-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.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index df2e05738f3..ea53e6a570b 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; } |