]> err.no Git - linux-2.6/blobdiff - drivers/ide/pci/pdc202xx_new.c
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / drivers / ide / pci / pdc202xx_new.c
index 7b0e479c355c116ea732402339c444535d54eb54..070df8ab3b218946ac69b2804bb9ebafce7a48de 100644 (file)
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
 #include <linux/hdreg.h>
-#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ide.h>
 
 #include <asm/io.h>
-#include <asm/irq.h>
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/prom.h>
@@ -40,7 +34,7 @@
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args)
+#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args)
 #else
 #define DBG(fmt, args...)
 #endif
@@ -89,8 +83,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
 {
        u8 value;
 
-       outb(index, hwif->dma_vendor1);
-       value = inb(hwif->dma_vendor3);
+       outb(index, hwif->dma_base + 1);
+       value = inb(hwif->dma_base + 3);
 
        DBG("index[%02X] value[%02X]\n", index, value);
        return value;
@@ -103,8 +97,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
  */
 static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
 {
-       outb(index, hwif->dma_vendor1);
-       outb(value, hwif->dma_vendor3);
+       outb(index, hwif->dma_base + 1);
+       outb(value, hwif->dma_base + 3);
        DBG("index[%02X] value[%02X]\n", index, value);
 }
 
@@ -146,66 +140,35 @@ static struct udma_timing {
        { 0x1a, 0x01, 0xcb },   /* UDMA mode 6 */
 };
 
-static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed)
+static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 adj                  = (drive->dn & 1) ? 0x08 : 0x00;
-       int                     err;
-
-       speed = ide_rate_filter(drive, speed);
 
        /*
-        * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will
+        * IDE core issues SETFEATURES_XFER to the drive first (thanks to
+        * IDE_HFLAG_POST_SET_MODE in ->host_flags).  PDC202xx hardware will
         * automatically set the timing registers based on 100 MHz PLL output.
-        */
-       err = ide_config_drive_speed(drive, speed);
-
-       /*
+        *
         * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
         * chips, we must override the default register settings...
         */
-       if (max_dma_rate(hwif->pci_dev) == 4) {
+       if (max_dma_rate(dev) == 4) {
                u8 mode = speed & 0x07;
 
-               switch (speed) {
-                       case XFER_UDMA_6:
-                       case XFER_UDMA_5:
-                       case XFER_UDMA_4:
-                       case XFER_UDMA_3:
-                       case XFER_UDMA_2:
-                       case XFER_UDMA_1:
-                       case XFER_UDMA_0:
-                               set_indexed_reg(hwif, 0x10 + adj,
-                                               udma_timings[mode].reg10);
-                               set_indexed_reg(hwif, 0x11 + adj,
-                                               udma_timings[mode].reg11);
-                               set_indexed_reg(hwif, 0x12 + adj,
-                                               udma_timings[mode].reg12);
-                               break;
-
-                       case XFER_MW_DMA_2:
-                       case XFER_MW_DMA_1:
-                       case XFER_MW_DMA_0:
-                               set_indexed_reg(hwif, 0x0e + adj,
-                                               mwdma_timings[mode].reg0e);
-                               set_indexed_reg(hwif, 0x0f + adj,
-                                               mwdma_timings[mode].reg0f);
-                               break;
-                       case XFER_PIO_4:
-                       case XFER_PIO_3:
-                       case XFER_PIO_2:
-                       case XFER_PIO_1:
-                       case XFER_PIO_0:
-                               set_indexed_reg(hwif, 0x0c + adj,
-                                               pio_timings[mode].reg0c);
-                               set_indexed_reg(hwif, 0x0d + adj,
-                                               pio_timings[mode].reg0d);
-                               set_indexed_reg(hwif, 0x13 + adj,
-                                               pio_timings[mode].reg13);
-                               break;
-                       default:
-                               printk(KERN_ERR "pdc202xx_new: "
-                                      "Unknown speed %d ignored\n", speed);
+               if (speed >= XFER_UDMA_0) {
+                       set_indexed_reg(hwif, 0x10 + adj,
+                                       udma_timings[mode].reg10);
+                       set_indexed_reg(hwif, 0x11 + adj,
+                                       udma_timings[mode].reg11);
+                       set_indexed_reg(hwif, 0x12 + adj,
+                                       udma_timings[mode].reg12);
+               } else {
+                       set_indexed_reg(hwif, 0x0e + adj,
+                                       mwdma_timings[mode].reg0e);
+                       set_indexed_reg(hwif, 0x0f + adj,
+                                       mwdma_timings[mode].reg0f);
                }
        } else if (speed == XFER_UDMA_2) {
                /* Set tHOLD bit to 0 if using UDMA mode 2 */
@@ -213,17 +176,22 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed)
 
                set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
        }
-
-       return err;
 }
 
