fbdev: move FBIO_WAITFORVSYNC to linux/fb.h
[safe/jmp/linux-2.6] / drivers / ide / ide-dma.c
index d935a6e..06b14bc 100644 (file)
  */
 
 #include <linux/types.h>
+#include <linux/gfp.h>
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
-#include <linux/io.h>
 
 static const struct drive_list_entry drive_whitelist[] = {
        { "Micropolis 2112A"    ,       NULL            },
@@ -90,16 +90,21 @@ static const struct drive_list_entry drive_blacklist[] = {
 ide_startstop_t ide_dma_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
+       struct ide_cmd *cmd = &hwif->cmd;
        u8 stat = 0, dma_stat = 0;
 
+       drive->waiting_for_dma = 0;
        dma_stat = hwif->dma_ops->dma_end(drive);
+       ide_dma_unmap_sg(drive, cmd);
        stat = hwif->tp_ops->read_status(hwif);
 
        if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
                if (!dma_stat) {
-                       struct request *rq = hwif->hwgroup->rq;
-
-                       task_end_request(drive, rq, stat);
+                       if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
+                               ide_finish_cmd(drive, cmd, stat);
+                       else
+                               ide_complete_rq(drive, 0,
+                                               blk_rq_sectors(cmd->rq) << 9);
                        return ide_stopped;
                }
                printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
@@ -107,17 +112,16 @@ ide_startstop_t ide_dma_intr(ide_drive_t *drive)
        }
        return ide_error(drive, "dma_intr", stat);
 }
-EXPORT_SYMBOL_GPL(ide_dma_intr);
 
-static int ide_dma_good_drive(ide_drive_t *drive)
+int ide_dma_good_drive(ide_drive_t *drive)
 {
        return ide_in_drive_list(drive->id, drive_whitelist);
 }
 
 /**
- *     ide_build_sglist        -       map IDE scatter gather for DMA I/O
- *     @drive: the drive to build the DMA table for
- *     @rq: the request holding the sg list
+ *     ide_dma_map_sg  -       map IDE scatter gather for DMA I/O
+ *     @drive: the drive to map the DMA table for
+ *     @cmd: command
  *
  *     Perform the DMA mapping magic necessary to access the source or
  *     target buffers of a request via DMA.  The lower layers of the
@@ -125,109 +129,28 @@ static int ide_dma_good_drive(ide_drive_t *drive)
  *     operate in a portable fashion.
  */
 
-int ide_build_sglist(ide_drive_t *drive, struct request *rq)
+static int ide_dma_map_sg(ide_drive_t *drive, struct ide_cmd *cmd)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct scatterlist *sg = hwif->sg_table;
-
-       ide_map_sg(drive, rq);
-
-       if (rq_data_dir(rq) == READ)
-               hwif->sg_dma_direction = DMA_FROM_DEVICE;
-       else
-               hwif->sg_dma_direction = DMA_TO_DEVICE;
-
-       return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
-                         hwif->sg_dma_direction);
-}
-EXPORT_SYMBOL_GPL(ide_build_sglist);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- *     ide_build_dmatable      -       build IDE DMA table
- *
- *     ide_build_dmatable() prepares a dma request. We map the command
- *     to get the pci bus addresses of the buffers and then build up
- *     the PRD table that the IDE layer wants to be fed.
- *
- *     Most chipsets correctly interpret a length of 0x0000 as 64KB,
- *     but at least one (e.g. CS5530) misinterprets it as zero (!).
- *     So we break the 64KB entry into two 32KB entries instead.
- *
- *     Returns the number of built PRD entries if all went okay,
- *     returns 0 otherwise.
- *
- *     May also be invoked from trm290.c
- */
-
-int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       __le32 *table = (__le32 *)hwif->dmatable_cpu;
-       unsigned int is_trm290  = (hwif->chipset == ide_trm290) ? 1 : 0;
-       unsigned int count = 0;
        int i;
-       struct scatterlist *sg;
 
