Commit 4b01f66c authored by Jeff Garzik's avatar Jeff Garzik

[libata] update dma start/stop path to only set/clear the bits we care about

Legacy IDE software has traditionally unconditionally cleared the
bits in the IDE BMDMA control register, but at least one controller
has important bits in the 'reserved' area that we don't want to touch.
So now, we only set/clear the data-direction and dma-start bits, and
leave the rest alone.
parent 032d9317
...@@ -2263,9 +2263,12 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) ...@@ -2263,9 +2263,12 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
mb(); /* make sure PRD table writes are visible to controller */ mb(); /* make sure PRD table writes are visible to controller */
writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
/* specify data direction */ /* specify data direction, triple-check start bit is clear */
/* FIXME: redundant to later start-dma command? */ dmactl = readb(mmio + ATA_DMA_CMD);
writeb(rw ? 0 : ATA_DMA_WR, mmio + ATA_DMA_CMD); dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
if (!rw)
dmactl |= ATA_DMA_WR;
writeb(dmactl, mmio + ATA_DMA_CMD);
/* clear interrupt, error bits */ /* clear interrupt, error bits */
host_stat = readb(mmio + ATA_DMA_STATUS); host_stat = readb(mmio + ATA_DMA_STATUS);
...@@ -2275,7 +2278,6 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) ...@@ -2275,7 +2278,6 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
ap->ops->exec_command(ap, &qc->tf); ap->ops->exec_command(ap, &qc->tf);
/* start host DMA transaction */ /* start host DMA transaction */
dmactl = readb(mmio + ATA_DMA_CMD);
writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
/* Strictly, one may wish to issue a readb() here, to /* Strictly, one may wish to issue a readb() here, to
...@@ -2308,9 +2310,12 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc) ...@@ -2308,9 +2310,12 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
/* load PRD table addr. */ /* load PRD table addr. */
outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
/* specify data direction */ /* specify data direction, triple-check start bit is clear */
/* FIXME: redundant to later start-dma command? */ dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
outb(rw ? 0 : ATA_DMA_WR, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
if (!rw)
dmactl |= ATA_DMA_WR;
outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
/* clear interrupt, error bits */ /* clear interrupt, error bits */
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
...@@ -2321,7 +2326,6 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc) ...@@ -2321,7 +2326,6 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
ap->ops->exec_command(ap, &qc->tf); ap->ops->exec_command(ap, &qc->tf);
/* start host DMA transaction */ /* start host DMA transaction */
dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
outb(dmactl | ATA_DMA_START, outb(dmactl | ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD); ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
} }
...@@ -2344,14 +2348,16 @@ static void ata_dma_complete(struct ata_port *ap, u8 host_stat, ...@@ -2344,14 +2348,16 @@ static void ata_dma_complete(struct ata_port *ap, u8 host_stat,
void *mmio = (void *) ap->ioaddr.bmdma_addr; void *mmio = (void *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */ /* clear start/stop bit */
writeb(0, mmio + ATA_DMA_CMD); writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
/* ack intr, err bits */ /* ack intr, err bits */
writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
mmio + ATA_DMA_STATUS); mmio + ATA_DMA_STATUS);
} else { } else {
/* clear start/stop bit */ /* clear start/stop bit */
outb(0, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
/* ack intr, err bits */ /* ack intr, err bits */
outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
......
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