-static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
+static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       pio = ide_get_best_pio_mode(drive, pio, 4);
-       (void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio);
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
+
+       if (max_dma_rate(dev) == 4) {
+               set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
+               set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
+               set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
+       }
 }
 
-static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
+static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif)
 {
        if (get_indexed_reg(hwif, 0x0b) & 0x04)
                return ATA_CBL_PATA40;
@@ -231,27 +199,17 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
                return ATA_CBL_PATA80;
 }
 
-static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
-{
-       drive->init_speed = 0;
-
-       if (ide_tune_dma(drive))
-               return 0;
-
-       if (ide_use_fast_pio(drive))
-               pdcnew_tune_drive(drive, 255);
-
-       return -1;
-}
-
-static int pdcnew_quirkproc(ide_drive_t *drive)
+static void pdcnew_quirkproc(ide_drive_t *drive)
 {
        const char **list, *model = drive->id->model;
 
        for (list = pdc_quirk_drives; *list != NULL; list++)
-               if (strstr(model, *list) != NULL)
-                       return 2;
-       return 0;
+               if (strstr(model, *list) != NULL) {
+                       drive->quirk_list = 2;
+                       return;
+               }
+
+       drive->quirk_list = 0;
 }
 
 static void pdcnew_reset(ide_drive_t *drive)
@@ -353,16 +311,12 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base)
 static void __devinit apple_kiwi_init(struct pci_dev *pdev)
 {
        struct device_node *np = pci_device_to_OF_node(pdev);
-       unsigned int class_rev = 0;
        u8 conf;
 
        if (np == NULL || !of_device_is_compatible(np, "kiwi-root"))
                return;
 
-       pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
-       class_rev &= 0xff;
-
-       if (class_rev >= 0x03) {
+       if (pdev->revision >= 0x03) {
                /* Setup chip magic config stuff (from darwin) */
                pci_read_config_byte (pdev, 0x40, &conf);
                pci_write_config_byte(pdev, 0x40, (conf | 0x01));
@@ -488,150 +442,58 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
        return dev->irq;
 }
 
-static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
+static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
 {
-       hwif->autodma = 0;
-
-       hwif->tuneproc  = &pdcnew_tune_drive;
-       hwif->quirkproc = &pdcnew_quirkproc;
-       hwif->speedproc = &pdcnew_tune_chipset;
-       hwif->resetproc = &pdcnew_reset;
-
-       hwif->err_stops_fifo = 1;
-
-       hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
-
-       if (hwif->dma_base == 0)
-               return;
-
-       hwif->atapi_dma  = 1;
+       struct pci_dev *dev2;
 
-       hwif->ultra_mask = hwif->cds->udma_mask;
-       hwif->mwdma_mask = 0x07;
+       dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1,
+                                               PCI_FUNC(dev->devfn)));
 
-       hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
+       if (dev2 &&
+           dev2->vendor == dev->vendor &&
+           dev2->device == dev->device) {
 
-       if (hwif->cbl != ATA_CBL_PATA40_SHORT)
-               hwif->cbl = pdcnew_cable_detect(hwif);
+               if (dev2->irq != dev->irq) {
+                       dev2->irq = dev->irq;
+                       printk(KERN_INFO "PDC20270: PCI config space "
+                                        "interrupt fixed\n");
+               }
 
-       if (!noautodma)
-               hwif->autodma = 1;
-       hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
-}
+               return dev2;
+       }
 
-static int __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d)
-{
-       return ide_setup_pci_device(dev, d);
+       return NULL;
 }
 