-       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) {
-               u32 cur_addr, cur_len, xcount, bcount;
-
-               cur_addr = sg_dma_address(sg);
-               cur_len = sg_dma_len(sg);
-
-               /*
-                * Fill in the dma table, without crossing any 64kB boundaries.
-                * Most hardware requires 16-bit alignment of all blocks,
-                * but the trm290 requires 32-bit alignment.
-                */
-
-               while (cur_len) {
-                       if (count++ >= PRD_ENTRIES)
-                               goto use_pio_instead;
-
-                       bcount = 0x10000 - (cur_addr & 0xffff);
-                       if (bcount > cur_len)
-                               bcount = cur_len;
-                       *table++ = cpu_to_le32(cur_addr);
-                       xcount = bcount & 0xffff;
-                       if (is_trm290)
-                               xcount = ((xcount >> 2) - 1) << 16;
-                       if (xcount == 0x0000) {
-                               if (count++ >= PRD_ENTRIES)
-                                       goto use_pio_instead;
-                               *table++ = cpu_to_le32(0x8000);
-                               *table++ = cpu_to_le32(cur_addr + 0x8000);
-                               xcount = 0x8000;
-                       }
-                       *table++ = cpu_to_le32(xcount);
-                       cur_addr += bcount;
-                       cur_len -= bcount;
-               }
-       }
+       if (cmd->tf_flags & IDE_TFLAG_WRITE)
+               cmd->sg_dma_direction = DMA_TO_DEVICE;
+       else
+               cmd->sg_dma_direction = DMA_FROM_DEVICE;
 
-       if (count) {
-               if (!is_trm290)
-                       *--table |= cpu_to_le32(0x80000000);
-               return count;
+       i = dma_map_sg(hwif->dev, sg, cmd->sg_nents, cmd->sg_dma_direction);
+       if (i) {
+               cmd->orig_sg_nents = cmd->sg_nents;
+               cmd->sg_nents = i;
        }
 
-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 */
+       return i;
 }
-EXPORT_SYMBOL_GPL(ide_build_dmatable);
-#endif
 
 /**
- *     ide_destroy_dmatable    -       clean up DMA mapping
+ *     ide_dma_unmap_sg        -       clean up DMA mapping
  *     @drive: The drive to unmap
  *
  *     Teardown mappings after DMA has completed. This must be called
@@ -237,128 +160,14 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
  *     time.
  */
 
-void ide_destroy_dmatable(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
-                    hwif->sg_dma_direction);
-}
-EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- *     config_drive_for_dma    -       attempt to activate IDE DMA
- *     @drive: the drive to place in DMA mode
- *
- *     If the drive supports at least mode 2 DMA or UDMA of any kind
- *     then attempt to place it into DMA mode. Drives that are known to
- *     support DMA but predate the DMA properties or that are known
- *     to have DMA handling bugs are also set up appropriately based
- *     on the good/bad drive lists.
- */
-
-static int config_drive_for_dma(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u16 *id = drive->id;
-
-       if (drive->media != ide_disk) {
-               if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
-                       return 0;
-       }
-
-       /*
-        * Enable DMA on any drive that has
-        * UltraDMA (mode 0/1/2/3/4/5/6) enabled
-        */
-       if ((id[ATA_ID_FIELD_VALID] & 4) &&
-           ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
-               return 1;
-
-       /*
-        * 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;
-
-       /* Consult the list of known "good" drives */
-       if (ide_dma_good_drive(drive))
-               return 1;
-
-       return 0;
-}
-
-/**
- *     dma_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
- *     the driver to resolve the problem, if a DMA transfer is still
- *     in progress we continue to wait (arguably we need to add a
- *     secondary 'I don't care what the drive thinks' timeout here)
- *     Finally if we have an interrupt we let it complete the I/O.
- *     But only one time - we clear expiry and if it's still not
- *     completed after WAIT_CMD, we error and retry in PIO.
- *     This can occur if an interrupt is lost or due to hang or bugs.
- */
-
-static int dma_timer_expiry(ide_drive_t *drive)
+void ide_dma_unmap_sg(ide_drive_t *drive, struct ide_cmd *cmd)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
-               drive->name, __func__, dma_stat);
-
-       if ((dma_stat & 0x18) == 0x18)  /* BUSY Stupid Early Timer !! */
-               return WAIT_CMD;
 
