Commit 263924d7 authored by Jeff Garzik's avatar Jeff Garzik

[libata] consolidate data transfer mode handling

The various ways you can send data to/from your ATA device is
known as the ATA taskfile protocol:  PIO single sector, PIO
multiple sector, DMA, DMA TCQ, DMA NCQ, ...

Prior to this change, the data direction (read/write) was encoded
implicitly into the ATA_PROT_xxx value itself.  This increased
complexity in some areas, and inhibited flexibility in others.

This change separates data direction from taskfile protocol, and also
moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
level (ATA_TFLAG_WRITE).
parent 3b64bb0c
...@@ -444,8 +444,7 @@ static int ata_prot_to_cmd(int protocol, int lba48) ...@@ -444,8 +444,7 @@ static int ata_prot_to_cmd(int protocol, int lba48)
int rcmd = 0, wcmd = 0; int rcmd = 0, wcmd = 0;
switch (protocol) { switch (protocol) {
case ATA_PROT_PIO_READ: case ATA_PROT_PIO:
case ATA_PROT_PIO_WRITE:
if (lba48) { if (lba48) {
rcmd = ATA_CMD_PIO_READ_EXT; rcmd = ATA_CMD_PIO_READ_EXT;
wcmd = ATA_CMD_PIO_WRITE_EXT; wcmd = ATA_CMD_PIO_WRITE_EXT;
...@@ -455,8 +454,7 @@ static int ata_prot_to_cmd(int protocol, int lba48) ...@@ -455,8 +454,7 @@ static int ata_prot_to_cmd(int protocol, int lba48)
} }
break; break;
case ATA_PROT_DMA_READ: case ATA_PROT_DMA:
case ATA_PROT_DMA_WRITE:
if (lba48) { if (lba48) {
rcmd = ATA_CMD_READ_EXT; rcmd = ATA_CMD_READ_EXT;
wcmd = ATA_CMD_WRITE_EXT; wcmd = ATA_CMD_WRITE_EXT;
...@@ -479,13 +477,10 @@ static void ata_dev_set_protocol(struct ata_device *dev) ...@@ -479,13 +477,10 @@ static void ata_dev_set_protocol(struct ata_device *dev)
int lba48 = (dev->flags & ATA_DFLAG_LBA48); int lba48 = (dev->flags & ATA_DFLAG_LBA48);
int proto, cmd; int proto, cmd;
if (pio) { if (pio)
proto = dev->r_protocol = ATA_PROT_PIO_READ; proto = dev->xfer_protocol = ATA_PROT_PIO;
dev->w_protocol = ATA_PROT_PIO_WRITE; else
} else { proto = dev->xfer_protocol = ATA_PROT_DMA;
proto = dev->r_protocol = ATA_PROT_DMA_READ;
dev->w_protocol = ATA_PROT_DMA_WRITE;
}
cmd = ata_prot_to_cmd(proto, lba48); cmd = ata_prot_to_cmd(proto, lba48);
if (cmd < 0) if (cmd < 0)
...@@ -899,7 +894,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ...@@ -899,7 +894,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
retry: retry:
ata_tf_init(ap, &tf, device); ata_tf_init(ap, &tf, device);
tf.ctl |= ATA_NIEN; tf.ctl |= ATA_NIEN;
tf.protocol = ATA_PROT_PIO_READ; tf.protocol = ATA_PROT_PIO;
if (dev->class == ATA_DEV_ATA) { if (dev->class == ATA_DEV_ATA) {
tf.command = ATA_CMD_ID_ATA; tf.command = ATA_CMD_ID_ATA;
...@@ -1803,7 +1798,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1803,7 +1798,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg_dma_address(sg) = dma_address; sg_dma_address(sg) = dma_address;
DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen, DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen,
qc->flags & ATA_QCFLAG_WRITE ? "write" : "read"); qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
return 0; return 0;
} }
...@@ -1904,8 +1899,7 @@ static void ata_pio_start (struct ata_queued_cmd *qc) ...@@ -1904,8 +1899,7 @@ static void ata_pio_start (struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
assert((qc->tf.protocol == ATA_PROT_PIO_READ) || assert(qc->tf.protocol == ATA_PROT_PIO);
(qc->tf.protocol == ATA_PROT_PIO_WRITE));
qc->flags |= ATA_QCFLAG_POLL; qc->flags |= ATA_QCFLAG_POLL;
qc->tf.ctl |= ATA_NIEN; /* disable interrupts */ qc->tf.ctl |= ATA_NIEN; /* disable interrupts */
...@@ -2025,12 +2019,12 @@ static void ata_pio_sector(struct ata_port *ap) ...@@ -2025,12 +2019,12 @@ static void ata_pio_sector(struct ata_port *ap)
} }
DPRINTK("data %s, drv_stat 0x%X\n", DPRINTK("data %s, drv_stat 0x%X\n",
qc->flags & ATA_QCFLAG_WRITE ? "write" : "read", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
status); status);
/* do the actual data transfer */ /* do the actual data transfer */
/* FIXME: mmio-ize */ /* FIXME: mmio-ize */
if (qc->flags & ATA_QCFLAG_WRITE) if (qc->tf.flags & ATA_TFLAG_WRITE)
outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
else else
insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
...@@ -2095,8 +2089,7 @@ void ata_eng_timeout(struct ata_port *ap) ...@@ -2095,8 +2089,7 @@ void ata_eng_timeout(struct ata_port *ap)
qc->scsidone = scsi_finish_command; qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ: case ATA_PROT_DMA:
case ATA_PROT_DMA_WRITE:
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr; void *mmio = (void *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS); host_stat = readb(mmio + ATA_DMA_STATUS);
...@@ -2320,7 +2313,7 @@ int ata_qc_issue(struct ata_queued_cmd *qc) ...@@ -2320,7 +2313,7 @@ int ata_qc_issue(struct ata_queued_cmd *qc)
void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE); unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 host_stat, dmactl; u8 host_stat, dmactl;
void *mmio = (void *) ap->ioaddr.bmdma_addr; void *mmio = (void *) ap->ioaddr.bmdma_addr;
...@@ -2369,7 +2362,7 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) ...@@ -2369,7 +2362,7 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
void ata_bmdma_start_pio (struct ata_queued_cmd *qc) void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE); unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 host_stat, dmactl; u8 host_stat, dmactl;
/* load PRD table addr. */ /* load PRD table addr. */
...@@ -2464,8 +2457,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -2464,8 +2457,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
unsigned int handled = 0; unsigned int handled = 0;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ: case ATA_PROT_DMA:
case ATA_PROT_DMA_WRITE:
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr; void *mmio = (void *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS); host_stat = readb(mmio + ATA_DMA_STATUS);
......
...@@ -102,7 +102,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc) ...@@ -102,7 +102,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc)
cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */ cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */
/* additional-sense-code[-qualifier] */ /* additional-sense-code[-qualifier] */
if ((qc->flags & ATA_QCFLAG_WRITE) == 0) { if (cmd->sc_data_direction == SCSI_DATA_READ) {
cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */ cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
cmd->sense_buffer[13] = 0x04; cmd->sense_buffer[13] = 0x04;
} else { } else {
...@@ -179,17 +179,15 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd, ...@@ -179,17 +179,15 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd,
tf->hob_lbal = 0; tf->hob_lbal = 0;
tf->hob_lbam = 0; tf->hob_lbam = 0;
tf->hob_lbah = 0; tf->hob_lbah = 0;
tf->protocol = qc->dev->xfer_protocol;
if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 || if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
scsicmd[0] == READ_16) { scsicmd[0] == READ_16) {
tf->command = qc->dev->read_cmd; tf->command = qc->dev->read_cmd;
tf->protocol = qc->dev->r_protocol;
qc->flags &= ~ATA_QCFLAG_WRITE;
VPRINTK("reading\n"); VPRINTK("reading\n");
} else { } else {
tf->command = qc->dev->write_cmd; tf->command = qc->dev->write_cmd;
tf->protocol = qc->dev->w_protocol; tf->flags |= ATA_TFLAG_WRITE;
qc->flags |= ATA_QCFLAG_WRITE;
VPRINTK("writing\n"); VPRINTK("writing\n");
} }
...@@ -886,7 +884,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev, ...@@ -886,7 +884,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
if (cmd->sc_data_direction == SCSI_DATA_WRITE) { if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
qc->flags |= ATA_QCFLAG_WRITE; qc->tf.flags |= ATA_TFLAG_WRITE;
DPRINTK("direction: write\n"); DPRINTK("direction: write\n");
} }
......
...@@ -393,11 +393,10 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf, ...@@ -393,11 +393,10 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
* and seq id (byte 2) * and seq id (byte 2)
*/ */
switch (tf->protocol) { switch (tf->protocol) {
case ATA_PROT_DMA_READ: case ATA_PROT_DMA:
if (!(tf->flags & ATA_TFLAG_WRITE))
buf32[0] = cpu_to_le32(PDC_PKT_READ); buf32[0] = cpu_to_le32(PDC_PKT_READ);
break; else
case ATA_PROT_DMA_WRITE:
buf32[0] = 0; buf32[0] = 0;
break; break;
...@@ -557,7 +556,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, ...@@ -557,7 +556,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
/* /*
* Set up ATA packet * Set up ATA packet
*/ */
if (tf->protocol == ATA_PROT_DMA_READ) if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
buf[i++] = PDC_PKT_READ; buf[i++] = PDC_PKT_READ;
else if (tf->protocol == ATA_PROT_NODATA) else if (tf->protocol == ATA_PROT_NODATA)
buf[i++] = PDC_PKT_NODATA; buf[i++] = PDC_PKT_NODATA;
...@@ -609,7 +608,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, ...@@ -609,7 +608,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
/* /*
* Set up Host DMA packet * Set up Host DMA packet
*/ */
if (tf->protocol == ATA_PROT_DMA_READ) if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
tmp = PDC_PKT_READ; tmp = PDC_PKT_READ;
else else
tmp = 0; tmp = 0;
...@@ -771,7 +770,7 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc) ...@@ -771,7 +770,7 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
struct ata_host_set *host_set = ap->host_set; struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no; unsigned int port_no = ap->port_no;
void *mmio = host_set->mmio_base; void *mmio = host_set->mmio_base;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE); unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 seq = (u8) (port_no + 1); u8 seq = (u8) (port_no + 1);
unsigned int doing_hdma = 0, port_ofs; unsigned int doing_hdma = 0, port_ofs;
...@@ -824,8 +823,9 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -824,8 +823,9 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
switch (qc->tf.protocol) { if ((qc->tf.protocol == ATA_PROT_DMA) && /* read */
case ATA_PROT_DMA_READ: (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
/* step two - DMA from DIMM to host */ /* step two - DMA from DIMM to host */
if (doing_hdma) { if (doing_hdma) {
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
...@@ -846,9 +846,9 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -846,9 +846,9 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
port_ofs + PDC_DIMM_HOST_PKT); port_ofs + PDC_DIMM_HOST_PKT);
} }
handled = 1; handled = 1;
break;
case ATA_PROT_DMA_WRITE: } else if (qc->tf.protocol == ATA_PROT_DMA) { /* write */
/* step one - DMA from host to DIMM */ /* step one - DMA from host to DIMM */
if (doing_hdma) { if (doing_hdma) {
u8 seq = (u8) (port_no + 1); u8 seq = (u8) (port_no + 1);
...@@ -871,18 +871,17 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -871,18 +871,17 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
pdc20621_pop_hdma(qc); pdc20621_pop_hdma(qc);
} }
handled = 1; handled = 1;
break;
case ATA_PROT_NODATA: /* command completion, but no data xfer */ /* command completion, but no data xfer */
} else if (qc->tf.protocol == ATA_PROT_NODATA) {
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
ata_qc_complete(qc, status, 0); ata_qc_complete(qc, status, 0);
handled = 1; handled = 1;
break;
default: } else {
ap->stats.idle_irq++; ap->stats.idle_irq++;
break;
} }
return handled; return handled;
...@@ -1002,8 +1001,7 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -1002,8 +1001,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
qc->scsidone = scsi_finish_command; qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ: case ATA_PROT_DMA:
case ATA_PROT_DMA_WRITE:
printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
ata_wait_idle(ap) | ATA_ERR, 0); ata_wait_idle(ap) | ATA_ERR, 0);
...@@ -1039,8 +1037,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap, ...@@ -1039,8 +1037,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
unsigned int handled = 0; unsigned int handled = 0;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ: case ATA_PROT_DMA:
case ATA_PROT_DMA_WRITE:
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
handled = 1; handled = 1;
break; break;
...@@ -1133,16 +1130,14 @@ static void pdc_dma_start(struct ata_queued_cmd *qc) ...@@ -1133,16 +1130,14 @@ static void pdc_dma_start(struct ata_queued_cmd *qc)
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{ {
if ((tf->protocol != ATA_PROT_DMA_READ) && if (tf->protocol != ATA_PROT_DMA)
(tf->protocol != ATA_PROT_DMA_WRITE))
ata_tf_load_mmio(ap, tf); ata_tf_load_mmio(ap, tf);
} }
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{ {
if ((tf->protocol != ATA_PROT_DMA_READ) && if (tf->protocol != ATA_PROT_DMA)
(tf->protocol != ATA_PROT_DMA_WRITE))
ata_exec_command_mmio(ap, tf); ata_exec_command_mmio(ap, tf);
} }
......
...@@ -105,10 +105,8 @@ enum { ...@@ -105,10 +105,8 @@ enum {
/* ATA taskfile protocols */ /* ATA taskfile protocols */
ATA_PROT_UNKNOWN = 0, ATA_PROT_UNKNOWN = 0,
ATA_PROT_NODATA = 1, ATA_PROT_NODATA = 1,
ATA_PROT_PIO_READ = 2, ATA_PROT_PIO = 2,
ATA_PROT_PIO_WRITE = 3, ATA_PROT_DMA = 4,
ATA_PROT_DMA_READ = 4,
ATA_PROT_DMA_WRITE = 5,
ATA_PROT_ATAPI = 6, ATA_PROT_ATAPI = 6,
ATA_PROT_ATAPI_DMA = 7, ATA_PROT_ATAPI_DMA = 7,
......
...@@ -108,11 +108,11 @@ enum { ...@@ -108,11 +108,11 @@ enum {
ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */
/* struct ata_taskfile flags */ /* struct ata_taskfile flags */
ATA_TFLAG_LBA48 = (1 << 0), ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */
ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */
ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */
ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */
ATA_QCFLAG_WRITE = (1 << 0), /* read==0, write==1 */
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_DMA = (1 << 2), /* data delivered via DMA */ ATA_QCFLAG_DMA = (1 << 2), /* data delivered via DMA */
ATA_QCFLAG_ATAPI = (1 << 3), /* is ATAPI packet command? */ ATA_QCFLAG_ATAPI = (1 << 3), /* is ATAPI packet command? */
...@@ -295,8 +295,7 @@ struct ata_device { ...@@ -295,8 +295,7 @@ struct ata_device {
*/ */
/* cache info about current transfer mode */ /* cache info about current transfer mode */
u8 r_protocol; /* taskfile read protocol */ u8 xfer_protocol; /* taskfile xfer protocol */
u8 w_protocol; /* taskfile write protocol */
u8 read_cmd; /* opcode to use on read */ u8 read_cmd; /* opcode to use on read */
u8 write_cmd; /* opcode to use on write */ u8 write_cmd; /* opcode to use on write */
}; };
......
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