-static int __devinit init_setup_pdc20270(struct pci_dev *dev,
-                                        ide_pci_device_t *d)
-{
-       struct pci_dev *findev = NULL;
-       int ret;
-
-       if ((dev->bus->self &&
-            dev->bus->self->vendor == PCI_VENDOR_ID_DEC) &&
-           (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) {
-               if (PCI_SLOT(dev->devfn) & 2)
-                       return -ENODEV;
-
-               while ((findev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
-                       if ((findev->vendor == dev->vendor) &&
-                           (findev->device == dev->device) &&
-                           (PCI_SLOT(findev->devfn) & 2)) {
-                               if (findev->irq != dev->irq) {
-                                       findev->irq = dev->irq;
-                               }
-                               ret = ide_setup_pci_devices(dev, findev, d);
-                               if (ret < 0)
-                                       pci_dev_put(findev);
-                               return ret;
-                       }
-               }
-       }
-       return ide_setup_pci_device(dev, d);
-}
+static const struct ide_port_ops pdcnew_port_ops = {
+       .set_pio_mode           = pdcnew_set_pio_mode,
+       .set_dma_mode           = pdcnew_set_dma_mode,
+       .quirkproc              = pdcnew_quirkproc,
+       .resetproc              = pdcnew_reset,
+       .cable_detect           = pdcnew_cable_detect,
+};
 
-static int __devinit init_setup_pdc20276(struct pci_dev *dev,
-                                        ide_pci_device_t *d)
-{
-       if ((dev->bus->self) &&
-           (dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) &&
-           ((dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) ||
-            (dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) {
-               printk(KERN_INFO "ide: Skipping Promise PDC20276 "
-                       "attached to I2O RAID controller.\n");
-               return -ENODEV;
+#define DECLARE_PDCNEW_DEV(name_str, udma) \
+       { \
+               .name           = name_str, \
+               .init_chipset   = init_chipset_pdcnew, \
+               .port_ops       = &pdcnew_port_ops, \
+               .host_flags     = IDE_HFLAG_POST_SET_MODE | \
+                                 IDE_HFLAG_ERROR_STOPS_FIFO | \
+                                 IDE_HFLAG_OFF_BOARD, \
+               .pio_mask       = ATA_PIO4, \
+               .mwdma_mask     = ATA_MWDMA2, \
+               .udma_mask      = udma, \
        }
-       return ide_setup_pci_device(dev, d);
-}
 
-static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
-       {       /* 0 */
-               .name           = "PDC20268",
-               .init_setup     = init_setup_pdcnew,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x3f, /* udma0-5 */
-       },{     /* 1 */
-               .name           = "PDC20269",
-               .init_setup     = init_setup_pdcnew,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x7f, /* udma0-6*/
-       },{     /* 2 */
-               .name           = "PDC20270",
-               .init_setup     = init_setup_pdc20270,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x3f, /* udma0-5 */
-       },{     /* 3 */
-               .name           = "PDC20271",
-               .init_setup     = init_setup_pdcnew,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x7f, /* udma0-6*/
-       },{     /* 4 */
-               .name           = "PDC20275",
-               .init_setup     = init_setup_pdcnew,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x7f, /* udma0-6*/
-       },{     /* 5 */
-               .name           = "PDC20276",
-               .init_setup     = init_setup_pdc20276,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x7f, /* udma0-6*/
-       },{     /* 6 */
-               .name           = "PDC20277",
-               .init_setup     = init_setup_pdcnew,
-               .init_chipset   = init_chipset_pdcnew,
-               .init_hwif      = init_hwif_pdc202new,
-               .autodma        = AUTODMA,
-               .bootable       = OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = 0x7f, /* udma0-6*/
-       }
+static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
+       /* 0 */ DECLARE_PDCNEW_DEV("PDC20268", ATA_UDMA5),
+       /* 1 */ DECLARE_PDCNEW_DEV("PDC20269", ATA_UDMA6),
+       /* 2 */ DECLARE_PDCNEW_DEV("PDC20270", ATA_UDMA5),
+       /* 3 */ DECLARE_PDCNEW_DEV("PDC20271", ATA_UDMA6),
+       /* 4 */ DECLARE_PDCNEW_DEV("PDC20275", ATA_UDMA6),
+       /* 5 */ DECLARE_PDCNEW_DEV("PDC20276", ATA_UDMA6),
+       /* 6 */ DECLARE_PDCNEW_DEV("PDC20277", ATA_UDMA6),
 };
 
 /**
@@ -645,19 +507,50 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
  
 static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       ide_pci_device_t *d = &pdcnew_chipsets[id->driver_data];
+       const struct ide_port_info *d;
+       struct pci_dev *bridge = dev->bus->self;
+       u8 idx = id->driver_data;
 
-       return d->init_setup(dev, d);
+       d = &pdcnew_chipsets[idx];
+
+       if (idx == 2 && bridge &&
+           bridge->vendor == PCI_VENDOR_ID_DEC &&
+           bridge->device == PCI_DEVICE_ID_DEC_21150) {
+               struct pci_dev *dev2;
+
+               if (PCI_SLOT(dev->devfn) & 2)
+                       return -ENODEV;
+
+               dev2 = pdc20270_get_dev2(dev);
+
+               if (dev2) {
+                       int ret = ide_setup_pci_devices(dev, dev2, d);
+                       if (ret < 0)
+                               pci_dev_put(dev2);
+                       return ret;
+               }
+       }
+
+       if (idx == 5 && bridge &&
+           bridge->vendor == PCI_VENDOR_ID_INTEL &&
+           (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
+            bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
+               printk(KERN_INFO "PDC20276: attached to I2O RAID controller, "
+                                "skipping\n");
+               return -ENODEV;
+       }
+
+       return ide_setup_pci_device(dev, d);
 }
 
-static struct pci_device_id pdc202new_pci_tbl[] = {
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
-       { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+static const struct pci_device_id pdc202new_pci_tbl[] = {
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 2 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 3 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 4 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 5 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 6 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);