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)
int rcmd = 0, wcmd = 0;
switch (protocol) {
case ATA_PROT_PIO_READ:
case ATA_PROT_PIO_WRITE:
case ATA_PROT_PIO:
if (lba48) {
rcmd = ATA_CMD_PIO_READ_EXT;
wcmd = ATA_CMD_PIO_WRITE_EXT;
......@@ -455,8 +454,7 @@ static int ata_prot_to_cmd(int protocol, int lba48)
}
break;
case ATA_PROT_DMA_READ:
case ATA_PROT_DMA_WRITE:
case ATA_PROT_DMA:
if (lba48) {
rcmd = ATA_CMD_READ_EXT;
wcmd = ATA_CMD_WRITE_EXT;
......@@ -479,13 +477,10 @@ static void ata_dev_set_protocol(struct ata_device *dev)
int lba48 = (dev->flags & ATA_DFLAG_LBA48);
int proto, cmd;
if (pio) {
proto = dev->r_protocol = ATA_PROT_PIO_READ;
dev->w_protocol = ATA_PROT_PIO_WRITE;
} else {
proto = dev->r_protocol = ATA_PROT_DMA_READ;
dev->w_protocol = ATA_PROT_DMA_WRITE;
}
if (pio)
proto = dev->xfer_protocol = ATA_PROT_PIO;
else
proto = dev->xfer_protocol = ATA_PROT_DMA;
cmd = ata_prot_to_cmd(proto, lba48);
if (cmd < 0)
......@@ -899,7 +894,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
retry:
ata_tf_init(ap, &tf, device);
tf.ctl |= ATA_NIEN;
tf.protocol = ATA_PROT_PIO_READ;
tf.protocol = ATA_PROT_PIO;
if (dev->class == ATA_DEV_ATA) {
tf.command = ATA_CMD_ID_ATA;
......@@ -1803,7 +1798,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg_dma_address(sg) = dma_address;
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;
}
......@@ -1904,8 +1899,7 @@ static void ata_pio_start (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
assert((qc->tf.protocol == ATA_PROT_PIO_READ) ||
(qc->tf.protocol == ATA_PROT_PIO_WRITE));
assert(qc->tf.protocol == ATA_PROT_PIO);
qc->flags |= ATA_QCFLAG_POLL;
qc->tf.ctl |= ATA_NIEN; /* disable interrupts */
......@@ -2025,12 +2019,12 @@ static void ata_pio_sector(struct ata_port *ap)
}
DPRINTK("data %s, drv_stat 0x%X\n",
qc->flags & ATA_QCFLAG_WRITE ? "write" : "read",
qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
status);
/* do the actual data transfer */
/* 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);
else
insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
......@@ -2095,8 +2089,7 @@ void ata_eng_timeout(struct ata_port *ap)
qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ:
case ATA_PROT_DMA_WRITE:
case ATA_PROT_DMA:
if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
......@@ -2320,7 +2313,7 @@ int ata_qc_issue(struct ata_queued_cmd *qc)
void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
{
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;
void *mmio = (void *) ap->ioaddr.bmdma_addr;
......@@ -2369,7 +2362,7 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
{
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;
/* load PRD table addr. */
......@@ -2464,8 +2457,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
unsigned int handled = 0;
switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ:
case ATA_PROT_DMA_WRITE:
case ATA_PROT_DMA:
if (ap->flags & ATA_FLAG_MMIO) {
void *mmio = (void *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
......
......@@ -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? */
/* 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[13] = 0x04;
} else {
......@@ -179,17 +179,15 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd,
tf->hob_lbal = 0;
tf->hob_lbam = 0;
tf->hob_lbah = 0;
tf->protocol = qc->dev->xfer_protocol;
if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
scsicmd[0] == READ_16) {
tf->command = qc->dev->read_cmd;
tf->protocol = qc->dev->r_protocol;
qc->flags &= ~ATA_QCFLAG_WRITE;
VPRINTK("reading\n");
} else {
tf->command = qc->dev->write_cmd;
tf->protocol = qc->dev->w_protocol;
qc->flags |= ATA_QCFLAG_WRITE;
tf->flags |= ATA_TFLAG_WRITE;
VPRINTK("writing\n");
}
......@@ -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;
if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
qc->flags |= ATA_QCFLAG_WRITE;
qc->tf.flags |= ATA_TFLAG_WRITE;
DPRINTK("direction: write\n");
}
......
......@@ -393,11 +393,10 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
* and seq id (byte 2)
*/
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);
break;
case ATA_PROT_DMA_WRITE:
else
buf32[0] = 0;
break;
......@@ -557,7 +556,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
/*
* 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;
else if (tf->protocol == ATA_PROT_NODATA)
buf[i++] = PDC_PKT_NODATA;
......@@ -609,7 +608,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
/*
* 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;
else
tmp = 0;
......@@ -771,7 +770,7 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
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);
unsigned int doing_hdma = 0, port_ofs;
......@@ -824,8 +823,9 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ENTER\n");
switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ:
if ((qc->tf.protocol == ATA_PROT_DMA) && /* read */
(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
/* step two - DMA from DIMM to host */
if (doing_hdma) {
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,
port_ofs + PDC_DIMM_HOST_PKT);
}
handled = 1;
break;
case ATA_PROT_DMA_WRITE:
} else if (qc->tf.protocol == ATA_PROT_DMA) { /* write */
/* step one - DMA from host to DIMM */
if (doing_hdma) {
u8 seq = (u8) (port_no + 1);
......@@ -871,18 +871,17 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
pdc20621_pop_hdma(qc);
}
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);
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
ata_qc_complete(qc, status, 0);
handled = 1;
break;
default:
} else {
ap->stats.idle_irq++;
break;
}
return handled;
......@@ -1002,8 +1001,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ:
case ATA_PROT_DMA_WRITE:
case ATA_PROT_DMA:
printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
ata_wait_idle(ap) | ATA_ERR, 0);
......@@ -1039,8 +1037,7 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
unsigned int handled = 0;
switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ:
case ATA_PROT_DMA_WRITE:
case ATA_PROT_DMA:
pdc_dma_complete(ap, qc);
handled = 1;
break;
......@@ -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)
{
if ((tf->protocol != ATA_PROT_DMA_READ) &&
(tf->protocol != ATA_PROT_DMA_WRITE))
if (tf->protocol != ATA_PROT_DMA)
ata_tf_load_mmio(ap, tf);
}
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
if ((tf->protocol != ATA_PROT_DMA_READ) &&
(tf->protocol != ATA_PROT_DMA_WRITE))
if (tf->protocol != ATA_PROT_DMA)
ata_exec_command_mmio(ap, tf);
}
......
......@@ -105,10 +105,8 @@ enum {
/* ATA taskfile protocols */
ATA_PROT_UNKNOWN = 0,
ATA_PROT_NODATA = 1,
ATA_PROT_PIO_READ = 2,
ATA_PROT_PIO_WRITE = 3,
ATA_PROT_DMA_READ = 4,
ATA_PROT_DMA_WRITE = 5,
ATA_PROT_PIO = 2,
ATA_PROT_DMA = 4,
ATA_PROT_ATAPI = 6,
ATA_PROT_ATAPI_DMA = 7,
......
......@@ -108,11 +108,11 @@ enum {
ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */
/* 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_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_DMA = (1 << 2), /* data delivered via DMA */
ATA_QCFLAG_ATAPI = (1 << 3), /* is ATAPI packet command? */
......@@ -295,8 +295,7 @@ struct ata_device {
*/
/* cache info about current transfer mode */
u8 r_protocol; /* taskfile read protocol */
u8 w_protocol; /* taskfile write protocol */
u8 xfer_protocol; /* taskfile xfer protocol */
u8 read_cmd; /* opcode to use on read */
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