Commit fba6edbd authored by Mikael Pettersson's avatar Mikael Pettersson Committed by Jeff Garzik

sata_promise: handle ATAPI_NODATA ourselves

This patch extends sata_promise to handle ATAPI_NODATA
commands internally. However, commands destined to
ATA_DFLAG_CDB_INTR devices are excluded from this and
continue to be returned to libata.

Concrete changes:
- pdc_atapi_dma_pkt() is renamed to pdc_atapi_pkt(), and is
  extended to set up correct headers for NODATA packets
- pdc_qc_prep() calls pdc_atapi_pkt() for ATAPI_NODATA
- pdc_host_intr() handles ATAPI_NODATA
- pdc_qc_issue_prot() sends ATAPI_NODATA packets via the
  chip's packet mechanism, except for CDB_INTR devices

Tested on first- and second-generation chips, SATAPI and PATAPI,
with no observable regressions.
Signed-off-by: default avatarMikael Pettersson <mikpe@it.uu.se>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 4113bb6b
...@@ -448,7 +448,7 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, ...@@ -448,7 +448,7 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
} }
static void pdc_atapi_dma_pkt(struct ata_queued_cmd *qc) static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
dma_addr_t sg_table = ap->prd_dma; dma_addr_t sg_table = ap->prd_dma;
...@@ -462,10 +462,20 @@ static void pdc_atapi_dma_pkt(struct ata_queued_cmd *qc) ...@@ -462,10 +462,20 @@ static void pdc_atapi_dma_pkt(struct ata_queued_cmd *qc)
/* set control bits (byte 0), zero delay seq id (byte 3), /* set control bits (byte 0), zero delay seq id (byte 3),
* and seq id (byte 2) * and seq id (byte 2)
*/ */
if (!(qc->tf.flags & ATA_TFLAG_WRITE)) switch (qc->tf.protocol) {
buf32[0] = cpu_to_le32(PDC_PKT_READ); case ATA_PROT_ATAPI_DMA:
else if (!(qc->tf.flags & ATA_TFLAG_WRITE))
buf32[0] = 0; buf32[0] = cpu_to_le32(PDC_PKT_READ);
else
buf32[0] = 0;
break;
case ATA_PROT_ATAPI_NODATA:
buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
break;
default:
BUG();
break;
}
buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */
buf32[2] = 0; /* no next-packet */ buf32[2] = 0; /* no next-packet */
...@@ -549,13 +559,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) ...@@ -549,13 +559,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
break; break;
case ATA_PROT_ATAPI: case ATA_PROT_ATAPI:
case ATA_PROT_ATAPI_NODATA:
ata_qc_prep(qc); ata_qc_prep(qc);
break; break;
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
ata_qc_prep(qc); ata_qc_prep(qc);
pdc_atapi_dma_pkt(qc); /*FALLTHROUGH*/
case ATA_PROT_ATAPI_NODATA:
pdc_atapi_pkt(qc);
break; break;
default: default:
...@@ -672,6 +683,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap, ...@@ -672,6 +683,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI_NODATA:
qc->err_mask |= ac_err_mask(ata_wait_idle(ap)); qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
ata_qc_complete(qc); ata_qc_complete(qc);
handled = 1; handled = 1;
...@@ -771,6 +783,10 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc) ...@@ -771,6 +783,10 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
{ {
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_ATAPI_NODATA:
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
break;
/*FALLTHROUGH*/
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
......
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