Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[pandora-kernel.git] / drivers / ide / pci / sgiioc4.c
index 85ffaaa..0546264 100644 (file)
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
+#include <linux/scatterlist.h>
 #include <linux/ioc4.h>
 #include <asm/io.h>
 
@@ -158,6 +157,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
                }
 
                if (intr_reg & 0x02) {
+                       struct pci_dev *dev = to_pci_dev(hwif->dev);
                        /* Error when transferring DMA data on PCI bus */
                        u32 pci_err_addr_low, pci_err_addr_high,
                            pci_stat_cmd_reg;
@@ -166,7 +166,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
                                readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
                        pci_err_addr_high =
                                readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
-                       pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
+                       pci_read_config_dword(dev, PCI_COMMAND,
                                              &pci_stat_cmd_reg);
                        printk(KERN_ERR
                               "%s(%s) : PCI Bus Error when doing DMA:"
@@ -177,8 +177,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
                               __FUNCTION__, drive->name,
                               pci_err_addr_high, pci_err_addr_low);
                        /* Clear the PCI Error indicator */
-                       pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
-                                              0x00000146);
+                       pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
                }
 
                /* Clear the Interrupt, Error bits on the IOC4 */
@@ -276,39 +275,10 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
        return dma_stat;
 }
 
-static int
-sgiioc4_ide_dma_on(ide_drive_t * drive)
-{
-       drive->using_dma = 1;
-
-       return 0;
-}
-
-static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
-{
-       drive->using_dma = 0;
-
-       drive->hwif->dma_host_off(drive);
-}
-
 static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 }
 
-static int sgiioc4_ide_dma_check(ide_drive_t *drive)
-{
-       if (ide_tune_dma(drive))
-               return 0;
-
-       /*
-        * ->set_pio_mode is not implemented currently
-        * so this is just for the completness
-        */
-       ide_set_max_pio(drive);
-
-       return -1;
-}
-
 /* returns 1 if dma irq issued, 0 otherwise */
 static int
 sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
@@ -316,13 +286,10 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
        return sgiioc4_checkirq(HWIF(drive));
 }
 
-static void sgiioc4_dma_host_on(ide_drive_t * drive)
-{
-}
-
-static void sgiioc4_dma_host_off(ide_drive_t * drive)
+static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
 {
-       sgiioc4_clearirq(drive);
+       if (!on)
+               sgiioc4_clearirq(drive);
 }
 
 static void
@@ -365,6 +332,7 @@ sgiioc4_INB(unsigned long port)
 static int __devinit
 ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
 {
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
        void __iomem *virt_dma_base;
        int num_ports = sizeof (ioc4_dma_regs_t);
        void *pad;
@@ -390,7 +358,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
        }
        hwif->dma_base = (unsigned long) virt_dma_base;
 
-       hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+       hwif->dmatable_cpu = pci_alloc_consistent(dev,
                                          IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
                                          &hwif->dmatable_dma);
 
@@ -399,7 +367,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
 
        hwif->sg_max_nents = IOC4_PRD_ENTRIES;
 
-       pad = pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE,
+       pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
                                   (dma_addr_t *) &(hwif->dma_status));
 
        if (pad) {
@@ -407,8 +375,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
                return 0;
        }
 
-       pci_free_consistent(hwif->pci_dev,
-                           IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+       pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
                            hwif->dmatable_cpu, hwif->dmatable_dma);
        printk(KERN_INFO
               "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
@@ -537,7 +504,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
                        }
                }
 
-               sg++;
+               sg = sg_next(sg);
                i--;
        }
 
@@ -548,8 +515,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
        }
 
 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 */
 }