-       hwif->hwgroup->expiry = NULL;   /* one free ride for now */
-
-       /* 1 dmaing, 2 error, 4 intr */
-       if (dma_stat & 2)       /* ERROR */
-               return -1;
-
-       if (dma_stat & 1)       /* DMAing */
-               return WAIT_CMD;
-
-       if (dma_stat & 4)       /* Got an Interrupt */
-               return WAIT_CMD;
-
-       return 0;       /* Status is unknown -- reset the bus */
+       dma_unmap_sg(hwif->dev, hwif->sg_table, cmd->orig_sg_nents,
+                    cmd->sg_dma_direction);
 }
-
-/**
- *     ide_dma_host_set        -       Enable/disable DMA on a host
- *     @drive: drive to control
- *
- *     Enable/disable DMA on an IDE controller following generic
- *     bus-mastering IDE controller behaviour.
- */
-
-void ide_dma_host_set(ide_drive_t *drive, int on)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 unit = drive->dn & 1;
-       u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       if (on)
-               dma_stat |= (1 << (5 + unit));
-       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);
-}
-EXPORT_SYMBOL_GPL(ide_dma_host_set);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF  */
+EXPORT_SYMBOL_GPL(ide_dma_unmap_sg);
 
 /**
  *     ide_dma_off_quietly     -       Generic DMA kill
@@ -406,154 +215,6 @@ void ide_dma_on(ide_drive_t *drive)
        drive->hwif->dma_ops->dma_host_set(drive, 1);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- *     ide_dma_setup   -       begin a DMA phase
- *     @drive: target device
- *
- *     Build an IDE DMA PRD (IDE speak for scatter gather table)
- *     and then set up the DMA transfer registers for a device
- *     that follows generic IDE PCI DMA behaviour. Controllers can
- *     override this function if they need to
- *
- *     Returns 0 on success. If a PIO fallback is required then 1
- *     is returned.
- */
-
-int ide_dma_setup(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->hwgroup->rq;
-       unsigned int reading;
-       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 dma_stat;
-
-       if (rq_data_dir(rq))
-               reading = 0;
-       else
-               reading = 1 << 3;
-
-       /* fall back to pio! */
-       if (!ide_build_dmatable(drive, rq)) {
-               ide_map_sg(drive, rq);
-               return 1;
-       }
-
-       /* PRD table */
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               writel(hwif->dmatable_dma,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
-       else
-               outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
-
-       /* specify r/w */
-       if (mmio)
-               writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-       else
-               outb(reading, hwif->dma_base + ATA_DMA_CMD);
-
-       /* read DMA status for INTR & ERROR flags */
-       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       /* clear INTR & ERROR flags */
-       if (mmio)
-               writeb(dma_stat | 6,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-
-       drive->waiting_for_dma = 1;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ide_dma_setup);
-
-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);
-
-void ide_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 dma_cmd;
-
-       /* Note that this is done *after* the cmd has
-        * been issued to the drive, as per the BM-IDE spec.
-        * The Promise Ultra33 doesn't work correctly when
-        * we do this part before issuing the drive cmd.
-        */
-       if (hwif->host_flags & IDE_HFLAG_MMIO) {
-               dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-               /* start DMA */
-               writeb(dma_cmd | 1,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-       } else {
-               dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-               outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
-       }
-
-       wmb();
-}
-EXPORT_SYMBOL_GPL(ide_dma_start);
-
-/* returns 1 on error, 0 otherwise */
-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;
-
-       drive->waiting_for_dma = 0;
-
-       if (mmio) {
-               /* get DMA command mode */
-               dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-               /* stop DMA */
-               writeb(dma_cmd & ~1,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-       } else {
-               dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-               outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
-       }
-
-       /* get DMA status */
-       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       if (mmio)
-               /* clear the INTR & ERROR bits */
-               writeb(dma_stat | 6,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-
-       /* purge DMA mappings */
-       ide_destroy_dmatable(drive);
-       /* verify good DMA status */
-       wmb();
-       return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
-}
-EXPORT_SYMBOL_GPL(ide_dma_end);
-
-/* returns 1 if dma irq issued, 0 otherwise */
-int ide_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       /* return 1 if INTR asserted */
-       if ((dma_stat & 4) == 4)
-               return 1;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ide_dma_test_irq);
-#else
-static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
-
 int __ide_dma_bad_drive(ide_drive_t *drive)
 {
        u16 *id = drive->id;
@@ -585,12 +246,11 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
        case XFER_UDMA_0:
                if ((id[ATA_ID_FIELD_VALID] & 4) == 0)
                        break;
-
+               mask = id[ATA_ID_UDMA_MODES];
                if (port_ops && port_ops->udma_filter)
-                       mask = port_ops->udma_filter(drive);
+                       mask &= port_ops->udma_filter(drive);
                else
-                       mask = hwif->ultra_mask;
-               mask &= id[ATA_ID_UDMA_MODES];
+                       mask &= hwif->ultra_mask;
 
                /*
                 * avoid false cable warning from eighty_ninty_three()
@@ -601,18 +261,23 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
                }
                break;
        case XFER_MW_DMA_0:
-               if ((id[ATA_ID_FIELD_VALID] & 2) == 0)
-                       break;
+               mask = id[ATA_ID_MWDMA_MODES];
+
+               /* Also look for the CF specific MWDMA modes... */
+               if (ata_id_is_cfa(id) && (id[ATA_ID_CFA_MODES] & 0x38)) {
+                       u8 mode = ((id[ATA_ID_CFA_MODES] & 0x38) >> 3) - 1;
+
+                       mask |= ((2 << mode) - 1) << 3;
+               }
+
                if (port_ops && port_ops->mdma_filter)
-                       mask = port_ops->mdma_filter(drive);
+                       mask &= port_ops->mdma_filter(drive);
                else
-                       mask = hwif->mwdma_mask;
-               mask &= id[ATA_ID_MWDMA_MODES];
+                       mask &= hwif->mwdma_mask;
                break;
        case XFER_SW_DMA_0:
-               if (id[ATA_ID_FIELD_VALID] & 2) {
-                       mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask;
-               } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) {
+               mask = id[ATA_ID_SWDMA_MODES];
+               if (!(mask & ATA_SWDMA2) && (id[ATA_ID_OLD_DMA_MODES] >> 8)) {
                        u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8;
 
                        /*
@@ -620,8 +285,9 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
                         * (the maximum allowed mode is XFER_SW_DMA_2)
                         */
                        if (mode <= 2)
-                               mask = ((2 << mode) - 1) & hwif->swdma_mask;
+                               mask = (2 << mode) - 1;
                }
+               mask &= hwif->swdma_mask;
                break;
        default:
                BUG();
@@ -682,7 +348,6 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
 
        return mode;
 }
-EXPORT_SYMBOL_GPL(ide_find_dma_mode);
 
 static int ide_tune_dma(ide_drive_t *drive)
 {
@@ -697,9 +362,6 @@ static int ide_tune_dma(ide_drive_t *drive)
        if (__ide_dma_bad_drive(drive))
                return 0;
 
-       if (ide_id_dma_bug(drive))
-               return 0;
-
        if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
                return config_drive_for_dma(drive);
 
@@ -730,25 +392,6 @@ static int ide_dma_check(ide_drive_t *drive)
        return -1;
 }
 
-int ide_id_dma_bug(ide_drive_t *drive)
-{
-       u16 *id = drive->id;
-
-       if (id[ATA_ID_FIELD_VALID] & 4) {
-               if ((id[ATA_ID_UDMA_MODES] >> 8) &&
-                   (id[ATA_ID_MWDMA_MODES] >> 8))
-                       goto err_out;
-       } else if (id[ATA_ID_FIELD_VALID] & 2) {
-               if ((id[ATA_ID_MWDMA_MODES] >> 8) &&
-                   (id[ATA_ID_SWDMA_MODES] >> 8))
-                       goto err_out;
-       }
-       return 0;
-err_out:
-       printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
-       return 1;
-}
-
 int ide_set_dma(ide_drive_t *drive)
 {
        int rc;
@@ -796,20 +439,64 @@ void ide_dma_lost_irq(ide_drive_t *drive)
 }
 EXPORT_SYMBOL_GPL(ide_dma_lost_irq);
 
-void ide_dma_timeout(ide_drive_t *drive)
+/*
+ * un-busy the port etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_dma_ops *dma_ops = hwif->dma_ops;
+       struct ide_cmd *cmd = &hwif->cmd;
+       struct request *rq;
+       ide_startstop_t ret = ide_stopped;
 
-       printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
+       /*
+        * end current dma transaction
+        */
 
-       if (hwif->dma_ops->dma_test_irq(drive))
-               return;
+       if (error < 0) {
+               printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+               drive->waiting_for_dma = 0;
+               (void)dma_ops->dma_end(drive);
+               ide_dma_unmap_sg(drive, cmd);
+               ret = ide_error(drive, "dma timeout error",
+                               hwif->tp_ops->read_status(hwif));
+       } else {
+               printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+               if (dma_ops->dma_clear)
+                       dma_ops->dma_clear(drive);
+               printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
+               if (dma_ops->dma_test_irq(drive) == 0) {
+                       ide_dump_status(drive, "DMA timeout",
+                                       hwif->tp_ops->read_status(hwif));
+                       drive->waiting_for_dma = 0;
+                       (void)dma_ops->dma_end(drive);
+                       ide_dma_unmap_sg(drive, cmd);
+               }
+       }
 
-       ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
+       /*
+        * disable dma for now, but remember that we did so because of
+        * a timeout -- we'll reenable after we finish this next request
+        * (or rather the first chunk of it) in pio.
+        */
+       drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
+       drive->retry_pio++;
+       ide_dma_off_quietly(drive);
 
-       hwif->dma_ops->dma_end(drive);
+       /*
+        * un-busy drive etc and make sure request is sane
+        */
+       rq = hwif->rq;
+       if (rq) {
+               hwif->rq = NULL;
+               rq->errors = 0;
+               ide_requeue_and_plug(drive, rq);
+       }
+       return ret;
 }
-EXPORT_SYMBOL_GPL(ide_dma_timeout);
 
 void ide_release_dma_engine(ide_hwif_t *hwif)
 {
@@ -847,16 +534,24 @@ int ide_allocate_dma_engine(ide_hwif_t *hwif)
 }
 EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-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,
-};
-EXPORT_SYMBOL_GPL(sff_dma_ops);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
+int ide_dma_prepare(ide_drive_t *drive, struct ide_cmd *cmd)
+{
+       const struct ide_dma_ops *dma_ops = drive->hwif->dma_ops;
+
+       if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 ||
+           (dma_ops->dma_check && dma_ops->dma_check(drive, cmd)))
+               goto out;
+       ide_map_sg(drive, cmd);
+       if (ide_dma_map_sg(drive, cmd) == 0)
+               goto out_map;
+       if (dma_ops->dma_setup(drive, cmd))
+               goto out_dma_unmap;
+       drive->waiting_for_dma = 1;
+       return 0;
+out_dma_unmap:
+       ide_dma_unmap_sg(drive, cmd);
+out_map:
+       ide_map_sg(drive, cmd);
+out:
+       return 1;
+}