]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-dma.c
ide: introduce CONFIG_BLK_DEV_IDEDMA_SFF option
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-dma.c
index 5bf32038dc435ed029644d425045efbdde610397..d0e7b537353e38ea1bb23ff6f0604f0d93777752 100644 (file)
@@ -1,15 +1,13 @@
 /*
- *  linux/drivers/ide/ide-dma.c                Version 4.10    June 9, 2000
+ *  Copyright (C) 1995-1998   Mark Lord
+ *  Copyright (C) 1999-2000   Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2004, 2007  Bartlomiej Zolnierkiewicz
  *
- *  Copyright (c) 1999-2000    Andre Hedrick <andre@linux-ide.org>
  *  May be copied or modified under the terms of the GNU General Public License
  */
 
 /*
  *  Special Thanks to Mark for his Six years of work.
- *
- *  Copyright (c) 1995-1998  Mark Lord
- *  May be copied or modified under the terms of the GNU General Public License
  */
 
 /*
@@ -85,6 +83,7 @@
 #include <linux/ide.h>
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -148,7 +147,8 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
        u8 stat = 0, dma_stat = 0;
 
        dma_stat = HWIF(drive)->ide_dma_end(drive);
-       stat = HWIF(drive)->INB(IDE_STATUS_REG);        /* get drive status */
+       stat = ide_read_status(drive);
+
        if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
                if (!dma_stat) {
                        struct request *rq = HWGROUP(drive)->rq;
@@ -169,16 +169,15 @@ static int ide_dma_good_drive(ide_drive_t *drive)
        return ide_in_drive_list(drive->id, drive_whitelist);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 /**
  *     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
  *
- *     Perform the PCI mapping magic necessary to access the source or
- *     target buffers of a request via PCI DMA. The lower layers of the
+ *     Perform the DMA mapping magic necessary to access the source or
+ *     target buffers of a request via DMA.  The lower layers of the
  *     kernel provide the necessary cache management so that we can
- *     operate in a portable fashion
+ *     operate in a portable fashion.
  */
 
 int ide_build_sglist(ide_drive_t *drive, struct request *rq)
@@ -186,20 +185,20 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
        ide_hwif_t *hwif = HWIF(drive);
        struct scatterlist *sg = hwif->sg_table;
 
-       BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256);
-
        ide_map_sg(drive, rq);
 
        if (rq_data_dir(rq) == READ)
-               hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+               hwif->sg_dma_direction = DMA_FROM_DEVICE;
        else
-               hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+               hwif->sg_dma_direction = DMA_TO_DEVICE;
 
-       return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
+       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
  *
@@ -284,16 +283,17 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
                        *--table |= cpu_to_le32(0x80000000);
                return count;
        }
+
        printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
+
 use_pio_instead:
-       pci_unmap_sg(hwif->pci_dev,
-                    hwif->sg_table,
-                    hwif->sg_nents,
-                    hwif->sg_dma_direction);
+       ide_destroy_dmatable(drive);
+
        return 0; /* revert to PIO for this request */
 }
 
 EXPORT_SYMBOL_GPL(ide_build_dmatable);
+#endif
 
 /**
  *     ide_destroy_dmatable    -       clean up DMA mapping
@@ -308,15 +308,15 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
  
 void ide_destroy_dmatable (ide_drive_t *drive)
 {
-       struct pci_dev *dev = HWIF(drive)->pci_dev;
-       struct scatterlist *sg = HWIF(drive)->sg_table;
-       int nents = HWIF(drive)->sg_nents;
+       ide_hwif_t *hwif = drive->hwif;
 
-       pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+       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
@@ -424,7 +424,7 @@ void ide_dma_host_set(ide_drive_t *drive, int on)
 }
 
 EXPORT_SYMBOL_GPL(ide_dma_host_set);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
+#endif /* CONFIG_BLK_DEV_IDEDMA_SFF  */
 
 /**
  *     ide_dma_off_quietly     -       Generic DMA kill
@@ -474,9 +474,7 @@ void ide_dma_on(ide_drive_t *drive)
        drive->hwif->dma_host_set(drive, 1);
 }
 
-EXPORT_SYMBOL(ide_dma_on);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
 /**
  *     ide_dma_setup   -       begin a DMA phase
  *     @drive: target device
@@ -593,7 +591,7 @@ static int __ide_dma_test_irq(ide_drive_t *drive)
 }
 #else
 static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
+#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
 
 int __ide_dma_bad_drive (ide_drive_t *drive)
 {
@@ -822,7 +820,27 @@ int ide_set_dma(ide_drive_t *drive)
        return 0;
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+void ide_check_dma_crc(ide_drive_t *drive)
+{
+       u8 mode;
+
+       ide_dma_off_quietly(drive);
+       drive->crc_count = 0;
+       mode = drive->current_speed;
+       /*
+        * Don't try non Ultra-DMA modes without iCRC's.  Force the
+        * device to PIO and make the user enable SWDMA/MWDMA modes.
+        */
+       if (mode > XFER_UDMA_0 && mode <= XFER_UDMA_7)
+               mode--;
+       else
+               mode = XFER_PIO_4;
+       ide_set_xfer_rate(drive, mode);
+       if (drive->current_speed >= XFER_SW_DMA_0)
+               ide_dma_on(drive);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
 void ide_dma_lost_irq (ide_drive_t *drive)
 {
        printk("%s: DMA interrupt recovery\n", drive->name);
@@ -847,10 +865,10 @@ EXPORT_SYMBOL(ide_dma_timeout);
 static void ide_release_dma_engine(ide_hwif_t *hwif)
 {
        if (hwif->dmatable_cpu) {
-               pci_free_consistent(hwif->pci_dev,
-                                   PRD_ENTRIES * PRD_BYTES,
-                                   hwif->dmatable_cpu,
-                                   hwif->dmatable_dma);
+               struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+               pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
+                                   hwif->dmatable_cpu, hwif->dmatable_dma);
                hwif->dmatable_cpu = NULL;
        }
 }