@@ -587,7 +553,6 @@ static void __devinit
 ide_init_sgiioc4(ide_hwif_t * hwif)
 {
        hwif->mmio = 1;
-       hwif->pio_mask = 0x00;
        hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
        hwif->set_dma_mode = &sgiioc4_set_dma_mode;
        hwif->selectproc = NULL;/* Use the default routine to select drive */
@@ -595,7 +560,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
        hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
        hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
                                                clear interrupts */
-       hwif->intrproc = NULL;  /* Enable or Disable interrupt from drive */
        hwif->maskproc = &sgiioc4_maskproc;     /* Mask on/off NIEN register */
        hwif->quirkproc = NULL;
        hwif->busproc = NULL;
@@ -605,22 +569,22 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
        if (hwif->dma_base == 0)
                return;
 
-       hwif->atapi_dma = 1;
-       hwif->mwdma_mask = 0x04;
-
+       hwif->dma_host_set = &sgiioc4_dma_host_set;
        hwif->dma_setup = &sgiioc4_ide_dma_setup;
        hwif->dma_start = &sgiioc4_ide_dma_start;
        hwif->ide_dma_end = &sgiioc4_ide_dma_end;
-       hwif->ide_dma_check = &sgiioc4_ide_dma_check;
-       hwif->ide_dma_on = &sgiioc4_ide_dma_on;
-       hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
        hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
-       hwif->dma_host_on = &sgiioc4_dma_host_on;
-       hwif->dma_host_off = &sgiioc4_dma_host_off;
        hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
        hwif->dma_timeout = &ide_dma_timeout;
 }
 
+static const struct ide_port_info sgiioc4_port_info __devinitdata = {
+       .chipset                = ide_pci,
+       .host_flags             = IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+                                 IDE_HFLAG_NO_AUTOTUNE,
+       .mwdma_mask             = ATA_MWDMA2_ONLY,
+};
+
 static int __devinit
 sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
 {
@@ -629,6 +593,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
        void __iomem *virt_base;
        ide_hwif_t *hwif;
        int h;
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+       hw_regs_t hw;
+       struct ide_port_info d = sgiioc4_port_info;
 
        /*
         * Find an empty HWIF; if none available, return -ENOMEM.
@@ -668,19 +635,15 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
                return -ENOMEM;
        }
 
-       if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
-               /* Initialize the IO registers */
-               sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport);
-               memcpy(hwif->io_ports, hwif->hw.io_ports,
-                      sizeof (hwif->io_ports));
-               hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
-       }
+       /* Initialize the IO registers */
+       memset(&hw, 0, sizeof(hw));
+       sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
+       hw.irq = dev->irq;
+       hw.chipset = ide_pci;
+       hw.dev = &dev->dev;
+       ide_init_port_hw(hwif, &hw);
 
-       hwif->irq = dev->irq;
-       hwif->chipset = ide_pci;
-       hwif->pci_dev = dev;
-       hwif->channel = 0;      /* Single Channel chip */
-       hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
+       hwif->dev = &dev->dev;
 
        /* The IOC4 uses MMIO rather than Port IO. */
        default_hwif_mmiops(hwif);
@@ -688,22 +651,18 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
        /* Initializing chipset IRQ Registers */
        writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
-       hwif->autodma = 0;
-
-       if (dma_base && ide_dma_sgiioc4(hwif, dma_base) == 0) {
-               hwif->autodma = 1;
-               hwif->drives[1].autodma = hwif->drives[0].autodma = 1;
-       } else
+       if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) {
                printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
                                 hwif->name, DRV_NAME);
+               d.mwdma_mask = 0;
+       }
 
        ide_init_sgiioc4(hwif);
 
-       if (probe_hwif_init(hwif))
-               return -EIO;
+       idx[0] = hwif->index;
 
-       /* Create /proc/ide entries */
-       ide_proc_register_port(hwif);
+       if (ide_device_add(idx, &d))
+               return -EIO;
 
        return 0;
 }
@@ -711,14 +670,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
 static unsigned int __devinit
 pci_init_sgiioc4(struct pci_dev *dev)
 {
-       unsigned int class_rev;
        int ret;
 
-       pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-       class_rev &= 0xff;
        printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
-                        DRV_NAME, pci_name(dev), class_rev);
-       if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
+                        DRV_NAME, pci_name(dev), dev->revision);
+
+       if (dev->revision < IOC4_SUPPORTED_FIRMWARE_REV) {
                printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
                                "firmware is obsolete - please upgrade to "
                                "revision46 or higher\n",