it821x: use ->pio_mode value to determine pair device speed
[safe/jmp/linux-2.6] / drivers / ide / ide-dma-sff.c
index bcdadc7..e4cdf78 100644 (file)
@@ -38,10 +38,9 @@ int config_drive_for_dma(ide_drive_t *drive)
         * Enable DMA on any drive that has mode2 DMA
         * (multi or single) enabled
         */
-       if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
-               if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
-                   (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
-                       return 1;
+       if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
+           (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
+               return 1;
 
        /* Consult the list of known "good" drives */
        if (ide_dma_good_drive(drive))
@@ -61,6 +60,16 @@ u8 ide_dma_sff_read_status(ide_hwif_t *hwif)
 }
 EXPORT_SYMBOL_GPL(ide_dma_sff_read_status);
 
+static void ide_dma_sff_write_status(ide_hwif_t *hwif, u8 val)
+{
+       unsigned long addr = hwif->dma_base + ATA_DMA_STATUS;
+
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               writeb(val, (void __iomem *)addr);
+       else
+               outb(val, addr);
+}
+
 /**
  *     ide_dma_host_set        -       Enable/disable DMA on a host
  *     @drive: drive to control
@@ -80,11 +89,7 @@ void ide_dma_host_set(ide_drive_t *drive, int on)
        else
                dma_stat &= ~(1 << (5 + unit));
 
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               writeb(dma_stat,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
+       ide_dma_sff_write_status(hwif, dma_stat);
 }
 EXPORT_SYMBOL_GPL(ide_dma_host_set);
 
@@ -105,7 +110,7 @@ EXPORT_SYMBOL_GPL(ide_dma_host_set);
  *     May also be invoked from trm290.c
  */
 
-int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+int ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
        ide_hwif_t *hwif = drive->hwif;
        __le32 *table = (__le32 *)hwif->dmatable_cpu;
@@ -114,11 +119,7 @@ int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
        struct scatterlist *sg;
        u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290);
 
-       hwif->sg_nents = ide_build_sglist(drive, rq);
-       if (hwif->sg_nents == 0)
-               return 0;
-
-       for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+       for_each_sg(hwif->sg_table, sg, cmd->sg_nents, i) {
                u32 cur_addr, cur_len, xcount, bcount;
 
                cur_addr = sg_dma_address(sg);
@@ -164,8 +165,6 @@ use_pio_instead:
        printk(KERN_ERR "%s: %s\n", drive->name,
                count ? "DMA table too small" : "empty DMA table?");
 
-       ide_destroy_dmatable(drive);
-
        return 0; /* revert to PIO for this request */
 }
 EXPORT_SYMBOL_GPL(ide_build_dmatable);
@@ -173,6 +172,7 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
 /**
  *     ide_dma_setup   -       begin a DMA phase
  *     @drive: target device
+ *     @cmd: command
  *
  *     Build an IDE DMA PRD (IDE speak for scatter gather table)
  *     and then set up the DMA transfer registers for a device
@@ -183,22 +183,21 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
  *     is returned.
  */
 
-int ide_dma_setup(ide_drive_t *drive)
+int ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
        ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->rq;
-       unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR;
        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+       u8 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR;
        u8 dma_stat;
 
        /* fall back to pio! */
-       if (!ide_build_dmatable(drive, rq)) {
-               ide_map_sg(drive, rq);
+       if (ide_build_dmatable(drive, cmd) == 0) {
+               ide_map_sg(drive, cmd);
                return 1;
        }
 
        /* PRD table */
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
+       if (mmio)
                writel(hwif->dmatable_dma,
                       (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
        else
@@ -206,28 +205,22 @@ int ide_dma_setup(ide_drive_t *drive)
 
        /* specify r/w */
        if (mmio)
-               writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+               writeb(rw, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
        else
-               outb(reading, hwif->dma_base + ATA_DMA_CMD);
+               outb(rw, hwif->dma_base + ATA_DMA_CMD);
 
        /* read DMA status for INTR & ERROR flags */
        dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
 
        /* clear INTR & ERROR flags */
-       if (mmio)
-               writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
-                    hwif->dma_base + ATA_DMA_STATUS);
+       ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR);
 
-       drive->waiting_for_dma = 1;
        return 0;
 }
 EXPORT_SYMBOL_GPL(ide_dma_setup);
 
 /**
- *     dma_timer_expiry        -       handle a DMA timeout
+ *     ide_dma_sff_timer_expiry        -       handle a DMA timeout
  *     @drive: Drive that timed out
  *
  *     An IDE DMA transfer timed out. In the event of an error we ask
@@ -240,7 +233,7 @@ EXPORT_SYMBOL_GPL(ide_dma_setup);
  *     This can occur if an interrupt is lost or due to hang or bugs.
  */
 
-static int dma_timer_expiry(ide_drive_t *drive)
+int ide_dma_sff_timer_expiry(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
@@ -264,14 +257,7 @@ static int dma_timer_expiry(ide_drive_t *drive)
 
        return 0;       /* Status is unknown -- reset the bus */
 }
-
-void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-       /* issue cmd to drive */
-       ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD,
-                           dma_timer_expiry);
-}
-EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
+EXPORT_SYMBOL_GPL(ide_dma_sff_timer_expiry);
 
 void ide_dma_start(ide_drive_t *drive)
 {
@@ -291,8 +277,6 @@ void ide_dma_start(ide_drive_t *drive)
                dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
                outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
        }
-
-       wmb();
 }
 EXPORT_SYMBOL_GPL(ide_dma_start);
 
@@ -300,13 +284,10 @@ EXPORT_SYMBOL_GPL(ide_dma_start);
 int ide_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 dma_stat = 0, dma_cmd = 0, mask;
-
-       drive->waiting_for_dma = 0;
+       u8 dma_stat = 0, dma_cmd = 0;
 
        /* stop DMA */
-       if (mmio) {
+       if (hwif->host_flags & IDE_HFLAG_MMIO) {
                dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
                writeb(dma_cmd & ~ATA_DMA_START,
                       (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
@@ -318,21 +299,13 @@ int ide_dma_end(ide_drive_t *drive)
        /* get DMA status */
        dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
 
-       if (mmio)
-               /* clear the INTR & ERROR bits */
-               writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
-                    hwif->dma_base + ATA_DMA_STATUS);
+       /* clear INTR & ERROR bits */
+       ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR);
 
-       /* purge DMA mappings */
-       ide_destroy_dmatable(drive);
-       wmb();
+#define CHECK_DMA_MASK (ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR)
 
        /* verify good DMA status */
-       mask = ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR;
-       if ((dma_stat & mask) != ATA_DMA_INTR)
+       if ((dma_stat & CHECK_DMA_MASK) != ATA_DMA_INTR)
                return 0x10 | dma_stat;
        return 0;
 }
@@ -351,12 +324,11 @@ EXPORT_SYMBOL_GPL(ide_dma_test_irq);
 const struct ide_dma_ops sff_dma_ops = {
        .dma_host_set           = ide_dma_host_set,
        .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = ide_dma_start,
        .dma_end                = ide_dma_end,
        .dma_test_irq           = ide_dma_test_irq,
-       .dma_timeout            = ide_dma_timeout,
        .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timer_expiry       = ide_dma_sff_timer_expiry,
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 EXPORT_SYMBOL_GPL(sff_dma_ops);