@@ -878,7 +896,9 @@ int ide_release_dma(ide_hwif_t *hwif)
 
 static int ide_allocate_dma_engine(ide_hwif_t *hwif)
 {
-       hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+       hwif->dmatable_cpu = pci_alloc_consistent(pdev,
                                                  PRD_ENTRIES * PRD_BYTES,
                                                  &hwif->dmatable_dma);
 
@@ -891,19 +911,19 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
        return 1;
 }
 
-static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
 {
        printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
 
        return 0;
 }
 
-static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
 {
        printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
-              hwif->name, base, base + ports - 1);
+              hwif->name, base, base + 7);
 
-       if (!request_region(base, ports, hwif->name)) {
+       if (!request_region(base, 8, hwif->name)) {
                printk(" -- Error, ports in use.\n");
                return 1;
        }
@@ -915,7 +935,7 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
                        if (!request_region(hwif->extra_base,
                                            hwif->cds->extra, hwif->cds->name)) {
                                printk(" -- Error, extra ports in use.\n");
-                               release_region(base, ports);
+                               release_region(base, 8);
                                return 1;
                        }
                        hwif->extra_ports = hwif->cds->extra;
@@ -925,17 +945,19 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
        return 0;
 }
 
-static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
 {
        if (hwif->mmio)
-               return ide_mapped_mmio_dma(hwif, base,ports);
+               return ide_mapped_mmio_dma(hwif, base);
 
-       return ide_iomio_dma(hwif, base, ports);
+       return ide_iomio_dma(hwif, base);
 }
 
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
+void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
 {
-       if (ide_dma_iobase(hwif, base, num_ports))
+       u8 dma_stat;
+
+       if (ide_dma_iobase(hwif, base))
                return;
 
        if (ide_allocate_dma_engine(hwif)) {
@@ -945,16 +967,16 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
 
        hwif->dma_base = base;
 
-       if (!(hwif->dma_command))
-               hwif->dma_command       = hwif->dma_base;
-       if (!(hwif->dma_vendor1))
-               hwif->dma_vendor1       = (hwif->dma_base + 1);
-       if (!(hwif->dma_status))
-               hwif->dma_status        = (hwif->dma_base + 2);
-       if (!(hwif->dma_vendor3))
-               hwif->dma_vendor3       = (hwif->dma_base + 3);
-       if (!(hwif->dma_prdtable))
-               hwif->dma_prdtable      = (hwif->dma_base + 4);
+       if (!hwif->dma_command)
+               hwif->dma_command       = hwif->dma_base + 0;
+       if (!hwif->dma_vendor1)
+               hwif->dma_vendor1       = hwif->dma_base + 1;
+       if (!hwif->dma_status)
+               hwif->dma_status        = hwif->dma_base + 2;
+       if (!hwif->dma_vendor3)
+               hwif->dma_vendor3       = hwif->dma_base + 3;
+       if (!hwif->dma_prdtable)
+               hwif->dma_prdtable      = hwif->dma_base + 4;
 
        if (!hwif->dma_host_set)
                hwif->dma_host_set = &ide_dma_host_set;
@@ -973,14 +995,11 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
        if (!hwif->dma_lost_irq)
                hwif->dma_lost_irq = &ide_dma_lost_irq;
 
-       if (hwif->chipset != ide_trm290) {
-               u8 dma_stat = hwif->INB(hwif->dma_status);
-               printk(", BIOS settings: %s:%s, %s:%s",
-                      hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
-                      hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
-       }
-       printk("\n");
+       dma_stat = hwif->INB(hwif->dma_status);
+       printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
+              hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
+              hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
 }
 
 EXPORT_SYMBOL_GPL(ide_setup_dma);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
+#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */