Commit 2db78dd3 authored by Alan Cox's avatar Alan Cox Committed by Jeff Garzik

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: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 681c80b5
...@@ -2305,8 +2305,8 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) ...@@ -2305,8 +2305,8 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_PKT_DMA; qc->tf.feature |= ATAPI_PKT_DMA;
} else { } else {
qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.protocol = ATA_PROT_ATAPI;
qc->tf.lbam = (8 * 1024) & 0xff; qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
qc->tf.lbah = (8 * 1024) >> 8; qc->tf.lbah = 0;
} }
qc->nbytes = SCSI_SENSE_BUFFERSIZE; qc->nbytes = SCSI_SENSE_BUFFERSIZE;
...@@ -2415,6 +2415,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) ...@@ -2415,6 +2415,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
struct ata_device *dev = qc->dev; struct ata_device *dev = qc->dev;
int using_pio = (dev->flags & ATA_DFLAG_PIO); int using_pio = (dev->flags & ATA_DFLAG_PIO);
int nodata = (scmd->sc_data_direction == DMA_NONE); int nodata = (scmd->sc_data_direction == DMA_NONE);
unsigned int nbytes;
memset(qc->cdb, 0, dev->cdb_len); memset(qc->cdb, 0, dev->cdb_len);
memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len); memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
...@@ -2434,14 +2435,20 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) ...@@ -2434,14 +2435,20 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
if (!using_pio && ata_check_atapi_dma(qc)) if (!using_pio && ata_check_atapi_dma(qc))
using_pio = 1; 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) { if (using_pio || nodata) {
/* no data, or PIO data xfer */ /* no data, or PIO data xfer */
if (nodata) if (nodata)
qc->tf.protocol = ATA_PROT_ATAPI_NODATA; qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
else else
qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.protocol = ATA_PROT_ATAPI;
qc->tf.lbam = (8 * 1024) & 0xff;
qc->tf.lbah = (8 * 1024) >> 8;
} else { } else {
/* DMA data xfer */ /* DMA data xfer */
qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.protocol = ATA_PROT_ATAPI_DMA;
...@@ -2452,6 +2459,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) ...@@ -2452,6 +2459,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_DMADIR; 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment