ide: remove useless subdirs from drivers/ide/
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Tue, 21 Oct 2008 18:57:23 +0000 (20:57 +0200)
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Tue, 21 Oct 2008 18:57:23 +0000 (20:57 +0200)
Suggested-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>

117 files changed:
drivers/ide/Makefile
drivers/ide/aec62xx.c [new file with mode: 0644]
drivers/ide/ali14xx.c [new file with mode: 0644]
drivers/ide/alim15x3.c [new file with mode: 0644]
drivers/ide/amd74xx.c [new file with mode: 0644]
drivers/ide/arm/Makefile [deleted file]
drivers/ide/arm/icside.c [deleted file]
drivers/ide/arm/ide_arm.c [deleted file]
drivers/ide/arm/palm_bk3710.c [deleted file]
drivers/ide/arm/rapide.c [deleted file]
drivers/ide/atiixp.c [new file with mode: 0644]
drivers/ide/au1xxx-ide.c [new file with mode: 0644]
drivers/ide/buddha.c [new file with mode: 0644]
drivers/ide/cmd640.c [new file with mode: 0644]
drivers/ide/cmd64x.c [new file with mode: 0644]
drivers/ide/cs5520.c [new file with mode: 0644]
drivers/ide/cs5530.c [new file with mode: 0644]
drivers/ide/cs5535.c [new file with mode: 0644]
drivers/ide/cy82c693.c [new file with mode: 0644]
drivers/ide/delkin_cb.c [new file with mode: 0644]
drivers/ide/dtc2278.c [new file with mode: 0644]
drivers/ide/falconide.c [new file with mode: 0644]
drivers/ide/gayle.c [new file with mode: 0644]
drivers/ide/generic.c [new file with mode: 0644]
drivers/ide/h8300/Makefile [deleted file]
drivers/ide/h8300/ide-h8300.c [deleted file]
drivers/ide/hpt366.c [new file with mode: 0644]
drivers/ide/ht6560b.c [new file with mode: 0644]
drivers/ide/icside.c [new file with mode: 0644]
drivers/ide/ide-4drives.c [new file with mode: 0644]
drivers/ide/ide-cs.c [new file with mode: 0644]
drivers/ide/ide-h8300.c [new file with mode: 0644]
drivers/ide/ide_arm.c [new file with mode: 0644]
drivers/ide/ide_platform.c [new file with mode: 0644]
drivers/ide/it8213.c [new file with mode: 0644]
drivers/ide/it821x.c [new file with mode: 0644]
drivers/ide/jmicron.c [new file with mode: 0644]
drivers/ide/legacy/Makefile [deleted file]
drivers/ide/legacy/ali14xx.c [deleted file]
drivers/ide/legacy/buddha.c [deleted file]
drivers/ide/legacy/dtc2278.c [deleted file]
drivers/ide/legacy/falconide.c [deleted file]
drivers/ide/legacy/gayle.c [deleted file]
drivers/ide/legacy/ht6560b.c [deleted file]
drivers/ide/legacy/ide-4drives.c [deleted file]
drivers/ide/legacy/ide-cs.c [deleted file]
drivers/ide/legacy/ide_platform.c [deleted file]
drivers/ide/legacy/macide.c [deleted file]
drivers/ide/legacy/q40ide.c [deleted file]
drivers/ide/legacy/qd65xx.c [deleted file]
drivers/ide/legacy/qd65xx.h [deleted file]
drivers/ide/legacy/umc8672.c [deleted file]
drivers/ide/macide.c [new file with mode: 0644]
drivers/ide/mips/Makefile [deleted file]
drivers/ide/mips/au1xxx-ide.c [deleted file]
drivers/ide/ns87415.c [new file with mode: 0644]
drivers/ide/opti621.c [new file with mode: 0644]
drivers/ide/palm_bk3710.c [new file with mode: 0644]
drivers/ide/pci/Makefile [deleted file]
drivers/ide/pci/aec62xx.c [deleted file]
drivers/ide/pci/alim15x3.c [deleted file]
drivers/ide/pci/amd74xx.c [deleted file]
drivers/ide/pci/atiixp.c [deleted file]
drivers/ide/pci/cmd640.c [deleted file]
drivers/ide/pci/cmd64x.c [deleted file]
drivers/ide/pci/cs5520.c [deleted file]
drivers/ide/pci/cs5530.c [deleted file]
drivers/ide/pci/cs5535.c [deleted file]
drivers/ide/pci/cy82c693.c [deleted file]
drivers/ide/pci/delkin_cb.c [deleted file]
drivers/ide/pci/generic.c [deleted file]
drivers/ide/pci/hpt366.c [deleted file]
drivers/ide/pci/it8213.c [deleted file]
drivers/ide/pci/it821x.c [deleted file]
drivers/ide/pci/jmicron.c [deleted file]
drivers/ide/pci/ns87415.c [deleted file]
drivers/ide/pci/opti621.c [deleted file]
drivers/ide/pci/pdc202xx_new.c [deleted file]
drivers/ide/pci/pdc202xx_old.c [deleted file]
drivers/ide/pci/piix.c [deleted file]
drivers/ide/pci/rz1000.c [deleted file]
drivers/ide/pci/sc1200.c [deleted file]
drivers/ide/pci/scc_pata.c [deleted file]
drivers/ide/pci/serverworks.c [deleted file]
drivers/ide/pci/sgiioc4.c [deleted file]
drivers/ide/pci/siimage.c [deleted file]
drivers/ide/pci/sis5513.c [deleted file]
drivers/ide/pci/sl82c105.c [deleted file]
drivers/ide/pci/slc90e66.c [deleted file]
drivers/ide/pci/tc86c001.c [deleted file]
drivers/ide/pci/triflex.c [deleted file]
drivers/ide/pci/trm290.c [deleted file]
drivers/ide/pci/via82cxxx.c [deleted file]
drivers/ide/pdc202xx_new.c [new file with mode: 0644]
drivers/ide/pdc202xx_old.c [new file with mode: 0644]
drivers/ide/piix.c [new file with mode: 0644]
drivers/ide/pmac.c [new file with mode: 0644]
drivers/ide/ppc/Makefile [deleted file]
drivers/ide/ppc/pmac.c [deleted file]
drivers/ide/q40ide.c [new file with mode: 0644]
drivers/ide/qd65xx.c [new file with mode: 0644]
drivers/ide/qd65xx.h [new file with mode: 0644]
drivers/ide/rapide.c [new file with mode: 0644]
drivers/ide/rz1000.c [new file with mode: 0644]
drivers/ide/sc1200.c [new file with mode: 0644]
drivers/ide/scc_pata.c [new file with mode: 0644]
drivers/ide/serverworks.c [new file with mode: 0644]
drivers/ide/sgiioc4.c [new file with mode: 0644]
drivers/ide/siimage.c [new file with mode: 0644]
drivers/ide/sis5513.c [new file with mode: 0644]
drivers/ide/sl82c105.c [new file with mode: 0644]
drivers/ide/slc90e66.c [new file with mode: 0644]
drivers/ide/tc86c001.c [new file with mode: 0644]
drivers/ide/triflex.c [new file with mode: 0644]
drivers/ide/trm290.c [new file with mode: 0644]
drivers/ide/umc8672.c [new file with mode: 0644]
drivers/ide/via82cxxx.c [new file with mode: 0644]

index 093d324..9cf92ac 100644 (file)
@@ -18,22 +18,66 @@ ide-core-$(CONFIG_BLK_DEV_IDEACPI)  += ide-acpi.o
 
 obj-$(CONFIG_IDE)                      += ide-core.o
 
-ifeq ($(CONFIG_IDE_ARM), y)
-       ide-arm-core-y += arm/ide_arm.o
-       obj-y += ide-arm-core.o
-endif
-
-obj-$(CONFIG_IDE)                      += legacy/ pci/
+obj-$(CONFIG_IDE_ARM)                  += ide_arm.o
+
+obj-$(CONFIG_BLK_DEV_ALI14XX)          += ali14xx.o
+obj-$(CONFIG_BLK_DEV_UMC8672)          += umc8672.o
+obj-$(CONFIG_BLK_DEV_DTC2278)          += dtc2278.o
+obj-$(CONFIG_BLK_DEV_HT6560B)          += ht6560b.o
+obj-$(CONFIG_BLK_DEV_QD65XX)           += qd65xx.o
+obj-$(CONFIG_BLK_DEV_4DRIVES)          += ide-4drives.o
+
+obj-$(CONFIG_BLK_DEV_GAYLE)            += gayle.o
+obj-$(CONFIG_BLK_DEV_FALCON_IDE)       += falconide.o
+obj-$(CONFIG_BLK_DEV_MAC_IDE)          += macide.o
+obj-$(CONFIG_BLK_DEV_Q40IDE)           += q40ide.o
+obj-$(CONFIG_BLK_DEV_BUDDHA)           += buddha.o
+
+obj-$(CONFIG_BLK_DEV_AEC62XX)          += aec62xx.o
+obj-$(CONFIG_BLK_DEV_ALI15X3)          += alim15x3.o
+obj-$(CONFIG_BLK_DEV_AMD74XX)          += amd74xx.o
+obj-$(CONFIG_BLK_DEV_ATIIXP)           += atiixp.o
+obj-$(CONFIG_BLK_DEV_CELLEB)           += scc_pata.o
+obj-$(CONFIG_BLK_DEV_CMD64X)           += cmd64x.o
+obj-$(CONFIG_BLK_DEV_CS5520)           += cs5520.o
+obj-$(CONFIG_BLK_DEV_CS5530)           += cs5530.o
+obj-$(CONFIG_BLK_DEV_CS5535)           += cs5535.o
+obj-$(CONFIG_BLK_DEV_SC1200)           += sc1200.o
+obj-$(CONFIG_BLK_DEV_CY82C693)         += cy82c693.o
+obj-$(CONFIG_BLK_DEV_DELKIN)           += delkin_cb.o
+obj-$(CONFIG_BLK_DEV_HPT366)           += hpt366.o
+obj-$(CONFIG_BLK_DEV_IT8213)           += it8213.o
+obj-$(CONFIG_BLK_DEV_IT821X)           += it821x.o
+obj-$(CONFIG_BLK_DEV_JMICRON)          += jmicron.o
+obj-$(CONFIG_BLK_DEV_NS87415)          += ns87415.o
+obj-$(CONFIG_BLK_DEV_OPTI621)          += opti621.o
+obj-$(CONFIG_BLK_DEV_PDC202XX_OLD)     += pdc202xx_old.o
+obj-$(CONFIG_BLK_DEV_PDC202XX_NEW)     += pdc202xx_new.o
+obj-$(CONFIG_BLK_DEV_PIIX)             += piix.o
+obj-$(CONFIG_BLK_DEV_RZ1000)           += rz1000.o
+obj-$(CONFIG_BLK_DEV_SVWKS)            += serverworks.o
+obj-$(CONFIG_BLK_DEV_SGIIOC4)          += sgiioc4.o
+obj-$(CONFIG_BLK_DEV_SIIMAGE)          += siimage.o
+obj-$(CONFIG_BLK_DEV_SIS5513)          += sis5513.o
+obj-$(CONFIG_BLK_DEV_SL82C105)         += sl82c105.o
+obj-$(CONFIG_BLK_DEV_SLC90E66)         += slc90e66.o
+obj-$(CONFIG_BLK_DEV_TC86C001)         += tc86c001.o
+obj-$(CONFIG_BLK_DEV_TRIFLEX)          += triflex.o
+obj-$(CONFIG_BLK_DEV_TRM290)           += trm290.o
+obj-$(CONFIG_BLK_DEV_VIA82CXXX)                += via82cxxx.o
+
+# Must appear at the end of the block
+obj-$(CONFIG_BLK_DEV_GENERIC)          += ide-pci-generic.o
+ide-pci-generic-y                      += generic.o
 
 obj-$(CONFIG_IDEPCI_PCIBUS_ORDER)      += ide-scan-pci.o
 
-ifeq ($(CONFIG_BLK_DEV_CMD640), y)
-       cmd640-core-y += pci/cmd640.o
-       obj-y += cmd640-core.o
-endif
+obj-$(CONFIG_BLK_DEV_CMD640)           += cmd640.o
+
+obj-$(CONFIG_BLK_DEV_IDE_PMAC)         += pmac.o
+
+obj-$(CONFIG_IDE_H8300)                        += ide-h8300.o
 
-obj-$(CONFIG_IDE)                      += ppc/
-obj-$(CONFIG_IDE_H8300)                        += h8300/
 obj-$(CONFIG_IDE_GENERIC)              += ide-generic.o
 obj-$(CONFIG_BLK_DEV_IDEPNP)           += ide-pnp.o
 
@@ -58,14 +102,12 @@ obj-$(CONFIG_IDE_GD)                       += ide-gd_mod.o
 obj-$(CONFIG_BLK_DEV_IDECD)            += ide-cd_mod.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)          += ide-tape.o
 
-ifeq ($(CONFIG_BLK_DEV_IDECS), y)
-       ide-cs-core-y += legacy/ide-cs.o
-       obj-y += ide-cs-core.o
-endif
+obj-$(CONFIG_BLK_DEV_IDECS)            += ide-cs.o
 
-ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
-       ide-platform-core-y += legacy/ide_platform.o
-       obj-y += ide-platform-core.o
-endif
+obj-$(CONFIG_BLK_DEV_PLATFORM)         += ide_platform.o
+
+obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)       += icside.o
+obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)       += rapide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)  += palm_bk3710.o
 
-obj-$(CONFIG_IDE)                      += arm/ mips/
+obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)       += au1xxx-ide.o
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
new file mode 100644 (file)
index 0000000..4142c69
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "aec62xx"
+
+struct chipset_bus_clock_list_entry {
+       u8 xfer_speed;
+       u8 chipset_settings;
+       u8 ultra_settings;
+};
+
+static const struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
+       {       XFER_UDMA_6,    0x31,   0x07    },
+       {       XFER_UDMA_5,    0x31,   0x06    },
+       {       XFER_UDMA_4,    0x31,   0x05    },
+       {       XFER_UDMA_3,    0x31,   0x04    },
+       {       XFER_UDMA_2,    0x31,   0x03    },
+       {       XFER_UDMA_1,    0x31,   0x02    },
+       {       XFER_UDMA_0,    0x31,   0x01    },
+
+       {       XFER_MW_DMA_2,  0x31,   0x00    },
+       {       XFER_MW_DMA_1,  0x31,   0x00    },
+       {       XFER_MW_DMA_0,  0x0a,   0x00    },
+       {       XFER_PIO_4,     0x31,   0x00    },
+       {       XFER_PIO_3,     0x33,   0x00    },
+       {       XFER_PIO_2,     0x08,   0x00    },
+       {       XFER_PIO_1,     0x0a,   0x00    },
+       {       XFER_PIO_0,     0x00,   0x00    },
+       {       0,              0x00,   0x00    }
+};
+
+static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
+       {       XFER_UDMA_6,    0x41,   0x06    },
+       {       XFER_UDMA_5,    0x41,   0x05    },
+       {       XFER_UDMA_4,    0x41,   0x04    },
+       {       XFER_UDMA_3,    0x41,   0x03    },
+       {       XFER_UDMA_2,    0x41,   0x02    },
+       {       XFER_UDMA_1,    0x41,   0x01    },
+       {       XFER_UDMA_0,    0x41,   0x01    },
+
+       {       XFER_MW_DMA_2,  0x41,   0x00    },
+       {       XFER_MW_DMA_1,  0x42,   0x00    },
+       {       XFER_MW_DMA_0,  0x7a,   0x00    },
+       {       XFER_PIO_4,     0x41,   0x00    },
+       {       XFER_PIO_3,     0x43,   0x00    },
+       {       XFER_PIO_2,     0x78,   0x00    },
+       {       XFER_PIO_1,     0x7a,   0x00    },
+       {       XFER_PIO_0,     0x70,   0x00    },
+       {       0,              0x00,   0x00    }
+};
+
+/*
+ * TO DO: active tuning and correction of cards without a bios.
+ */
+static u8 pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+       for ( ; chipset_table->xfer_speed ; chipset_table++)
+               if (chipset_table->xfer_speed == speed) {
+                       return chipset_table->chipset_settings;
+               }
+       return chipset_table->chipset_settings;
+}
+
+static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+       for ( ; chipset_table->xfer_speed ; chipset_table++)
+               if (chipset_table->xfer_speed == speed) {
+                       return chipset_table->ultra_settings;
+               }
+       return chipset_table->ultra_settings;
+}
+
+static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
+       u16 d_conf              = 0;
+       u8 ultra = 0, ultra_conf = 0;
+       u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       /* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
+       pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
+       tmp0 = pci_bus_clock_list(speed, bus_clock);
+       d_conf = ((tmp0 & 0xf0) << 4) | (tmp0 & 0xf);
+       pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
+
+       tmp1 = 0x00;
+       tmp2 = 0x00;
+       pci_read_config_byte(dev, 0x54, &ultra);
+       tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
+       ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
+       tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
+       pci_write_config_byte(dev, 0x54, tmp2);
+       local_irq_restore(flags);
+}
+
+static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
+       u8 unit                 = drive->dn & 1;
+       u8 tmp1 = 0, tmp2 = 0;
+       u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       /* high 4-bits: Active, low 4-bits: Recovery */
+       pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
+       drive_conf = pci_bus_clock_list(speed, bus_clock);
+       pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
+
+       pci_read_config_byte(dev, (0x44|hwif->channel), &ultra);
+       tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
+       ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
+       tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
+       pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
+       local_irq_restore(flags);
+}
+
+static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
+}
+
+static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
+{
+       /* These are necessary to get AEC6280 Macintosh cards to work */
+       if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
+           (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
+               u8 reg49h = 0, reg4ah = 0;
+               /* Clear reset and test bits.  */
+               pci_read_config_byte(dev, 0x49, &reg49h);
+               pci_write_config_byte(dev, 0x49, reg49h & ~0x30);
+               /* Enable chip interrupt output.  */
+               pci_read_config_byte(dev, 0x4a, &reg4ah);
+               pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01);
+               /* Enable burst mode. */
+               pci_read_config_byte(dev, 0x4a, &reg4ah);
+               pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
+       }
+
+       return dev->irq;
+}
+
+static u8 atp86x_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
+       pci_read_config_byte(dev, 0x49, &ata66);
+
+       return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+static const struct ide_port_ops atp850_port_ops = {
+       .set_pio_mode           = aec_set_pio_mode,
+       .set_dma_mode           = aec6210_set_mode,
+};
+
+static const struct ide_port_ops atp86x_port_ops = {
+       .set_pio_mode           = aec_set_pio_mode,
+       .set_dma_mode           = aec6260_set_mode,
+       .cable_detect           = atp86x_cable_detect,
+};
+
+static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+       {       /* 0: AEC6210 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_aec62xx,
+               .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+               .port_ops       = &atp850_port_ops,
+               .host_flags     = IDE_HFLAG_SERIALIZE |
+                                 IDE_HFLAG_NO_ATAPI_DMA |
+                                 IDE_HFLAG_NO_DSC |
+                                 IDE_HFLAG_OFF_BOARD,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA2,
+       },
+       {       /* 1: AEC6260 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_aec62xx,
+               .port_ops       = &atp86x_port_ops,
+               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
+                                 IDE_HFLAG_OFF_BOARD,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA4,
+       },
+       {       /* 2: AEC6260R */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_aec62xx,
+               .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+               .port_ops       = &atp86x_port_ops,
+               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
+                                 IDE_HFLAG_NON_BOOTABLE,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA4,
+       },
+       {       /* 3: AEC6280 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_aec62xx,
+               .port_ops       = &atp86x_port_ops,
+               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
+                                 IDE_HFLAG_OFF_BOARD,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       },
+       {       /* 4: AEC6280R */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_aec62xx,
+               .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+               .port_ops       = &atp86x_port_ops,
+               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
+                                 IDE_HFLAG_OFF_BOARD,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       }
+};
+
+/**
+ *     aec62xx_init_one        -       called when a AEC is found
+ *     @dev: the aec62xx device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ *
+ *     NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
+ *     chips, pass a local copy of 'struct ide_port_info' down the call chain.
+ */
+
+static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       const struct chipset_bus_clock_list_entry *bus_clock;
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+       int err;
+
+       if (bus_speed <= 33)
+               bus_clock = aec6xxx_33_base;
+       else
+               bus_clock = aec6xxx_34_base;
+
+       err = pci_enable_device(dev);
+       if (err)
+               return err;
+
+       d = aec62xx_chipsets[idx];
+
+       if (idx == 3 || idx == 4) {
+               unsigned long dma_base = pci_resource_start(dev, 4);
+
+               if (inb(dma_base + 2) & 0x10) {
+                       printk(KERN_INFO DRV_NAME " %s: AEC6880%s card detected"
+                               "\n", pci_name(dev), (idx == 4) ? "R" : "");
+                       d.udma_mask = ATA_UDMA6;
+               }
+       }
+
+       err = ide_pci_init_one(dev, &d, (void *)bus_clock);
+       if (err)
+               pci_disable_device(dev);
+
+       return err;
+}
+
+static void __devexit aec62xx_remove(struct pci_dev *dev)
+{
+       ide_pci_remove(dev);
+       pci_disable_device(dev);
+}
+
+static const struct pci_device_id aec62xx_pci_tbl[] = {
+       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
+       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860),   1 },
+       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R),  2 },
+       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865),   3 },
+       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R),  4 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
+
+static struct pci_driver aec62xx_pci_driver = {
+       .name           = "AEC62xx_IDE",
+       .id_table       = aec62xx_pci_tbl,
+       .probe          = aec62xx_init_one,
+       .remove         = __devexit_p(aec62xx_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init aec62xx_ide_init(void)
+{
+       return ide_pci_register_driver(&aec62xx_pci_driver);
+}
+
+static void __exit aec62xx_ide_exit(void)
+{
+       pci_unregister_driver(&aec62xx_pci_driver);
+}
+
+module_init(aec62xx_ide_init);
+module_exit(aec62xx_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
new file mode 100644 (file)
index 0000000..90da1f9
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ *  Copyright (C) 1996  Linus Torvalds & author (see below)
+ */
+
+/*
+ * ALI M14xx chipset EIDE controller
+ *
+ * Works for ALI M1439/1443/1445/1487/1489 chipsets.
+ *
+ * Adapted from code developed by derekn@vw.ece.cmu.edu.  -ml
+ * Derek's notes follow:
+ *
+ * I think the code should be pretty understandable,
+ * but I'll be happy to (try to) answer questions.
+ *
+ * The critical part is in the setupDrive function.  The initRegisters
+ * function doesn't seem to be necessary, but the DOS driver does it, so
+ * I threw it in.
+ *
+ * I've only tested this on my system, which only has one disk.  I posted
+ * it to comp.sys.linux.hardware, so maybe some other people will try it
+ * out.
+ *
+ * Derek Noonburg  (derekn@ece.cmu.edu)
+ * 95-sep-26
+ *
+ * Update 96-jul-13:
+ *
+ * I've since upgraded to two disks and a CD-ROM, with no trouble, and
+ * I've also heard from several others who have used it successfully.
+ * This driver appears to work with both the 1443/1445 and the 1487/1489
+ * chipsets.  I've added support for PIO mode 4 for the 1487.  This
+ * seems to work just fine on the 1443 also, although I'm not sure it's
+ * advertised as supporting mode 4.  (I've been running a WDC AC21200 in
+ * mode 4 for a while now with no trouble.)  -Derek
+ */
+
+#include <linux/module.h>
+#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/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "ali14xx"
+
+/* port addresses for auto-detection */
+#define ALI_NUM_PORTS 4
+static const int ports[ALI_NUM_PORTS] __initdata =
+       { 0x074, 0x0f4, 0x034, 0x0e4 };
+
+/* register initialization data */
+typedef struct { u8 reg, data; } RegInitializer;
+
+static const RegInitializer initData[] __initdata = {
+       {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
+       {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
+       {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
+       {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
+       {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
+       {0x35, 0x03}, {0x00, 0x00}
+};
+
+/* timing parameter registers for each drive */
+static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
+       {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
+       {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
+       {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
+       {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
+};
+
+static int basePort;   /* base port address */
+static int regPort;    /* port for register number */
+static int dataPort;   /* port for register data */
+static u8 regOn;       /* output to base port to access registers */
+static u8 regOff;      /* output to base port to close registers */
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * Read a controller register.
+ */
+static inline u8 inReg(u8 reg)
+{
+       outb_p(reg, regPort);
+       return inb(dataPort);
+}
+
+/*
+ * Write a controller register.
+ */
+static void outReg(u8 data, u8 reg)
+{
+       outb_p(reg, regPort);
+       outb_p(data, dataPort);
+}
+
+static DEFINE_SPINLOCK(ali14xx_lock);
+
+/*
+ * Set PIO mode for the specified drive.
+ * This function computes timing parameters
+ * and sets controller registers accordingly.
+ */
+static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       int driveNum;
+       int time1, time2;
+       u8 param1, param2, param3, param4;
+       unsigned long flags;
+       int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
+       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+
+       /* calculate timing, according to PIO mode */
+       time1 = ide_pio_cycle_time(drive, pio);
+       time2 = t->active;
+       param3 = param1 = (time2 * bus_speed + 999) / 1000;
+       param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
+       if (pio < 3) {
+               param3 += 8;
+               param4 += 8;
+       }
+       printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
+               drive->name, pio, time1, time2, param1, param2, param3, param4);
+
+       /* stuff timing parameters into controller registers */
+       driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
+       spin_lock_irqsave(&ali14xx_lock, flags);
+       outb_p(regOn, basePort);
+       outReg(param1, regTab[driveNum].reg1);
+       outReg(param2, regTab[driveNum].reg2);
+       outReg(param3, regTab[driveNum].reg3);
+       outReg(param4, regTab[driveNum].reg4);
+       outb_p(regOff, basePort);
+       spin_unlock_irqrestore(&ali14xx_lock, flags);
+}
+
+/*
+ * Auto-detect the IDE controller port.
+ */
+static int __init findPort(void)
+{
+       int i;
+       u8 t;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       for (i = 0; i < ALI_NUM_PORTS; ++i) {
+               basePort = ports[i];
+               regOff = inb(basePort);
+               for (regOn = 0x30; regOn <= 0x33; ++regOn) {
+                       outb_p(regOn, basePort);
+                       if (inb(basePort) == regOn) {
+                               regPort = basePort + 4;
+                               dataPort = basePort + 8;
+                               t = inReg(0) & 0xf0;
+                               outb_p(regOff, basePort);
+                               local_irq_restore(flags);
+                               if (t != 0x50)
+                                       return 0;
+                               return 1;  /* success */
+                       }
+               }
+               outb_p(regOff, basePort);
+       }
+       local_irq_restore(flags);
+       return 0;
+}
+
+/*
+ * Initialize controller registers with default values.
+ */
+static int __init initRegisters(void)
+{
+       const RegInitializer *p;
+       u8 t;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       outb_p(regOn, basePort);
+       for (p = initData; p->reg != 0; ++p)
+               outReg(p->data, p->reg);
+       outb_p(0x01, regPort);
+       t = inb(regPort) & 0x01;
+       outb_p(regOff, basePort);
+       local_irq_restore(flags);
+       return t;
+}
+
+static const struct ide_port_ops ali14xx_port_ops = {
+       .set_pio_mode           = ali14xx_set_pio_mode,
+};
+
+static const struct ide_port_info ali14xx_port_info = {
+       .name                   = DRV_NAME,
+       .chipset                = ide_ali14xx,
+       .port_ops               = &ali14xx_port_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+       .pio_mask               = ATA_PIO4,
+};
+
+static int __init ali14xx_probe(void)
+{
+       printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
+                         basePort, regOn);
+
+       /* initialize controller registers */
+       if (!initRegisters()) {
+               printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
+               return 1;
+       }
+
+       return ide_legacy_device_add(&ali14xx_port_info, 0);
+}
+
+static int probe_ali14xx;
+
+module_param_named(probe, probe_ali14xx, bool, 0);
+MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
+
+static int __init ali14xx_init(void)
+{
+       if (probe_ali14xx == 0)
+               goto out;
+
+       /* auto-detect IDE controller port */
+       if (findPort()) {
+               if (ali14xx_probe())
+                       return -ENODEV;
+               return 0;
+       }
+       printk(KERN_ERR "ali14xx: not found.\n");
+out:
+       return -ENODEV;
+}
+
+module_init(ali14xx_init);
+
+MODULE_AUTHOR("see local file");
+MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
new file mode 100644 (file)
index 0000000..daf9dce
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
+ *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
+ *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
+ *
+ *  Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org)
+ *  May be copied or modified under the terms of the GNU General Public License
+ *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
+ *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
+ *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+ *
+ *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
+ *
+ **********************************************************************
+ *  9/7/99 --Parts from the above author are included and need to be
+ *  converted into standard interface, once I finish the thought.
+ *
+ *  Recent changes
+ *     Don't use LBA48 mode on ALi <= 0xC4
+ *     Don't poke 0x79 with a non ALi northbridge
+ *     Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang)
+ *     Allow UDMA6 on revisions > 0xC4
+ *
+ *  Documentation
+ *     Chipset documentation available under NDA only
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "alim15x3"
+
+/*
+ * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking
+ * (this is DANGEROUS and could result in data corruption).
+ */
+static int wdc_udma;
+
+module_param(wdc_udma, bool, 0);
+MODULE_PARM_DESC(wdc_udma,
+                "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)");
+
+/*
+ *     ALi devices are not plug in. Otherwise these static values would
+ *     need to go. They ought to go away anyway
+ */
+static u8 m5229_revision;
+static u8 chip_is_1543c_e;
+static struct pci_dev *isa_dev;
+
+/**
+ *     ali_set_pio_mode        -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Program the controller for the given PIO mode.
+ */
+
+static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+       int s_time = t->setup, a_time = t->active, c_time = t->cycle;
+       u8 s_clc, a_clc, r_clc;
+       unsigned long flags;
+       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+       int port = hwif->channel ? 0x5c : 0x58;
+       int portFIFO = hwif->channel ? 0x55 : 0x54;
+       u8 cd_dma_fifo = 0, unit = drive->dn & 1;
+
+       if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
+               s_clc = 0;
+       if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
+               a_clc = 0;
+
+       if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
+               r_clc = 1;
+       } else {
+               if (r_clc >= 16)
+                       r_clc = 0;
+       }
+       local_irq_save(flags);
+       
+       /* 
+        * PIO mode => ATA FIFO on, ATAPI FIFO off
+        */
+       pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);
+       if (drive->media==ide_disk) {
+               if (unit) {
+                       pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);
+               } else {
+                       pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);
+               }
+       } else {
+               if (unit) {
+                       pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);
+               } else {
+                       pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);
+               }
+       }
+       
+       pci_write_config_byte(dev, port, s_clc);
+       pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
+       local_irq_restore(flags);
+}
+
+/**
+ *     ali_udma_filter         -       compute UDMA mask
+ *     @drive: IDE device
+ *
+ *     Return available UDMA modes.
+ *
+ *     The actual rules for the ALi are:
+ *             No UDMA on revisions <= 0x20
+ *             Disk only for revisions < 0xC2
+ *             Not WDC drives on M1543C-E (?)
+ */
+
+static u8 ali_udma_filter(ide_drive_t *drive)
+{
+       if (m5229_revision > 0x20 && m5229_revision < 0xC2) {
+               if (drive->media != ide_disk)
+                       return 0;
+               if (wdc_udma == 0 && chip_is_1543c_e &&
+                   strstr((char *)&drive->id[ATA_ID_PROD], "WDC "))
+                       return 0;
+       }
+
+       return drive->hwif->ultra_mask;
+}
+
+/**
+ *     ali_set_dma_mode        -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Configure the hardware for the desired IDE transfer mode.
+ */
+
+static void ali_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 speed1               = speed;
+       u8 unit                 = drive->dn & 1;
+       u8 tmpbyte              = 0x00;
+       int m5229_udma          = (hwif->channel) ? 0x57 : 0x56;
+
+       if (speed == XFER_UDMA_6)
+               speed1 = 0x47;
+
+       if (speed < XFER_UDMA_0) {
+               u8 ultra_enable = (unit) ? 0x7f : 0xf7;
+               /*
+                * clear "ultra enable" bit
+                */
+               pci_read_config_byte(dev, m5229_udma, &tmpbyte);
+               tmpbyte &= ultra_enable;
+               pci_write_config_byte(dev, m5229_udma, tmpbyte);
+
+               /*
+                * FIXME: Oh, my... DMA timings are never set.
+                */
+       } else {
+               pci_read_config_byte(dev, m5229_udma, &tmpbyte);
+               tmpbyte &= (0x0f << ((1-unit) << 2));
+               /*
+                * enable ultra dma and set timing
+                */
+               tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2));
+               pci_write_config_byte(dev, m5229_udma, tmpbyte);
+               if (speed >= XFER_UDMA_3) {
+                       pci_read_config_byte(dev, 0x4b, &tmpbyte);
+                       tmpbyte |= 1;
+                       pci_write_config_byte(dev, 0x4b, tmpbyte);
+               }
+       }
+}
+
+/**
+ *     ali15x3_dma_setup       -       begin a DMA phase
+ *     @drive: target device
+ *
+ *     Returns 1 if the DMA cannot be performed, zero on success.
+ */
+
+static int ali15x3_dma_setup(ide_drive_t *drive)
+{
+       if (m5229_revision < 0xC2 && drive->media != ide_disk) {
+               if (rq_data_dir(drive->hwif->hwgroup->rq))
+                       return 1;       /* try PIO instead of DMA */
+       }
+       return ide_dma_setup(drive);
+}
+
+/**
+ *     init_chipset_ali15x3    -       Initialise an ALi IDE controller
+ *     @dev: PCI device
+ *
+ *     This function initializes the ALI IDE controller and where 
+ *     appropriate also sets up the 1533 southbridge.
+ */
+
+static unsigned int init_chipset_ali15x3(struct pci_dev *dev)
+{
+       unsigned long flags;
+       u8 tmpbyte;
+       struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
+
+       m5229_revision = dev->revision;
+
+       isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+
+       local_irq_save(flags);
+
+       if (m5229_revision < 0xC2) {
+               /*
+                * revision 0x20 (1543-E, 1543-F)
+                * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E)
+                * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7
+                */
+               pci_read_config_byte(dev, 0x4b, &tmpbyte);
+               /*
+                * clear bit 7
+                */
+               pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
+               /*
+                * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
+                */
+               if (m5229_revision >= 0x20 && isa_dev) {
+                       pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
+                       chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
+               }
+               goto out;
+       }
+
+       /*
+        * 1543C-B?, 1535, 1535D, 1553
+        * Note 1: not all "motherboard" support this detection
+        * Note 2: if no udma 66 device, the detection may "error".
+        *         but in this case, we will not set the device to
+        *         ultra 66, the detection result is not important
+        */
+
+       /*
+        * enable "Cable Detection", m5229, 0x4b, bit3
+        */
+       pci_read_config_byte(dev, 0x4b, &tmpbyte);
+       pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08);
+
+       /*
+        * We should only tune the 1533 enable if we are using an ALi
+        * North bridge. We might have no north found on some zany
+        * box without a device at 0:0.0. The ALi bridge will be at
+        * 0:0.0 so if we didn't find one we know what is cooking.
+        */
+       if (north && north->vendor != PCI_VENDOR_ID_AL)
+               goto out;
+
+       if (m5229_revision < 0xC5 && isa_dev)
+       {       
+               /*
+                * set south-bridge's enable bit, m1533, 0x79
+                */
+
+               pci_read_config_byte(isa_dev, 0x79, &tmpbyte);
+               if (m5229_revision == 0xC2) {
+                       /*
+                        * 1543C-B0 (m1533, 0x79, bit 2)
+                        */
+                       pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04);
+               } else if (m5229_revision >= 0xC3) {
+                       /*
+                        * 1553/1535 (m1533, 0x79, bit 1)
+                        */
+                       pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
+               }
+       }
+
+out:
+       /*
+        * CD_ROM DMA on (m5229, 0x53, bit0)
+        *      Enable this bit even if we want to use PIO.
+        * PIO FIFO off (m5229, 0x53, bit1)
+        *      The hardware will use 0x54h and 0x55h to control PIO FIFO.
+        *      (Not on later devices it seems)
+        *
+        *      0x53 changes meaning on later revs - we must no touch
+        *      bit 1 on them.  Need to check if 0x20 is the right break.
+        */
+       if (m5229_revision >= 0x20) {
+               pci_read_config_byte(dev, 0x53, &tmpbyte);
+
+               if (m5229_revision <= 0x20)
+                       tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+               else if (m5229_revision == 0xc7 || m5229_revision == 0xc8)
+                       tmpbyte |= 0x03;
+               else
+                       tmpbyte |= 0x01;
+
+               pci_write_config_byte(dev, 0x53, tmpbyte);
+       }
+       pci_dev_put(north);
+       pci_dev_put(isa_dev);
+       local_irq_restore(flags);
+       return 0;
+}
+
+/*
+ *     Cable special cases
+ */
+
+static const struct dmi_system_id cable_dmi_table[] = {
+       {
+               .ident = "HP Pavilion N5430",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+               },
+       },
+       {
+               .ident = "Toshiba Satellite S1800-814",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
+               },
+       },
+       { }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+       /* Fujitsu P2000 */
+       if (pdev->subsystem_vendor == 0x10CF &&
+           pdev->subsystem_device == 0x10AF)
+               return 1;
+
+       /* Mitac 8317 (Winbook-A) and relatives */
+       if (pdev->subsystem_vendor == 0x1071 &&
+           pdev->subsystem_device == 0x8317)
+               return 1;
+
+       /* Systems by DMI */
+       if (dmi_check_system(cable_dmi_table))
+               return 1;
+
+       return 0;
+}
+
+/**
+ *     ali_cable_detect        -       cable detection
+ *     @hwif: IDE interface
+ *
+ *     This checks if the controller and the cable are capable
+ *     of UDMA66 transfers. It doesn't check the drives.
+ *     But see note 2 below!
+ *
+ *     FIXME: frobs bits that are not defined on newer ALi devicea
+ */
+
+static u8 ali_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long flags;
+       u8 cbl = ATA_CBL_PATA40, tmpbyte;
+
+       local_irq_save(flags);
+
+       if (m5229_revision >= 0xC2) {
+               /*
+                * m5229 80-pin cable detection (from Host View)
+                *
+                * 0x4a bit0 is 0 => primary channel has 80-pin
+                * 0x4a bit1 is 0 => secondary channel has 80-pin
+                *
+                * Certain laptops use short but suitable cables
+                * and don't implement the detect logic.
+                */
+               if (ali_cable_override(dev))
+                       cbl = ATA_CBL_PATA40_SHORT;
+               else {
+                       pci_read_config_byte(dev, 0x4a, &tmpbyte);
+                       if ((tmpbyte & (1 << hwif->channel)) == 0)
+                               cbl = ATA_CBL_PATA80;
+               }
+       }
+
+       local_irq_restore(flags);
+
+       return cbl;
+}
+
+#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
+/**
+ *     init_hwif_ali15x3       -       Initialize the ALI IDE x86 stuff
+ *     @hwif: interface to configure
+ *
+ *     Obtain the IRQ tables for an ALi based IDE solution on the PC
+ *     class platforms. This part of the code isn't applicable to the
+ *     Sparc and PowerPC systems.
+ */
+
+static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u8 ideic, inmir;
+       s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
+                                     1, 11, 0, 12, 0, 14, 0, 15 };
+       int irq = -1;
+
+       if (dev->device == PCI_DEVICE_ID_AL_M5229)
+               hwif->irq = hwif->channel ? 15 : 14;
+
+       if (isa_dev) {
+               /*
+                * read IDE interface control
+                */
+               pci_read_config_byte(isa_dev, 0x58, &ideic);
+
+               /* bit0, bit1 */
+               ideic = ideic & 0x03;
+
+               /* get IRQ for IDE Controller */
+               if ((hwif->channel && ideic == 0x03) ||
+                   (!hwif->channel && !ideic)) {
+                       /*
+                        * get SIRQ1 routing table
+                        */
+                       pci_read_config_byte(isa_dev, 0x44, &inmir);
+                       inmir = inmir & 0x0f;
+                       irq = irq_routing_table[inmir];
+               } else if (hwif->channel && !(ideic & 0x01)) {
+                       /*
+                        * get SIRQ2 routing table
+                        */
+                       pci_read_config_byte(isa_dev, 0x75, &inmir);
+                       inmir = inmir & 0x0f;
+                       irq = irq_routing_table[inmir];
+               }
+               if(irq >= 0)
+                       hwif->irq = irq;
+       }
+}
+#else
+#define init_hwif_ali15x3 NULL
+#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
+
+/**
+ *     init_dma_ali15x3        -       set up DMA on ALi15x3
+ *     @hwif: IDE interface
+ *     @d: IDE port info
+ *
+ *     Set up the DMA functionality on the ALi 15x3.
+ */
+
+static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
+                                     const struct ide_port_info *d)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long base = ide_pci_dma_base(hwif, d);
+
+       if (base == 0)
+               return -1;
+
+       hwif->dma_base = base;
+
+       if (ide_pci_check_simplex(hwif, d) < 0)
+               return -1;
+
+       if (ide_pci_set_master(dev, d->name) < 0)
+               return -1;
+
+       if (!hwif->channel)
+               outb(inb(base + 2) & 0x60, base + 2);
+
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+                        hwif->name, base, base + 7);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       hwif->dma_ops = &sff_dma_ops;
+
+       return 0;
+}
+
+static const struct ide_port_ops ali_port_ops = {
+       .set_pio_mode           = ali_set_pio_mode,
+       .set_dma_mode           = ali_set_dma_mode,
+       .udma_filter            = ali_udma_filter,
+       .cable_detect           = ali_cable_detect,
+};
+
+static const struct ide_dma_ops ali_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ali15x3_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_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info ali15x3_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_ali15x3,
+       .init_hwif      = init_hwif_ali15x3,
+       .init_dma       = init_dma_ali15x3,
+       .port_ops       = &ali_port_ops,
+       .pio_mask       = ATA_PIO5,
+       .swdma_mask     = ATA_SWDMA2,
+       .mwdma_mask     = ATA_MWDMA2,
+};
+
+/**
+ *     alim15x3_init_one       -       set up an ALi15x3 IDE controller
+ *     @dev: PCI device to set up
+ *
+ *     Perform the actual set up for an ALi15x3 that has been found by the
+ *     hot plug layer.
+ */
+static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d = ali15x3_chipset;
+       u8 rev = dev->revision, idx = id->driver_data;
+
+       /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
+       if (rev <= 0xC4)
+               d.host_flags |= IDE_HFLAG_NO_LBA48_DMA;
+
+       if (rev >= 0x20) {
+               if (rev == 0x20)
+                       d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+
+               if (rev < 0xC2)
+                       d.udma_mask = ATA_UDMA2;
+               else if (rev == 0xC2 || rev == 0xC3)
+                       d.udma_mask = ATA_UDMA4;
+               else if (rev == 0xC4)
+                       d.udma_mask = ATA_UDMA5;
+               else
+                       d.udma_mask = ATA_UDMA6;
+
+               d.dma_ops = &ali_dma_ops;
+       } else {
+               d.host_flags |= IDE_HFLAG_NO_DMA;
+
+               d.mwdma_mask = d.swdma_mask = 0;
+       }
+
+       if (idx == 0)
+               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+
+static const struct pci_device_id alim15x3_pci_tbl[] = {
+       { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
+       { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
+
+static struct pci_driver alim15x3_pci_driver = {
+       .name           = "ALI15x3_IDE",
+       .id_table       = alim15x3_pci_tbl,
+       .probe          = alim15x3_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init ali15x3_ide_init(void)
+{
+       return ide_pci_register_driver(&alim15x3_pci_driver);
+}
+
+static void __exit ali15x3_ide_exit(void)
+{
+       return pci_unregister_driver(&alim15x3_pci_driver);
+}
+
+module_init(ali15x3_ide_init);
+module_exit(ali15x3_ide_exit);
+
+MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
new file mode 100644 (file)
index 0000000..81ec731
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
+ * IDE driver for Linux.
+ *
+ * Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
+ *
+ * Based on the work of:
+ *      Andre Hedrick
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#define DRV_NAME "amd74xx"
+
+enum {
+       AMD_IDE_CONFIG          = 0x41,
+       AMD_CABLE_DETECT        = 0x42,
+       AMD_DRIVE_TIMING        = 0x48,
+       AMD_8BIT_TIMING         = 0x4e,
+       AMD_ADDRESS_SETUP       = 0x4c,
+       AMD_UDMA_TIMING         = 0x50,
+};
+
+static unsigned int amd_80w;
+static unsigned int amd_clock;
+
+static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
+static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
+
+static inline u8 amd_offset(struct pci_dev *dev)
+{
+       return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
+}
+
+/*
+ * amd_set_speed() writes timing values to the chipset registers
+ */
+
+static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
+                         struct ide_timing *timing)
+{
+       u8 t = 0, offset = amd_offset(dev);
+
+       pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
+       t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+       pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
+
+       pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
+               ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
+
+       pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
+               ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
+
+       switch (udma_mask) {
+       case ATA_UDMA2: t = timing->udma ? (0xc0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
+       case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 2, 10)]) : 0x03; break;
+       case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 10)]) : 0x03; break;
+       case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 15)]) : 0x03; break;
+       default: return;
+       }
+
+       pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
+}
+
+/*
+ * amd_set_drive() computes timing values and configures the chipset
+ * to a desired transfer mode.  It also can be called by upper layers.
+ */
+
+static void amd_set_drive(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+       struct ide_timing t, p;
+       int T, UT;
+       u8 udma_mask = hwif->ultra_mask;
+
+       T = 1000000000 / amd_clock;
+       UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
+
+       ide_timing_compute(drive, speed, &t, T, UT);
+
+       if (peer->dev_flags & IDE_DFLAG_PRESENT) {
+               ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+               ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
+       }
+
+       if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
+       if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
+
+       amd_set_speed(dev, drive->dn, udma_mask, &t);
+}
+
+/*
+ * amd_set_pio_mode() is a callback from upper layers for PIO-only tuning.
+ */
+
+static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       amd_set_drive(drive, XFER_PIO_0 + pio);
+}
+
+static void amd7409_cable_detect(struct pci_dev *dev)
+{
+       /* no host side cable detection */
+       amd_80w = 0x03;
+}
+
+static void amd7411_cable_detect(struct pci_dev *dev)
+{
+       int i;
+       u32 u = 0;
+       u8 t = 0, offset = amd_offset(dev);
+
+       pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
+       pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
+       amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
+       for (i = 24; i >= 0; i -= 8)
+               if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
+                       printk(KERN_WARNING DRV_NAME " %s: BIOS didn't set "
+                               "cable bits correctly. Enabling workaround.\n",
+                               pci_name(dev));
+                       amd_80w |= (1 << (1 - (i >> 4)));
+               }
+}
+
+/*
+ * The initialization callback.  Initialize drive independent registers.
+ */
+
+static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
+{
+       u8 t = 0, offset = amd_offset(dev);
+
+/*
+ * Check 80-wire cable presence.
+ */
+
+       if (dev->vendor == PCI_VENDOR_ID_AMD &&
+           dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
+               ; /* no UDMA > 2 */
+       else if (dev->vendor == PCI_VENDOR_ID_AMD &&
+                dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
+               amd7409_cable_detect(dev);
+       else
+               amd7411_cable_detect(dev);
+
+/*
+ * Take care of prefetch & postwrite.
+ */
+
+       pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
+       /*
+        * Check for broken FIFO support.
+        */
+       if (dev->vendor == PCI_VENDOR_ID_AMD &&
+           dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
+               t &= 0x0f;
+       else
+               t |= 0xf0;
+       pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
+
+       return dev->irq;
+}
+
+static u8 amd_cable_detect(ide_hwif_t *hwif)
+{
+       if ((amd_80w >> hwif->channel) & 1)
+               return ATA_CBL_PATA80;
+       else
+               return ATA_CBL_PATA40;
+}
+
+static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       if (hwif->irq == 0) /* 0 is bogus but will do for now */
+               hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
+}
+
+static const struct ide_port_ops amd_port_ops = {
+       .set_pio_mode           = amd_set_pio_mode,
+       .set_dma_mode           = amd_set_drive,
+       .cable_detect           = amd_cable_detect,
+};
+
+#define IDE_HFLAGS_AMD \
+       (IDE_HFLAG_PIO_NO_BLACKLIST | \
+        IDE_HFLAG_POST_SET_MODE | \
+        IDE_HFLAG_IO_32BIT | \
+        IDE_HFLAG_UNMASK_IRQS)
+
+#define DECLARE_AMD_DEV(swdma, udma)                           \
+       {                                                               \
+               .name           = DRV_NAME,                             \
+               .init_chipset   = init_chipset_amd74xx,                 \
+               .init_hwif      = init_hwif_amd74xx,                    \
+               .enablebits     = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
+               .port_ops       = &amd_port_ops,                        \
+               .host_flags     = IDE_HFLAGS_AMD,                       \
+               .pio_mask       = ATA_PIO5,                             \
+               .swdma_mask     = swdma,                                \
+               .mwdma_mask     = ATA_MWDMA2,                           \
+               .udma_mask      = udma,                                 \
+       }
+
+#define DECLARE_NV_DEV(udma)                                   \
+       {                                                               \
+               .name           = DRV_NAME,                             \
+               .init_chipset   = init_chipset_amd74xx,                 \
+               .init_hwif      = init_hwif_amd74xx,                    \
+               .enablebits     = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
+               .port_ops       = &amd_port_ops,                        \
+               .host_flags     = IDE_HFLAGS_AMD,                       \
+               .pio_mask       = ATA_PIO5,                             \
+               .swdma_mask     = ATA_SWDMA2,                           \
+               .mwdma_mask     = ATA_MWDMA2,                           \
+               .udma_mask      = udma,                                 \
+       }
+
+static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
+       /* 0: AMD7401 */        DECLARE_AMD_DEV(0x00, ATA_UDMA2),
+       /* 1: AMD7409 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
+       /* 2: AMD7411/7441 */   DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
+       /* 3: AMD8111 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6),
+
+       /* 4: NFORCE */         DECLARE_NV_DEV(ATA_UDMA5),
+       /* 5: >= NFORCE2 */     DECLARE_NV_DEV(ATA_UDMA6),
+
+       /* 6: AMD5536 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
+};
+
+static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+
+       d = amd74xx_chipsets[idx];
+
+       /*
+        * Check for bad SWDMA and incorrectly wired Serenade mainboards.
+        */
+       if (idx == 1) {
+               if (dev->revision <= 7)
+                       d.swdma_mask = 0;
+               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+       } else if (idx == 3) {
+               if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+                   dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+                       d.udma_mask = ATA_UDMA5;
+       }
+
+       printk(KERN_INFO "%s %s: UDMA%s controller\n",
+               d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
+
+       /*
+       * Determine the system bus clock.
+       */
+       amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+       switch (amd_clock) {
+       case 33000: amd_clock = 33333; break;
+       case 37000: amd_clock = 37500; break;
+       case 41000: amd_clock = 41666; break;
+       }
+
+       if (amd_clock < 20000 || amd_clock > 50000) {
+               printk(KERN_WARNING "%s: User given PCI clock speed impossible"
+                                   " (%d), using 33 MHz instead.\n",
+                                   d.name, amd_clock);
+               amd_clock = 33333;
+       }
+
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static const struct pci_device_id amd74xx_pci_tbl[] = {
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_COBRA_7401),           0 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_VIPER_7409),           1 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_VIPER_7411),           2 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_OPUS_7441),            2 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_8111_IDE),             3 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_IDE),        4 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE),       5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE),      5 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA),     5 },
+#endif
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE),       5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE),      5 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA),     5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2),    5 },
+#endif
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE),  5 },
+       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE),  5 },
+       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_CS5536_IDE),           6 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
+
+static struct pci_driver amd74xx_pci_driver = {
+       .name           = "AMD_IDE",
+       .id_table       = amd74xx_pci_tbl,
+       .probe          = amd74xx_probe,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init amd74xx_ide_init(void)
+{
+       return ide_pci_register_driver(&amd74xx_pci_driver);
+}
+
+static void __exit amd74xx_ide_exit(void)
+{
+       pci_unregister_driver(&amd74xx_pci_driver);
+}
+
+module_init(amd74xx_ide_init);
+module_exit(amd74xx_ide_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik");
+MODULE_DESCRIPTION("AMD PCI IDE driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
deleted file mode 100644 (file)
index 5bc2605..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-
-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)       += icside.o
-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)       += rapide.o
-obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)  += palm_bk3710.o
-
-ifeq ($(CONFIG_IDE_ARM), m)
-       obj-m += ide_arm.o
-endif
-
-EXTRA_CFLAGS   := -Idrivers/ide
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
deleted file mode 100644 (file)
index 76bdc9a..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * Copyright (c) 1996-2004 Russell King.
- *
- * Please note that this platform does not support 32-bit IDE IO.
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/ide.h>
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/scatterlist.h>
-#include <linux/io.h>
-
-#include <asm/dma.h>
-#include <asm/ecard.h>
-
-#define DRV_NAME "icside"
-
-#define ICS_IDENT_OFFSET               0x2280
-
-#define ICS_ARCIN_V5_INTRSTAT          0x0000
-#define ICS_ARCIN_V5_INTROFFSET                0x0004
-#define ICS_ARCIN_V5_IDEOFFSET         0x2800
-#define ICS_ARCIN_V5_IDEALTOFFSET      0x2b80
-#define ICS_ARCIN_V5_IDESTEPPING       6
-
-#define ICS_ARCIN_V6_IDEOFFSET_1       0x2000
-#define ICS_ARCIN_V6_INTROFFSET_1      0x2200
-#define ICS_ARCIN_V6_INTRSTAT_1                0x2290
-#define ICS_ARCIN_V6_IDEALTOFFSET_1    0x2380
-#define ICS_ARCIN_V6_IDEOFFSET_2       0x3000
-#define ICS_ARCIN_V6_INTROFFSET_2      0x3200
-#define ICS_ARCIN_V6_INTRSTAT_2                0x3290
-#define ICS_ARCIN_V6_IDEALTOFFSET_2    0x3380
-#define ICS_ARCIN_V6_IDESTEPPING       6
-
-struct cardinfo {
-       unsigned int dataoffset;
-       unsigned int ctrloffset;
-       unsigned int stepping;
-};
-
-static struct cardinfo icside_cardinfo_v5 = {
-       .dataoffset     = ICS_ARCIN_V5_IDEOFFSET,
-       .ctrloffset     = ICS_ARCIN_V5_IDEALTOFFSET,
-       .stepping       = ICS_ARCIN_V5_IDESTEPPING,
-};
-
-static struct cardinfo icside_cardinfo_v6_1 = {
-       .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_1,
-       .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_1,
-       .stepping       = ICS_ARCIN_V6_IDESTEPPING,
-};
-
-static struct cardinfo icside_cardinfo_v6_2 = {
-       .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_2,
-       .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_2,
-       .stepping       = ICS_ARCIN_V6_IDESTEPPING,
-};
-
-struct icside_state {
-       unsigned int channel;
-       unsigned int enabled;
-       void __iomem *irq_port;
-       void __iomem *ioc_base;
-       unsigned int sel;
-       unsigned int type;
-       struct ide_host *host;
-};
-
-#define ICS_TYPE_A3IN  0
-#define ICS_TYPE_A3USER        1
-#define ICS_TYPE_V6    3
-#define ICS_TYPE_V5    15
-#define ICS_TYPE_NOTYPE        ((unsigned int)-1)
-
-/* ---------------- Version 5 PCB Support Functions --------------------- */
-/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
- * Purpose  : enable interrupts from card
- */
-static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
-{
-       struct icside_state *state = ec->irq_data;
-
-       writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
-}
-
-/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
- * Purpose  : disable interrupts from card
- */
-static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
-{
-       struct icside_state *state = ec->irq_data;
-
-       readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
-}
-
-static const expansioncard_ops_t icside_ops_arcin_v5 = {
-       .irqenable      = icside_irqenable_arcin_v5,
-       .irqdisable     = icside_irqdisable_arcin_v5,
-};
-
-
-/* ---------------- Version 6 PCB Support Functions --------------------- */
-/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
- * Purpose  : enable interrupts from card
- */
-static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
-{
-       struct icside_state *state = ec->irq_data;
-       void __iomem *base = state->irq_port;
-
-       state->enabled = 1;
-
-       switch (state->channel) {
-       case 0:
-               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
-               readb(base + ICS_ARCIN_V6_INTROFFSET_2);
-               break;
-       case 1:
-               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
-               readb(base + ICS_ARCIN_V6_INTROFFSET_1);
-               break;
-       }
-}
-
-/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
- * Purpose  : disable interrupts from card
- */
-static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
-{
-       struct icside_state *state = ec->irq_data;
-
-       state->enabled = 0;
-
-       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-}
-
-/* Prototype: icside_irqprobe(struct expansion_card *ec)
- * Purpose  : detect an active interrupt from card
- */
-static int icside_irqpending_arcin_v6(struct expansion_card *ec)
-{
-       struct icside_state *state = ec->irq_data;
-
-       return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
-              readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
-}
-
-static const expansioncard_ops_t icside_ops_arcin_v6 = {
-       .irqenable      = icside_irqenable_arcin_v6,
-       .irqdisable     = icside_irqdisable_arcin_v6,
-       .irqpending     = icside_irqpending_arcin_v6,
-};
-
-/*
- * Handle routing of interrupts.  This is called before
- * we write the command to the drive.
- */
-static void icside_maskproc(ide_drive_t *drive, int mask)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct expansion_card *ec = ECARD_DEV(hwif->dev);
-       struct icside_state *state = ecard_get_drvdata(ec);
-       unsigned long flags;
-
-       local_irq_save(flags);
-
-       state->channel = hwif->channel;
-
-       if (state->enabled && !mask) {
-               switch (hwif->channel) {
-               case 0:
-                       writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-                       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-                       break;
-               case 1:
-                       writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-                       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-                       break;
-               }
-       } else {
-               readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-               readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-       }
-
-       local_irq_restore(flags);
-}
-
-static const struct ide_port_ops icside_v6_no_dma_port_ops = {
-       .maskproc               = icside_maskproc,
-};
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
-/*
- * SG-DMA support.
- *
- * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
- * There is only one DMA controller per card, which means that only
- * one drive can be accessed at one time.  NOTE! We do not enforce that
- * here, but we rely on the main IDE driver spotting that both
- * interfaces use the same IRQ, which should guarantee this.
- */
-
-/*
- * Configure the IOMD to give the appropriate timings for the transfer
- * mode being requested.  We take the advice of the ATA standards, and
- * calculate the cycle time based on the transfer mode, and the EIDE
- * MW DMA specs that the drive provides in the IDENTIFY command.
- *
- * We have the following IOMD DMA modes to choose from:
- *
- *     Type    Active          Recovery        Cycle
- *     A       250 (250)       312 (550)       562 (800)
- *     B       187             250             437
- *     C       125 (125)       125 (375)       250 (500)
- *     D       62              125             187
- *
- * (figures in brackets are actual measured timings)
- *
- * However, we also need to take care of the read/write active and
- * recovery timings:
- *
- *                     Read    Write
- *     Mode    Active  -- Recovery --  Cycle   IOMD type
- *     MW0     215     50      215     480     A
- *     MW1     80      50      50      150     C
- *     MW2     70      25      25      120     C
- */
-static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
-{
-       int cycle_time, use_dma_info = 0;
-
-       switch (xfer_mode) {
-       case XFER_MW_DMA_2:
-               cycle_time = 250;
-               use_dma_info = 1;
-               break;
-
-       case XFER_MW_DMA_1:
-               cycle_time = 250;
-               use_dma_info = 1;
-               break;
-
-       case XFER_MW_DMA_0:
-               cycle_time = 480;
-               break;
-
-       case XFER_SW_DMA_2:
-       case XFER_SW_DMA_1:
-       case XFER_SW_DMA_0:
-               cycle_time = 480;
-               break;
-       }
-
-       /*
-        * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
-        * take care to note the values in the ID...
-        */
-       if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
-               cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
-
-       drive->drive_data = cycle_time;
-
-       printk("%s: %s selected (peak %dMB/s)\n", drive->name,
-               ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
-}
-
-static const struct ide_port_ops icside_v6_port_ops = {
-       .set_dma_mode           = icside_set_dma_mode,
-       .maskproc               = icside_maskproc,
-};
-
-static void icside_dma_host_set(ide_drive_t *drive, int on)
-{
-}
-
-static int icside_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct expansion_card *ec = ECARD_DEV(hwif->dev);
-
-       drive->waiting_for_dma = 0;
-
-       disable_dma(ec->dma);
-
-       /* Teardown mappings after DMA has completed. */
-       ide_destroy_dmatable(drive);
-
-       return get_dma_residue(ec->dma) != 0;
-}
-
-static void icside_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct expansion_card *ec = ECARD_DEV(hwif->dev);
-
-       /* We can not enable DMA on both channels simultaneously. */
-       BUG_ON(dma_channel_active(ec->dma));
-       enable_dma(ec->dma);
-}
-
-static int icside_dma_setup(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct expansion_card *ec = ECARD_DEV(hwif->dev);
-       struct icside_state *state = ecard_get_drvdata(ec);
-       struct request *rq = hwif->hwgroup->rq;
-       unsigned int dma_mode;
-
-       if (rq_data_dir(rq))
-               dma_mode = DMA_MODE_WRITE;
-       else
-               dma_mode = DMA_MODE_READ;
-
-       /*
-        * We can not enable DMA on both channels.
-        */
-       BUG_ON(dma_channel_active(ec->dma));
-
-       hwif->sg_nents = ide_build_sglist(drive, rq);
-
-       /*
-        * Ensure that we have the right interrupt routed.
-        */
-       icside_maskproc(drive, 0);
-
-       /*
-        * Route the DMA signals to the correct interface.
-        */
-       writeb(state->sel | hwif->channel, state->ioc_base);
-
-       /*
-        * Select the correct timing for this drive.
-        */
-       set_dma_speed(ec->dma, drive->drive_data);
-
-       /*
-        * Tell the DMA engine about the SG table and
-        * data direction.
-        */
-       set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
-       set_dma_mode(ec->dma, dma_mode);
-
-       drive->waiting_for_dma = 1;
-
-       return 0;
-}
-
-static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
-{
-       /* issue cmd to drive */
-       ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL);
-}
-
-static int icside_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct expansion_card *ec = ECARD_DEV(hwif->dev);
-       struct icside_state *state = ecard_get_drvdata(ec);
-
-       return readb(state->irq_port +
-                    (hwif->channel ?
-                       ICS_ARCIN_V6_INTRSTAT_2 :
-                       ICS_ARCIN_V6_INTRSTAT_1)) & 1;
-}
-
-static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
-       hwif->dmatable_cpu      = NULL;
-       hwif->dmatable_dma      = 0;
-
-       return 0;
-}
-
-static const struct ide_dma_ops icside_v6_dma_ops = {
-       .dma_host_set           = icside_dma_host_set,
-       .dma_setup              = icside_dma_setup,
-       .dma_exec_cmd           = icside_dma_exec_cmd,
-       .dma_start              = icside_dma_start,
-       .dma_end                = icside_dma_end,
-       .dma_test_irq           = icside_dma_test_irq,
-       .dma_timeout            = ide_dma_timeout,
-       .dma_lost_irq           = ide_dma_lost_irq,
-};
-#else
-#define icside_v6_dma_ops NULL
-#endif
-
-static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
-       return -EOPNOTSUPP;
-}
-
-static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
-                              struct cardinfo *info, struct expansion_card *ec)
-{
-       unsigned long port = (unsigned long)base + info->dataoffset;
-
-       hw->io_ports.data_addr   = port;
-       hw->io_ports.error_addr  = port + (1 << info->stepping);
-       hw->io_ports.nsect_addr  = port + (2 << info->stepping);
-       hw->io_ports.lbal_addr   = port + (3 << info->stepping);
-       hw->io_ports.lbam_addr   = port + (4 << info->stepping);
-       hw->io_ports.lbah_addr   = port + (5 << info->stepping);
-       hw->io_ports.device_addr = port + (6 << info->stepping);
-       hw->io_ports.status_addr = port + (7 << info->stepping);
-       hw->io_ports.ctl_addr    = (unsigned long)base + info->ctrloffset;
-
-       hw->irq = ec->irq;
-       hw->dev = &ec->dev;
-       hw->chipset = ide_acorn;
-}
-
-static int __init
-icside_register_v5(struct icside_state *state, struct expansion_card *ec)
-{
-       void __iomem *base;
-       struct ide_host *host;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-       int ret;
-
-       base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
-       if (!base)
-               return -ENOMEM;
-
-       state->irq_port = base;
-
-       ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;
-       ec->irqmask  = 1;
-
-       ecard_setirq(ec, &icside_ops_arcin_v5, state);
-
-       /*
-        * Be on the safe side - disable interrupts
-        */
-       icside_irqdisable_arcin_v5(ec, 0);
-
-       icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
-
-       host = ide_host_alloc(NULL, hws);
-       if (host == NULL)
-               return -ENODEV;
-
-       state->host = host;
-
-       ecard_set_drvdata(ec, state);
-
-       ret = ide_host_register(host, NULL, hws);
-       if (ret)
-               goto err_free;
-
-       return 0;
-err_free:
-       ide_host_free(host);
-       ecard_set_drvdata(ec, NULL);
-       return ret;
-}
-
-static const struct ide_port_info icside_v6_port_info __initdata = {
-       .init_dma               = icside_dma_off_init,
-       .port_ops               = &icside_v6_no_dma_port_ops,
-       .dma_ops                = &icside_v6_dma_ops,
-       .host_flags             = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
-       .mwdma_mask             = ATA_MWDMA2,
-       .swdma_mask             = ATA_SWDMA2,
-};
-
-static int __init
-icside_register_v6(struct icside_state *state, struct expansion_card *ec)
-{
-       void __iomem *ioc_base, *easi_base;
-       struct ide_host *host;
-       unsigned int sel = 0;
-       int ret;
-       hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
-       struct ide_port_info d = icside_v6_port_info;
-
-       ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
-       if (!ioc_base) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       easi_base = ioc_base;
-
-       if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
-               easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
-               if (!easi_base) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               /*
-                * Enable access to the EASI region.
-                */
-               sel = 1 << 5;
-       }
-
-       writeb(sel, ioc_base);
-
-       ecard_setirq(ec, &icside_ops_arcin_v6, state);
-
-       state->irq_port   = easi_base;
-       state->ioc_base   = ioc_base;
-       state->sel        = sel;
-
-       /*
-        * Be on the safe side - disable interrupts
-        */
-       icside_irqdisable_arcin_v6(ec, 0);
-
-       icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
-       icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
-
-       host = ide_host_alloc(&d, hws);
-       if (host == NULL)
-               return -ENODEV;
-
-       state->host = host;
-
-       ecard_set_drvdata(ec, state);
-
-       if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
-               d.init_dma = icside_dma_init;
-               d.port_ops = &icside_v6_port_ops;
-               d.dma_ops = NULL;
-       }
-
-       ret = ide_host_register(host, NULL, hws);
-       if (ret)
-               goto err_free;
-
-       return 0;
-err_free:
-       ide_host_free(host);
-       if (d.dma_ops)
-               free_dma(ec->dma);
-       ecard_set_drvdata(ec, NULL);
-out:
-       return ret;
-}
-
-static int __devinit
-icside_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-       struct icside_state *state;
-       void __iomem *idmem;
-       int ret;
-
-       ret = ecard_request_resources(ec);
-       if (ret)
-               goto out;
-
-       state = kzalloc(sizeof(struct icside_state), GFP_KERNEL);
-       if (!state) {
-               ret = -ENOMEM;
-               goto release;
-       }
-
-       state->type     = ICS_TYPE_NOTYPE;
-
-       idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
-       if (idmem) {
-               unsigned int type;
-
-               type = readb(idmem + ICS_IDENT_OFFSET) & 1;
-               type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
-               type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
-               type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
-               ecardm_iounmap(ec, idmem);
-
-               state->type = type;
-       }
-
-       switch (state->type) {
-       case ICS_TYPE_A3IN:
-               dev_warn(&ec->dev, "A3IN unsupported\n");
-               ret = -ENODEV;
-               break;
-
-       case ICS_TYPE_A3USER:
-               dev_warn(&ec->dev, "A3USER unsupported\n");
-               ret = -ENODEV;
-               break;
-
-       case ICS_TYPE_V5:
-               ret = icside_register_v5(state, ec);
-               break;
-
-       case ICS_TYPE_V6:
-               ret = icside_register_v6(state, ec);
-               break;
-
-       default:
-               dev_warn(&ec->dev, "unknown interface type\n");
-               ret = -ENODEV;
-               break;
-       }
-
-       if (ret == 0)
-               goto out;
-
-       kfree(state);
- release:
-       ecard_release_resources(ec);
- out:
-       return ret;
-}
-
-static void __devexit icside_remove(struct expansion_card *ec)
-{
-       struct icside_state *state = ecard_get_drvdata(ec);
-
-       switch (state->type) {
-       case ICS_TYPE_V5:
-               /* FIXME: tell IDE to stop using the interface */
-
-               /* Disable interrupts */
-               icside_irqdisable_arcin_v5(ec, 0);
-               break;
-
-       case ICS_TYPE_V6:
-               /* FIXME: tell IDE to stop using the interface */
-               if (ec->dma != NO_DMA)
-                       free_dma(ec->dma);
-
-               /* Disable interrupts */
-               icside_irqdisable_arcin_v6(ec, 0);
-
-               /* Reset the ROM pointer/EASI selection */
-               writeb(0, state->ioc_base);
-               break;
-       }
-
-       ecard_set_drvdata(ec, NULL);
-
-       kfree(state);
-       ecard_release_resources(ec);
-}
-
-static void icside_shutdown(struct expansion_card *ec)
-{
-       struct icside_state *state = ecard_get_drvdata(ec);
-       unsigned long flags;
-
-       /*
-        * Disable interrupts from this card.  We need to do
-        * this before disabling EASI since we may be accessing
-        * this register via that region.
-        */
-       local_irq_save(flags);
-       ec->ops->irqdisable(ec, 0);
-       local_irq_restore(flags);
-
-       /*
-        * Reset the ROM pointer so that we can read the ROM
-        * after a soft reboot.  This also disables access to
-        * the IDE taskfile via the EASI region.
-        */
-       if (state->ioc_base)
-               writeb(0, state->ioc_base);
-}
-
-static const struct ecard_id icside_ids[] = {
-       { MANU_ICS,  PROD_ICS_IDE  },
-       { MANU_ICS2, PROD_ICS2_IDE },
-       { 0xffff, 0xffff }
-};
-
-static struct ecard_driver icside_driver = {
-       .probe          = icside_probe,
-       .remove         = __devexit_p(icside_remove),
-       .shutdown       = icside_shutdown,
-       .id_table       = icside_ids,
-       .drv = {
-               .name   = "icside",
-       },
-};
-
-static int __init icside_init(void)
-{
-       return ecard_register_driver(&icside_driver);
-}
-
-static void __exit icside_exit(void);
-{
-       ecard_unregister_driver(&icside_driver);
-}
-
-MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ICS IDE driver");
-
-module_init(icside_init);
-module_exit(icside_exit);
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
deleted file mode 100644 (file)
index f728f29..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * ARM default IDE host driver
- *
- * Copyright (C) 2004 Bartlomiej Zolnierkiewicz
- * Based on code by: Russell King, Ian Molton and Alexander Schulz.
- *
- * May be copied or modified under the terms of the GNU General Public License.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/irq.h>
-
-#define DRV_NAME "ide_arm"
-
-#ifdef CONFIG_ARCH_CLPS7500
-# include <mach/hardware.h>
-#
-# define IDE_ARM_IO    (ISASLOT_IO + 0x1f0)
-# define IDE_ARM_IRQ   IRQ_ISA_14
-#else
-# define IDE_ARM_IO    0x1f0
-# define IDE_ARM_IRQ   IRQ_HARDDISK
-#endif
-
-static int __init ide_arm_init(void)
-{
-       unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-       if (!request_region(base, 8, DRV_NAME)) {
-               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
-                               DRV_NAME, base, base + 7);
-               return -EBUSY;
-       }
-
-       if (!request_region(ctl, 1, DRV_NAME)) {
-               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
-                               DRV_NAME, ctl);
-               release_region(base, 8);
-               return -EBUSY;
-       }
-
-       memset(&hw, 0, sizeof(hw));
-       ide_std_init_ports(&hw, base, ctl);
-       hw.irq = IDE_ARM_IRQ;
-       hw.chipset = ide_generic;
-
-       return ide_host_add(NULL, hws, NULL);
-}
-
-module_init(ide_arm_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
deleted file mode 100644 (file)
index 122ed3c..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Palmchip bk3710 IDE controller
- *
- * Copyright (C) 2006 Texas Instruments.
- * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ----------------------------------------------------------------------------
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/ide.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-/* Offset of the primary interface registers */
-#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
-
-/* Primary Control Offset */
-#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
-
-/*
- * PalmChip 3710 IDE Controller UDMA timing structure Definition
- */
-struct palm_bk3710_udmatiming {
-       unsigned int rptime;    /* Ready to pause time  */
-       unsigned int cycletime; /* Cycle Time           */
-};
-
-#define BK3710_BMICP           0x00
-#define BK3710_BMISP           0x02
-#define BK3710_BMIDTP          0x04
-#define BK3710_BMICS           0x08
-#define BK3710_BMISS           0x0A
-#define BK3710_BMIDTS          0x0C
-#define BK3710_IDETIMP         0x40
-#define BK3710_IDETIMS         0x42
-#define BK3710_SIDETIM         0x44
-#define BK3710_SLEWCTL         0x45
-#define BK3710_IDESTATUS       0x47
-#define BK3710_UDMACTL         0x48
-#define BK3710_UDMATIM         0x4A
-#define BK3710_MISCCTL         0x50
-#define BK3710_REGSTB          0x54
-#define BK3710_REGRCVR         0x58
-#define BK3710_DATSTB          0x5C
-#define BK3710_DATRCVR         0x60
-#define BK3710_DMASTB          0x64
-#define BK3710_DMARCVR         0x68
-#define BK3710_UDMASTB         0x6C
-#define BK3710_UDMATRP         0x70
-#define BK3710_UDMAENV         0x74
-#define BK3710_IORDYTMP                0x78
-#define BK3710_IORDYTMS                0x7C
-
-static unsigned ideclk_period; /* in nanoseconds */
-
-static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
-       {160, 240},             /* UDMA Mode 0 */
-       {125, 160},             /* UDMA Mode 1 */
-       {100, 120},             /* UDMA Mode 2 */
-       {100, 90},              /* UDMA Mode 3 */
-       {100, 60},              /* UDMA Mode 4 */
-       {85,  40},              /* UDMA Mode 5 */
-};
-
-static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
-                                   unsigned int mode)
-{
-       u8 tenv, trp, t0;
-       u32 val32;
-       u16 val16;
-
-       /* DMA Data Setup */
-       t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
-                         ideclk_period) - 1;
-       tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
-       trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
-                          ideclk_period) - 1;
-
-       /* udmatim Register */
-       val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
-       val16 |= (mode << (dev ? 4 : 0));
-       writew(val16, base + BK3710_UDMATIM);
-
-       /* udmastb Ultra DMA Access Strobe Width */
-       val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
-       val32 |= (t0 << (dev ? 8 : 0));
-       writel(val32, base + BK3710_UDMASTB);
-
-       /* udmatrp Ultra DMA Ready to Pause Time */
-       val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
-       val32 |= (trp << (dev ? 8 : 0));
-       writel(val32, base + BK3710_UDMATRP);
-
-       /* udmaenv Ultra DMA envelop Time */
-       val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
-       val32 |= (tenv << (dev ? 8 : 0));
-       writel(val32, base + BK3710_UDMAENV);
-
-       /* Enable UDMA for Device */
-       val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
-       writew(val16, base + BK3710_UDMACTL);
-}
-
-static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
-                                  unsigned short min_cycle,
-                                  unsigned int mode)
-{
-       u8 td, tkw, t0;
-       u32 val32;
-       u16 val16;
-       struct ide_timing *t;
-       int cycletime;
-
-       t = ide_timing_find_mode(mode);
-       cycletime = max_t(int, t->cycle, min_cycle);
-
-       /* DMA Data Setup */
-       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
-       td = DIV_ROUND_UP(t->active, ideclk_period);
-       tkw = t0 - td - 1;
-       td -= 1;
-
-       val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
-       val32 |= (td << (dev ? 8 : 0));
-       writel(val32, base + BK3710_DMASTB);
-
-       val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
-       val32 |= (tkw << (dev ? 8 : 0));
-       writel(val32, base + BK3710_DMARCVR);
-
-       /* Disable UDMA for Device */
-       val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
-       writew(val16, base + BK3710_UDMACTL);
-}
-
-static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
-                                  unsigned int dev, unsigned int cycletime,
-                                  unsigned int mode)
-{
-       u8 t2, t2i, t0;
-       u32 val32;
-       struct ide_timing *t;
-
-       /* PIO Data Setup */
-       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
-       t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
-                         ideclk_period);
-
-       t2i = t0 - t2 - 1;
-       t2 -= 1;
-
-       val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
-       val32 |= (t2 << (dev ? 8 : 0));
-       writel(val32, base + BK3710_DATSTB);
-
-       val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
-       val32 |= (t2i << (dev ? 8 : 0));
-       writel(val32, base + BK3710_DATRCVR);
-
-       if (mate) {
-               u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
-
-               if (mode2 < mode)
-                       mode = mode2;
-       }
-
-       /* TASKFILE Setup */
-       t = ide_timing_find_mode(XFER_PIO_0 + mode);
-       t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
-       t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
-
-       t2i = t0 - t2 - 1;
-       t2 -= 1;
-
-       val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
-       val32 |= (t2 << (dev ? 8 : 0));
-       writel(val32, base + BK3710_REGSTB);
-
-       val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
-       val32 |= (t2i << (dev ? 8 : 0));
-       writel(val32, base + BK3710_REGRCVR);
-}
-
-static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
-{
-       int is_slave = drive->dn & 1;
-       void __iomem *base = (void *)drive->hwif->dma_base;
-
-       if (xferspeed >= XFER_UDMA_0) {
-               palm_bk3710_setudmamode(base, is_slave,
-                                       xferspeed - XFER_UDMA_0);
-       } else {
-               palm_bk3710_setdmamode(base, is_slave,
-                                      drive->id[ATA_ID_EIDE_DMA_MIN],
-                                      xferspeed);
-       }
-}
-
-static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
-{
-       unsigned int cycle_time;
-       int is_slave = drive->dn & 1;
-       ide_drive_t *mate;
-       void __iomem *base = (void *)drive->hwif->dma_base;
-
-       /*
-        * Obtain the drive PIO data for tuning the Palm Chip registers
-        */
-       cycle_time = ide_pio_cycle_time(drive, pio);
-       mate = ide_get_pair_dev(drive);
-       palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
-}
-
-static void __devinit palm_bk3710_chipinit(void __iomem *base)
-{
-       /*
-        * enable the reset_en of ATA controller so that when ata signals
-        * are brought out, by writing into device config. at that
-        * time por_n signal should not be 'Z' and have a stable value.
-        */
-       writel(0x0300, base + BK3710_MISCCTL);
-
-       /* wait for some time and deassert the reset of ATA Device. */
-       mdelay(100);
-
-       /* Deassert the Reset */
-       writel(0x0200, base + BK3710_MISCCTL);
-
-       /*
-        * Program the IDETIMP Register Value based on the following assumptions
-        *
-        * (ATA_IDETIMP_IDEEN           , ENABLE ) |
-        * (ATA_IDETIMP_SLVTIMEN        , DISABLE) |
-        * (ATA_IDETIMP_RDYSMPL         , 70NS)    |
-        * (ATA_IDETIMP_RDYRCVRY        , 50NS)    |
-        * (ATA_IDETIMP_DMAFTIM1        , PIOCOMP) |
-        * (ATA_IDETIMP_PREPOST1        , DISABLE) |
-        * (ATA_IDETIMP_RDYSEN1         , DISABLE) |
-        * (ATA_IDETIMP_PIOFTIM1        , DISABLE) |
-        * (ATA_IDETIMP_DMAFTIM0        , PIOCOMP) |
-        * (ATA_IDETIMP_PREPOST0        , DISABLE) |
-        * (ATA_IDETIMP_RDYSEN0         , DISABLE) |
-        * (ATA_IDETIMP_PIOFTIM0        , DISABLE)
-        */
-       writew(0xB388, base + BK3710_IDETIMP);
-
-       /*
-        * Configure  SIDETIM  Register
-        * (ATA_SIDETIM_RDYSMPS1        ,120NS ) |
-        * (ATA_SIDETIM_RDYRCYS1        ,120NS )
-        */
-       writeb(0, base + BK3710_SIDETIM);
-
-       /*
-        * UDMACTL Ultra-ATA DMA Control
-        * (ATA_UDMACTL_UDMAP1  , 0 ) |
-        * (ATA_UDMACTL_UDMAP0  , 0 )
-        *
-        */
-       writew(0, base + BK3710_UDMACTL);
-
-       /*
-        * MISCCTL Miscellaneous Conrol Register
-        * (ATA_MISCCTL_RSTMODEP        , 1) |
-        * (ATA_MISCCTL_RESETP          , 0) |
-        * (ATA_MISCCTL_TIMORIDE        , 1)
-        */
-       writel(0x201, base + BK3710_MISCCTL);
-
-       /*
-        * IORDYTMP IORDY Timer for Primary Register
-        * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
-        */
-       writel(0xFFFF, base + BK3710_IORDYTMP);
-
-       /*
-        * Configure BMISP Register
-        * (ATA_BMISP_DMAEN1    , DISABLE )     |
-        * (ATA_BMISP_DMAEN0    , DISABLE )     |
-        * (ATA_BMISP_IORDYINT  , CLEAR)        |
-        * (ATA_BMISP_INTRSTAT  , CLEAR)        |
-        * (ATA_BMISP_DMAERROR  , CLEAR)
-        */
-       writew(0, base + BK3710_BMISP);
-
-       palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
-       palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
-}
-
-static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif)
-{
-       return ATA_CBL_PATA80;
-}
-
-static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
-                                         const struct ide_port_info *d)
-{
-       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
-
-       if (ide_allocate_dma_engine(hwif))
-               return -1;
-
-       hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
-
-       hwif->dma_ops = &sff_dma_ops;
-
-       return 0;
-}
-
-static const struct ide_port_ops palm_bk3710_ports_ops = {
-       .set_pio_mode           = palm_bk3710_set_pio_mode,
-       .set_dma_mode           = palm_bk3710_set_dma_mode,
-       .cable_detect           = palm_bk3710_cable_detect,
-};
-
-static struct ide_port_info __devinitdata palm_bk3710_port_info = {
-       .init_dma               = palm_bk3710_init_dma,
-       .port_ops               = &palm_bk3710_ports_ops,
-       .host_flags             = IDE_HFLAG_MMIO,
-       .pio_mask               = ATA_PIO4,
-       .mwdma_mask             = ATA_MWDMA2,
-};
-
-static int __init palm_bk3710_probe(struct platform_device *pdev)
-{
-       struct clk *clk;
-       struct resource *mem, *irq;
-       unsigned long base, rate;
-       int i, rc;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-       clk = clk_get(&pdev->dev, "IDECLK");
-       if (IS_ERR(clk))
-               return -ENODEV;
-
-       clk_enable(clk);
-       rate = clk_get_rate(clk);
-       ideclk_period = 1000000000UL / rate;
-
-       /* Register the IDE interface with Linux ATA Interface */
-       memset(&hw, 0, sizeof(hw));
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (mem == NULL) {
-               printk(KERN_ERR "failed to get memory region resource\n");
-               return -ENODEV;
-       }
-
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (irq == NULL) {
-               printk(KERN_ERR "failed to get IRQ resource\n");
-               return -ENODEV;
-       }
-
-       if (request_mem_region(mem->start, mem->end - mem->start + 1,
-                              "palm_bk3710") == NULL) {
-               printk(KERN_ERR "failed to request memory region\n");
-               return -EBUSY;
-       }
-
-       base = IO_ADDRESS(mem->start);
-
-       /* Configure the Palm Chip controller */
-       palm_bk3710_chipinit((void __iomem *)base);
-
-       for (i = 0; i < IDE_NR_PORTS - 2; i++)
-               hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
-       hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
-       hw.irq = irq->start;
-       hw.dev = &pdev->dev;
-       hw.chipset = ide_palm3710;
-
-       palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
-                                                            ATA_UDMA5;
-
-       rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
-       if (rc)
-               goto out;
-
-       return 0;
-out:
-       printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
-       return rc;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:palm_bk3710");
-
-static struct platform_driver platform_bk_driver = {
-       .driver = {
-               .name = "palm_bk3710",
-               .owner = THIS_MODULE,
-       },
-};
-
-static int __init palm_bk3710_init(void)
-{
-       return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe);
-}
-
-module_init(palm_bk3710_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
deleted file mode 100644 (file)
index 78d27d9..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 1996-2002 Russell King.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/ecard.h>
-
-static struct const ide_port_info rapide_port_info = {
-       .host_flags             = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
-};
-
-static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
-                              void __iomem *ctrl, unsigned int sz, int irq)
-{
-       unsigned long port = (unsigned long)base;
-       int i;
-
-       for (i = 0; i <= 7; i++) {
-               hw->io_ports_array[i] = port;
-               port += sz;
-       }
-       hw->io_ports.ctl_addr = (unsigned long)ctrl;
-       hw->irq = irq;
-}
-
-static int __devinit
-rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-       void __iomem *base;
-       struct ide_host *host;
-       int ret;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-       ret = ecard_request_resources(ec);
-       if (ret)
-               goto out;
-
-       base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
-       if (!base) {
-               ret = -ENOMEM;
-               goto release;
-       }
-
-       memset(&hw, 0, sizeof(hw));
-       rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
-       hw.chipset = ide_generic;
-       hw.dev = &ec->dev;
-
-       ret = ide_host_add(&rapide_port_info, hws, &host);
-       if (ret)
-               goto release;
-
-       ecard_set_drvdata(ec, host);
-       goto out;
-
- release:
-       ecard_release_resources(ec);
- out:
-       return ret;
-}
-
-static void __devexit rapide_remove(struct expansion_card *ec)
-{
-       struct ide_host *host = ecard_get_drvdata(ec);
-
-       ecard_set_drvdata(ec, NULL);
-
-       ide_host_remove(host);
-
-       ecard_release_resources(ec);
-}
-
-static struct ecard_id rapide_ids[] = {
-       { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 },
-       { 0xffff, 0xffff }
-};
-
-static struct ecard_driver rapide_driver = {
-       .probe          = rapide_probe,
-       .remove         = __devexit_p(rapide_remove),
-       .id_table       = rapide_ids,
-       .drv = {
-               .name   = "rapide",
-       },
-};
-
-static int __init rapide_init(void)
-{
-       return ecard_register_driver(&rapide_driver);
-}
-
-static void __exit rapide_exit(void)
-{
-       ecard_unregister_driver(&rapide_driver);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Yellowstone RAPIDE driver");
-
-module_init(rapide_init);
-module_exit(rapide_exit);
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
new file mode 100644 (file)
index 0000000..b2735d2
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  Copyright (C) 2003 ATI Inc. <hyu@ati.com>
+ *  Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "atiixp"
+
+#define ATIIXP_IDE_PIO_TIMING          0x40
+#define ATIIXP_IDE_MDMA_TIMING         0x44
+#define ATIIXP_IDE_PIO_CONTROL         0x48
+#define ATIIXP_IDE_PIO_MODE            0x4a
+#define ATIIXP_IDE_UDMA_CONTROL                0x54
+#define ATIIXP_IDE_UDMA_MODE           0x56
+
+typedef struct {
+       u8 command_width;
+       u8 recover_width;
+} atiixp_ide_timing;
+
+static atiixp_ide_timing pio_timing[] = {
+       { 0x05, 0x0d },
+       { 0x04, 0x07 },
+       { 0x03, 0x04 },
+       { 0x02, 0x02 },
+       { 0x02, 0x00 },
+};
+
+static atiixp_ide_timing mdma_timing[] = {
+       { 0x07, 0x07 },
+       { 0x02, 0x01 },
+       { 0x02, 0x00 },
+};
+
+static DEFINE_SPINLOCK(atiixp_lock);
+
+/**
+ *     atiixp_set_pio_mode     -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Set the interface PIO mode.
+ */
+
+static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       unsigned long flags;
+       int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+       u32 pio_timing_data;
+       u16 pio_mode_data;
+
+       spin_lock_irqsave(&atiixp_lock, flags);
+
+       pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
+       pio_mode_data &= ~(0x07 << (drive->dn * 4));
+       pio_mode_data |= (pio << (drive->dn * 4));
+       pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
+
+       pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+       pio_timing_data &= ~(0xff << timing_shift);
+       pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) |
+                (pio_timing[pio].command_width << (timing_shift + 4));
+       pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+
+       spin_unlock_irqrestore(&atiixp_lock, flags);
+}
+
+/**
+ *     atiixp_set_dma_mode     -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Set a ATIIXP host controller to the desired DMA mode.  This involves
+ *     programming the right timing data into the PCI configuration space.
+ */
+
+static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       unsigned long flags;
+       int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+       u32 tmp32;
+       u16 tmp16;
+       u16 udma_ctl = 0;
+
+       spin_lock_irqsave(&atiixp_lock, flags);
+
+       pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl);
+
+       if (speed >= XFER_UDMA_0) {
+               pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
+               tmp16 &= ~(0x07 << (drive->dn * 4));
+               tmp16 |= ((speed & 0x07) << (drive->dn * 4));
+               pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
+
+               udma_ctl |= (1 << drive->dn);
+       } else if (speed >= XFER_MW_DMA_0) {
+               u8 i = speed & 0x03;
+
+               pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
+               tmp32 &= ~(0xff << timing_shift);
+               tmp32 |= (mdma_timing[i].recover_width << timing_shift) |
+                        (mdma_timing[i].command_width << (timing_shift + 4));
+               pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
+
+               udma_ctl &= ~(1 << drive->dn);
+       }
+
+       pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl);
+
+       spin_unlock_irqrestore(&atiixp_lock, flags);
+}
+
+static u8 atiixp_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       u8 udma_mode = 0, ch = hwif->channel;
+
+       pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
+       if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
+               return ATA_CBL_PATA80;
+       else
+               return ATA_CBL_PATA40;
+}
+
+static const struct ide_port_ops atiixp_port_ops = {
+       .set_pio_mode           = atiixp_set_pio_mode,
+       .set_dma_mode           = atiixp_set_dma_mode,
+       .cable_detect           = atiixp_cable_detect,
+};
+
+static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+       {       /* 0: IXP200/300/400/700 */
+               .name           = DRV_NAME,
+               .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+               .port_ops       = &atiixp_port_ops,
+               .host_flags     = IDE_HFLAG_LEGACY_IRQS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       },
+       {       /* 1: IXP600 */
+               .name           = DRV_NAME,
+               .enablebits     = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
+               .port_ops       = &atiixp_port_ops,
+               .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       },
+};
+
+/**
+ *     atiixp_init_one -       called when a ATIIXP is found
+ *     @dev: the atiixp device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+
+static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
+}
+
+static const struct pci_device_id atiixp_pci_tbl[] = {
+       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), 0 },
+       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), 0 },
+       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 },
+       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 },
+       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
+
+static struct pci_driver atiixp_pci_driver = {
+       .name           = "ATIIXP_IDE",
+       .id_table       = atiixp_pci_tbl,
+       .probe          = atiixp_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init atiixp_ide_init(void)
+{
+       return ide_pci_register_driver(&atiixp_pci_driver);
+}
+
+static void __exit atiixp_ide_exit(void)
+{
+       pci_unregister_driver(&atiixp_pci_driver);
+}
+
+module_init(atiixp_ide_init);
+module_exit(atiixp_ide_exit);
+
+MODULE_AUTHOR("HUI YU");
+MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
new file mode 100644 (file)
index 0000000..0ec8fd1
--- /dev/null
@@ -0,0 +1,642 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
+ *
+ * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
+ *       Interface and Linux Device Driver" Application Note.
+ */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/scatterlist.h>
+
+#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1xxx_ide.h>
+
+#define DRV_NAME       "au1200-ide"
+#define DRV_AUTHOR     "Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>"
+
+/* enable the burstmode in the dbdma */
+#define IDE_AU1XXX_BURSTMODE   1
+
+static _auide_hwif auide_hwif;
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+
+void auide_insw(unsigned long port, void *addr, u32 count)
+{
+       _auide_hwif *ahwif = &auide_hwif;
+       chan_tab_t *ctp;
+       au1x_ddma_desc_t *dp;
+
+       if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, 
+                          DDMA_FLAGS_NOIE)) {
+               printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
+               return;
+       }
+       ctp = *((chan_tab_t **)ahwif->rx_chan);
+       dp = ctp->cur_ptr;
+       while (dp->dscr_cmd0 & DSCR_CMD0_V)
+               ;
+       ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
+}
+
+void auide_outsw(unsigned long port, void *addr, u32 count)
+{
+       _auide_hwif *ahwif = &auide_hwif;
+       chan_tab_t *ctp;
+       au1x_ddma_desc_t *dp;
+
+       if(!put_source_flags(ahwif->tx_chan, (void*)addr,
+                            count << 1, DDMA_FLAGS_NOIE)) {
+               printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
+               return;
+       }
+       ctp = *((chan_tab_t **)ahwif->tx_chan);
+       dp = ctp->cur_ptr;
+       while (dp->dscr_cmd0 & DSCR_CMD0_V)
+               ;
+       ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
+}
+
+static void au1xxx_input_data(ide_drive_t *drive, struct request *rq,
+                             void *buf, unsigned int len)
+{
+       auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
+}
+
+static void au1xxx_output_data(ide_drive_t *drive, struct request *rq,
+                              void *buf, unsigned int len)
+{
+       auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
+}
+#endif
+
+static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
+
+       /* set pio mode! */
+       switch(pio) {
+       case 0:
+               mem_sttime = SBC_IDE_TIMING(PIO0);
+
+               /* set configuration for RCS2# */
+               mem_stcfg |= TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS;
+               break;
+
+       case 1:
+               mem_sttime = SBC_IDE_TIMING(PIO1);
+
+               /* set configuration for RCS2# */
+               mem_stcfg |= TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS;
+               break;
+
+       case 2:
+               mem_sttime = SBC_IDE_TIMING(PIO2);
+
+               /* set configuration for RCS2# */
+               mem_stcfg &= ~TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS;
+               break;
+
+       case 3:
+               mem_sttime = SBC_IDE_TIMING(PIO3);
+
+               /* set configuration for RCS2# */
+               mem_stcfg &= ~TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS;
+
+               break;
+
+       case 4:
+               mem_sttime = SBC_IDE_TIMING(PIO4);
+
+               /* set configuration for RCS2# */
+               mem_stcfg &= ~TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS;
+               break;
+       }
+
+       au_writel(mem_sttime,MEM_STTIME2);
+       au_writel(mem_stcfg,MEM_STCFG2);
+}
+
+static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
+
+       switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+       case XFER_MW_DMA_2:
+               mem_sttime = SBC_IDE_TIMING(MDMA2);
+
+               /* set configuration for RCS2# */
+               mem_stcfg &= ~TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
+
+               break;
+       case XFER_MW_DMA_1:
+               mem_sttime = SBC_IDE_TIMING(MDMA1);
+
+               /* set configuration for RCS2# */
+               mem_stcfg &= ~TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
+
+               break;
+       case XFER_MW_DMA_0:
+               mem_sttime = SBC_IDE_TIMING(MDMA0);
+
+               /* set configuration for RCS2# */
+               mem_stcfg |= TS_MASK;
+               mem_stcfg &= ~TCSOE_MASK;
+               mem_stcfg &= ~TOECS_MASK;
+               mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
+
+               break;
+#endif
+       }
+
+       au_writel(mem_sttime,MEM_STTIME2);
+       au_writel(mem_stcfg,MEM_STCFG2);
+}
+
+/*
+ * Multi-Word DMA + DbDMA functions
+ */
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+static int auide_build_dmatable(ide_drive_t *drive)
+{
+       int i, iswrite, count = 0;
+       ide_hwif_t *hwif = HWIF(drive);
+       struct request *rq = HWGROUP(drive)->rq;
+       _auide_hwif *ahwif = &auide_hwif;
+       struct scatterlist *sg;
+
+       iswrite = (rq_data_dir(rq) == WRITE);
+       /* Save for interrupt context */
+       ahwif->drive = drive;
+
+       hwif->sg_nents = i = ide_build_sglist(drive, rq);
+
+       if (!i)
+               return 0;
+
+       /* fill the descriptors */
+       sg = hwif->sg_table;
+       while (i && sg_dma_len(sg)) {
+               u32 cur_addr;
+               u32 cur_len;
+
+               cur_addr = sg_dma_address(sg);
+               cur_len = sg_dma_len(sg);
+
+               while (cur_len) {
+                       u32 flags = DDMA_FLAGS_NOIE;
+                       unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
+
+                       if (++count >= PRD_ENTRIES) {
+                               printk(KERN_WARNING "%s: DMA table too small\n",
+                                      drive->name);
+                               goto use_pio_instead;
+                       }
+
+                       /* Lets enable intr for the last descriptor only */
+                       if (1==i)
+                               flags = DDMA_FLAGS_IE;
+                       else
+                               flags = DDMA_FLAGS_NOIE;
+
+                       if (iswrite) {
+                               if(!put_source_flags(ahwif->tx_chan, 
+                                                    (void*) sg_virt(sg),
+                                                    tc, flags)) { 
+                                       printk(KERN_ERR "%s failed %d\n", 
+                                              __func__, __LINE__);
+                               }
+                       } else 
+                       {
+                               if(!put_dest_flags(ahwif->rx_chan, 
+                                                  (void*) sg_virt(sg),
+                                                  tc, flags)) { 
+                                       printk(KERN_ERR "%s failed %d\n", 
+                                              __func__, __LINE__);
+                               }
+                       }
+
+                       cur_addr += tc;
+                       cur_len -= tc;
+               }
+               sg = sg_next(sg);
+               i--;
+       }
+
+       if (count)
+               return 1;
+
+ use_pio_instead:
+       ide_destroy_dmatable(drive);
+
+       return 0; /* revert to PIO for this request */
+}
+
+static int auide_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+
+       if (hwif->sg_nents) {
+               ide_destroy_dmatable(drive);
+               hwif->sg_nents = 0;
+       }
+
+       return 0;
+}
+
+static void auide_dma_start(ide_drive_t *drive )
+{
+}
+
+
+static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+       /* issue cmd to drive */
+       ide_execute_command(drive, command, &ide_dma_intr,
+                           (2*WAIT_CMD), NULL);
+}
+
+static int auide_dma_setup(ide_drive_t *drive)
+{              
+       struct request *rq = HWGROUP(drive)->rq;
+
+       if (!auide_build_dmatable(drive)) {
+               ide_map_sg(drive, rq);
+               return 1;
+       }
+
+       drive->waiting_for_dma = 1;
+       return 0;
+}
+
+static int auide_dma_test_irq(ide_drive_t *drive)
+{
+       /* If dbdma didn't execute the STOP command yet, the
+        * active bit is still set
+        */
+       drive->waiting_for_dma++;
+       if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
+               printk(KERN_WARNING "%s: timeout waiting for ddma to \
+                                     complete\n", drive->name);
+               return 1;
+       }
+       udelay(10);
+       return 0;
+}
+
+static void auide_dma_host_set(ide_drive_t *drive, int on)
+{
+}
+
+static void auide_ddma_tx_callback(int irq, void *param)
+{
+       _auide_hwif *ahwif = (_auide_hwif*)param;
+       ahwif->drive->waiting_for_dma = 0;
+}
+
+static void auide_ddma_rx_callback(int irq, void *param)
+{
+       _auide_hwif *ahwif = (_auide_hwif*)param;
+       ahwif->drive->waiting_for_dma = 0;
+}
+
+#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+
+static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags)
+{
+       dev->dev_id          = dev_id;
+       dev->dev_physaddr    = (u32)IDE_PHYS_ADDR;
+       dev->dev_intlevel    = 0;
+       dev->dev_intpolarity = 0;
+       dev->dev_tsize       = tsize;
+       dev->dev_devwidth    = devwidth;
+       dev->dev_flags       = flags;
+}
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+static const struct ide_dma_ops au1xxx_dma_ops = {
+       .dma_host_set           = auide_dma_host_set,
+       .dma_setup              = auide_dma_setup,
+       .dma_exec_cmd           = auide_dma_exec_cmd,
+       .dma_start              = auide_dma_start,
+       .dma_end                = auide_dma_end,
+       .dma_test_irq           = auide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       _auide_hwif *auide = &auide_hwif;
+       dbdev_tab_t source_dev_tab, target_dev_tab;
+       u32 dev_id, tsize, devwidth, flags;
+
+       dev_id   = IDE_DDMA_REQ;
+
+       tsize    =  8; /*  1 */
+       devwidth = 32; /* 16 */
+
+#ifdef IDE_AU1XXX_BURSTMODE 
+       flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE;
+#else
+       flags = DEV_FLAGS_SYNC;
+#endif
+
+       /* setup dev_tab for tx channel */
+       auide_init_dbdma_dev( &source_dev_tab,
+                             dev_id,
+                             tsize, devwidth, DEV_FLAGS_OUT | flags);
+       auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+
+       auide_init_dbdma_dev( &source_dev_tab,
+                             dev_id,
+                             tsize, devwidth, DEV_FLAGS_IN | flags);
+       auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+       
+       /* We also need to add a target device for the DMA */
+       auide_init_dbdma_dev( &target_dev_tab,
+                             (u32)DSCR_CMD0_ALWAYS,
+                             tsize, devwidth, DEV_FLAGS_ANYUSE);
+       auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); 
+       /* Get a channel for TX */
+       auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id,
+                                                auide->tx_dev_id,
+                                                auide_ddma_tx_callback,
+                                                (void*)auide);
+       /* Get a channel for RX */
+       auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
+                                                auide->target_dev_id,
+                                                auide_ddma_rx_callback,
+                                                (void*)auide);
+
+       auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan,
+                                                            NUM_DESCRIPTORS);
+       auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
+                                                            NUM_DESCRIPTORS);
+
+       /* FIXME: check return value */
+       (void)ide_allocate_dma_engine(hwif);
+       
+       au1xxx_dbdma_start( auide->tx_chan );
+       au1xxx_dbdma_start( auide->rx_chan );
+       return 0;
+} 
+#else
+static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       _auide_hwif *auide = &auide_hwif;
+       dbdev_tab_t source_dev_tab;
+       int flags;
+
+#ifdef IDE_AU1XXX_BURSTMODE 
+       flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE;
+#else
+       flags = DEV_FLAGS_SYNC;
+#endif
+
+       /* setup dev_tab for tx channel */
+       auide_init_dbdma_dev( &source_dev_tab,
+                             (u32)DSCR_CMD0_ALWAYS,
+                             8, 32, DEV_FLAGS_OUT | flags);
+       auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+
+       auide_init_dbdma_dev( &source_dev_tab,
+                             (u32)DSCR_CMD0_ALWAYS,
+                             8, 32, DEV_FLAGS_IN | flags);
+       auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+       
+       /* Get a channel for TX */
+       auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
+                                                auide->tx_dev_id,
+                                                NULL,
+                                                (void*)auide);
+       /* Get a channel for RX */
+       auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
+                                                DSCR_CMD0_ALWAYS,
+                                                NULL,
+                                                (void*)auide);
+       auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan,
+                                                            NUM_DESCRIPTORS);
+       auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
+                                                            NUM_DESCRIPTORS);
+       au1xxx_dbdma_start( auide->tx_chan );
+       au1xxx_dbdma_start( auide->rx_chan );
+       
+       return 0;
+}
+#endif
+
+static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
+{
+       int i;
+       unsigned long *ata_regs = hw->io_ports_array;
+
+       /* FIXME? */
+       for (i = 0; i < 8; i++)
+               *ata_regs++ = ahwif->regbase + (i << IDE_REG_SHIFT);
+
+       /* set the Alternative Status register */
+       *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
+}
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+static const struct ide_tp_ops au1xxx_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = au1xxx_input_data,
+       .output_data            = au1xxx_output_data,
+};
+#endif
+
+static const struct ide_port_ops au1xxx_port_ops = {
+       .set_pio_mode           = au1xxx_set_pio_mode,
+       .set_dma_mode           = auide_set_dma_mode,
+};
+
+static const struct ide_port_info au1xxx_port_info = {
+       .init_dma               = auide_ddma_init,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+       .tp_ops                 = &au1xxx_tp_ops,
+#endif
+       .port_ops               = &au1xxx_port_ops,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+       .dma_ops                = &au1xxx_dma_ops,
+#endif
+       .host_flags             = IDE_HFLAG_POST_SET_MODE |
+                                 IDE_HFLAG_NO_IO_32BIT |
+                                 IDE_HFLAG_UNMASK_IRQS,
+       .pio_mask               = ATA_PIO4,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+       .mwdma_mask             = ATA_MWDMA2,
+#endif
+};
+
+static int au_ide_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       _auide_hwif *ahwif = &auide_hwif;
+       struct resource *res;
+       struct ide_host *host;
+       int ret = 0;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+       char *mode = "MWDMA2";
+#elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+       char *mode = "PIO+DDMA(offload)";
+#endif
+
+       memset(&auide_hwif, 0, sizeof(_auide_hwif));
+       ahwif->irq = platform_get_irq(pdev, 0);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (res == NULL) {
+               pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id);
+               ret = -ENODEV;
+               goto out;
+       }
+       if (ahwif->irq < 0) {
+               pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id);
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (!request_mem_region(res->start, res->end - res->start + 1,
+                               pdev->name)) {
+               pr_debug("%s: request_mem_region failed\n", DRV_NAME);
+               ret =  -EBUSY;
+               goto out;
+       }
+
+       ahwif->regbase = (u32)ioremap(res->start, res->end - res->start + 1);
+       if (ahwif->regbase == 0) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+       auide_setup_ports(&hw, ahwif);
+       hw.irq = ahwif->irq;
+       hw.dev = dev;
+       hw.chipset = ide_au1xxx;
+
+       ret = ide_host_add(&au1xxx_port_info, hws, &host);
+       if (ret)
+               goto out;
+
+       auide_hwif.hwif = host->ports[0];
+
+       dev_set_drvdata(dev, host);
+
+       printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
+
+ out:
+       return ret;
+}
+
+static int au_ide_remove(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct resource *res;
+       struct ide_host *host = dev_get_drvdata(dev);
+       _auide_hwif *ahwif = &auide_hwif;
+
+       ide_host_remove(host);
+
+       iounmap((void *)ahwif->regbase);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       return 0;
+}
+
+static struct device_driver au1200_ide_driver = {
+       .name           = "au1200-ide",
+       .bus            = &platform_bus_type,
+       .probe          = au_ide_probe,
+       .remove         = au_ide_remove,
+};
+
+static int __init au_ide_init(void)
+{
+       return driver_register(&au1200_ide_driver);
+}
+
+static void __exit au_ide_exit(void)
+{
+       driver_unregister(&au1200_ide_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AU1200 IDE driver");
+
+module_init(au_ide_init);
+module_exit(au_ide_exit);
diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c
new file mode 100644 (file)
index 0000000..c5a3c9e
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *  Amiga Buddha, Catweasel and X-Surf IDE Driver
+ *
+ *     Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
+ *
+ *  This driver was written based on the specifications in README.buddha and
+ *  the X-Surf info from Inside_XSurf.txt available at
+ *  http://www.jschoenfeld.com
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  TODO:
+ *    - test it :-)
+ *    - tune the timings using the speed-register
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/zorro.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2
+     */
+
+#define BUDDHA_NUM_HWIFS       2
+#define CATWEASEL_NUM_HWIFS    3
+#define XSURF_NUM_HWIFS         2
+
+#define MAX_NUM_HWIFS          3
+
+    /*
+     *  Bases of the IDE interfaces (relative to the board address)
+     */
+
+#define BUDDHA_BASE1   0x800
+#define BUDDHA_BASE2   0xa00
+#define BUDDHA_BASE3   0xc00
+
+#define XSURF_BASE1     0xb000 /* 2.5" Interface */
+#define XSURF_BASE2     0xd000 /* 3.5" Interface */
+
+static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
+    BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
+};
+
+static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
+     XSURF_BASE1, XSURF_BASE2
+};
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define BUDDHA_CONTROL 0x11a
+
+    /*
+     *  Other registers
+     */
+
+#define BUDDHA_IRQ1    0xf00           /* MSB = 1, Harddisk is source of */
+#define BUDDHA_IRQ2    0xf40           /* interrupt */
+#define BUDDHA_IRQ3    0xf80
+
+#define XSURF_IRQ1      0x7e
+#define XSURF_IRQ2      0x7e
+
+static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
+    BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
+};
+
+static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = {
+    XSURF_IRQ1, XSURF_IRQ2
+};
+
+#define BUDDHA_IRQ_MR  0xfc0           /* master interrupt enable */
+
+
+    /*
+     *  Board information
+     */
+
+typedef enum BuddhaType_Enum {
+    BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
+} BuddhaType;
+
+static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" };
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int buddha_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = z_readb(hwif->io_ports.irq_addr);
+    if (!(ch & 0x80))
+           return 0;
+    return 1;
+}
+
+static int xsurf_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = z_readb(hwif->io_ports.irq_addr);
+    /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
+    z_writeb(0, hwif->io_ports.irq_addr);
+    if (!(ch & 0x80))
+           return 0;
+    return 1;
+}
+
+static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
+                                     unsigned long ctl, unsigned long irq_port,
+                                     ide_ack_intr_t *ack_intr)
+{
+       int i;
+
+       memset(hw, 0, sizeof(*hw));
+
+       hw->io_ports.data_addr = base;
+
+       for (i = 1; i < 8; i++)
+               hw->io_ports_array[i] = base + 2 + i * 4;
+
+       hw->io_ports.ctl_addr = ctl;
+       hw->io_ports.irq_addr = irq_port;
+
+       hw->irq = IRQ_AMIGA_PORTS;
+       hw->ack_intr = ack_intr;
+
+       hw->chipset = ide_generic;
+}
+
+    /*
+     *  Probe for a Buddha or Catweasel IDE interface
+     */
+
+static int __init buddha_init(void)
+{
+       struct zorro_dev *z = NULL;
+       u_long buddha_board = 0;
+       BuddhaType type;
+       int buddha_num_hwifs, i;
+
+       while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+               unsigned long board;
+               hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
+
+               if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
+                       buddha_num_hwifs = BUDDHA_NUM_HWIFS;
+                       type=BOARD_BUDDHA;
+               } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) {
+                       buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
+                       type=BOARD_CATWEASEL;
+               } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) {
+                       buddha_num_hwifs = XSURF_NUM_HWIFS;
+                       type=BOARD_XSURF;
+               } else 
+                       continue;
+               
+               board = z->resource.start;
+
+/*
+ * FIXME: we now have selectable mmio v/s iomio transports.
+ */
+
+               if(type != BOARD_XSURF) {
+                       if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
+                               continue;
+               } else {
+                       if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE"))
+                               continue;
+                       if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE"))
+                               goto fail_base2;
+                       if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) {
+                               release_mem_region(board+XSURF_BASE2, 0x1000);
+fail_base2:
+                               release_mem_region(board+XSURF_BASE1, 0x1000);
+                               continue;
+                       }
+               }         
+               buddha_board = ZTWO_VADDR(board);
+               
+               /* write to BUDDHA_IRQ_MR to enable the board IRQ */
+               /* X-Surf doesn't have this.  IRQs are always on */
+               if (type != BOARD_XSURF)
+                       z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
+
+               printk(KERN_INFO "ide: %s IDE controller\n",
+                                buddha_board_name[type]);
+
+               for (i = 0; i < buddha_num_hwifs; i++) {
+                       unsigned long base, ctl, irq_port;
+                       ide_ack_intr_t *ack_intr;
+
+                       if (type != BOARD_XSURF) {
+                               base = buddha_board + buddha_bases[i];
+                               ctl = base + BUDDHA_CONTROL;
+                               irq_port = buddha_board + buddha_irqports[i];
+                               ack_intr = buddha_ack_intr;
+                       } else {
+                               base = buddha_board + xsurf_bases[i];
+                               /* X-Surf has no CS1* (Control/AltStat) */
+                               ctl = 0;
+                               irq_port = buddha_board + xsurf_irqports[i];
+                               ack_intr = xsurf_ack_intr;
+                       }
+
+                       buddha_setup_ports(&hw[i], base, ctl, irq_port,
+                                          ack_intr);
+
+                       hws[i] = &hw[i];
+               }
+
+               ide_host_add(NULL, hws, NULL);
+       }
+
+       return 0;
+}
+
+module_init(buddha_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
new file mode 100644 (file)
index 0000000..e430664
--- /dev/null
@@ -0,0 +1,836 @@
+/*
+ *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
+ */
+
+/*
+ *  Original authors:  abramov@cecmow.enet.dec.com (Igor Abramov)
+ *                     mlord@pobox.com (Mark Lord)
+ *
+ *  See linux/MAINTAINERS for address of current maintainer.
+ *
+ *  This file provides support for the advanced features and bugs
+ *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
+ *
+ *  These chips are basically fucked by design, and getting this driver
+ *  to work on every motherboard design that uses this screwed chip seems
+ *  bloody well impossible.  However, we're still trying.
+ *
+ *  Version 0.97 worked for everybody.
+ *
+ *  User feedback is essential.  Many thanks to the beta test team:
+ *
+ *  A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com,
+ *  bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz,
+ *  chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de,
+ *  derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de,
+ *  flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net,
+ *  j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net,
+ *  kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu,
+ *  peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com,
+ *  s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net,
+ *  steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com
+ *  liug@mama.indstate.edu, and others.
+ *
+ *  Version 0.01       Initial version, hacked out of ide.c,
+ *                     and #include'd rather than compiled separately.
+ *                     This will get cleaned up in a subsequent release.
+ *
+ *  Version 0.02       Fixes for vlb initialization code, enable prefetch
+ *                     for versions 'B' and 'C' of chip by default,
+ *                     some code cleanup.
+ *
+ *  Version 0.03       Added reset of secondary interface,
+ *                     and black list for devices which are not compatible
+ *                     with prefetch mode. Separate function for setting
+ *                     prefetch is added, possibly it will be called some
+ *                     day from ioctl processing code.
+ *
+ *  Version 0.04       Now configs/compiles separate from ide.c
+ *
+ *  Version 0.05       Major rewrite of interface timing code.
+ *                     Added new function cmd640_set_mode to set PIO mode
+ *                     from ioctl call. New drives added to black list.
+ *
+ *  Version 0.06       More code cleanup. Prefetch is enabled only for
+ *                     detected hard drives, not included in prefetch
+ *                     black list.
+ *
+ *  Version 0.07       Changed to more conservative drive tuning policy.
+ *                     Unknown drives, which report PIO < 4 are set to
+ *                     (reported_PIO - 1) if it is supported, or to PIO0.
+ *                     List of known drives extended by info provided by
+ *                     CMD at their ftp site.
+ *
+ *  Version 0.08       Added autotune/noautotune support.
+ *
+ *  Version 0.09       Try to be smarter about 2nd port enabling.
+ *  Version 0.10       Be nice and don't reset 2nd port.
+ *  Version 0.11       Try to handle more weird situations.
+ *
+ *  Version 0.12       Lots of bug fixes from Laszlo Peter
+ *                     irq unmasking disabled for reliability.
+ *                     try to be even smarter about the second port.
+ *                     tidy up source code formatting.
+ *  Version 0.13       permit irq unmasking again.
+ *  Version 0.90       massive code cleanup, some bugs fixed.
+ *                     defaults all drives to PIO mode0, prefetch off.
+ *                     autotune is OFF by default, with compile time flag.
+ *                     prefetch can be turned OFF/ON using "hdparm -p8/-p9"
+ *                      (requires hdparm-3.1 or newer)
+ *  Version 0.91       first release to linux-kernel list.
+ *  Version 0.92       move initial reg dump to separate callable function
+ *                     change "readahead" to "prefetch" to avoid confusion
+ *  Version 0.95       respect original BIOS timings unless autotuning.
+ *                     tons of code cleanup and rearrangement.
+ *                     added CONFIG_BLK_DEV_CMD640_ENHANCED option
+ *                     prevent use of unmask when prefetch is on
+ *  Version 0.96       prevent use of io_32bit when prefetch is off
+ *  Version 0.97       fix VLB secondary interface for sjd@slip.net
+ *                     other minor tune-ups:  0.96 was very good.
+ *  Version 0.98       ignore PCI version when disabled by BIOS
+ *  Version 0.99       display setup/active/recovery clocks with PIO mode
+ *  Version 1.00       Mmm.. cannot depend on PCMD_ENA in all systems
+ *  Version 1.01       slow/fast devsel can be selected with "hdparm -p6/-p7"
+ *                      ("fast" is necessary for 32bit I/O in some systems)
+ *  Version 1.02       fix bug that resulted in slow "setup times"
+ *                      (patch courtesy of Zoltan Hidvegi)
+ */
+
+#define CMD640_PREFETCH_MASKS 1
+
+/*#define CMD640_DUMP_REGS */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "cmd640"
+
+static int cmd640_vlb;
+
+/*
+ * CMD640 specific registers definition.
+ */
+
+#define VID            0x00
+#define DID            0x02
+#define PCMD           0x04
+#define   PCMD_ENA     0x01
+#define PSTTS          0x06
+#define REVID          0x08
+#define PROGIF         0x09
+#define SUBCL          0x0a
+#define BASCL          0x0b
+#define BaseA0         0x10
+#define BaseA1         0x14
+#define BaseA2         0x18
+#define BaseA3         0x1c
+#define INTLINE                0x3c
+#define INPINE         0x3d
+
+#define        CFR             0x50
+#define   CFR_DEVREV           0x03
+#define   CFR_IDE01INTR                0x04
+#define          CFR_DEVID             0x18
+#define          CFR_AT_VESA_078h      0x20
+#define          CFR_DSA1              0x40
+#define          CFR_DSA0              0x80
+
+#define CNTRL          0x51
+#define          CNTRL_DIS_RA0         0x40
+#define   CNTRL_DIS_RA1                0x80
+#define          CNTRL_ENA_2ND         0x08
+
+#define        CMDTIM          0x52
+#define        ARTTIM0         0x53
+#define        DRWTIM0         0x54
+#define ARTTIM1        0x55
+#define DRWTIM1                0x56
+#define ARTTIM23       0x57
+#define   ARTTIM23_DIS_RA2     0x04
+#define   ARTTIM23_DIS_RA3     0x08
+#define DRWTIM23       0x58
+#define BRST           0x59
+
+/*
+ * Registers and masks for easy access by drive index:
+ */
+static u8 prefetch_regs[4]  = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
+static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3};
+
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+
+static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
+static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23};
+
+/*
+ * Current cmd640 timing values for each drive.
+ * The defaults for each are the slowest possible timings.
+ */
+static u8 setup_counts[4]    = {4, 4, 4, 4};     /* Address setup count (in clocks) */
+static u8 active_counts[4]   = {16, 16, 16, 16}; /* Active count   (encoded) */
+static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
+
+#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+static DEFINE_SPINLOCK(cmd640_lock);
+
+/*
+ * Interface to access cmd640x registers
+ */
+static unsigned int cmd640_key;
+static void (*__put_cmd640_reg)(u16 reg, u8 val);
+static u8 (*__get_cmd640_reg)(u16 reg);
+
+/*
+ * This is read from the CFR reg, and is used in several places.
+ */
+static unsigned int cmd640_chip_version;
+
+/*
+ * The CMD640x chip does not support DWORD config write cycles, but some
+ * of the BIOSes use them to implement the config services.
+ * Therefore, we must use direct IO instead.
+ */
+
+/* PCI method 1 access */
+
+static void put_cmd640_reg_pci1(u16 reg, u8 val)
+{
+       outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+       outb_p(val, (reg & 3) | 0xcfc);
+}
+
+static u8 get_cmd640_reg_pci1(u16 reg)
+{
+       outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+       return inb_p((reg & 3) | 0xcfc);
+}
+
+/* PCI method 2 access (from CMD datasheet) */
+
+static void put_cmd640_reg_pci2(u16 reg, u8 val)
+{
+       outb_p(0x10, 0xcf8);
+       outb_p(val, cmd640_key + reg);
+       outb_p(0, 0xcf8);
+}
+
+static u8 get_cmd640_reg_pci2(u16 reg)
+{
+       u8 b;
+
+       outb_p(0x10, 0xcf8);
+       b = inb_p(cmd640_key + reg);
+       outb_p(0, 0xcf8);
+       return b;
+}
+
+/* VLB access */
+
+static void put_cmd640_reg_vlb(u16 reg, u8 val)
+{
+       outb_p(reg, cmd640_key);
+       outb_p(val, cmd640_key + 4);
+}
+
+static u8 get_cmd640_reg_vlb(u16 reg)
+{
+       outb_p(reg, cmd640_key);
+       return inb_p(cmd640_key + 4);
+}
+
+static u8 get_cmd640_reg(u16 reg)
+{
+       unsigned long flags;
+       u8 b;
+
+       spin_lock_irqsave(&cmd640_lock, flags);
+       b = __get_cmd640_reg(reg);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+       return b;
+}
+
+static void put_cmd640_reg(u16 reg, u8 val)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cmd640_lock, flags);
+       __put_cmd640_reg(reg, val);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+}
+
+static int __init match_pci_cmd640_device(void)
+{
+       const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
+       unsigned int i;
+       for (i = 0; i < 4; i++) {
+               if (get_cmd640_reg(i) != ven_dev[i])
+                       return 0;
+       }
+#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT
+       if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
+               printk("ide: cmd640 on PCI disabled by BIOS\n");
+               return 0;
+       }
+#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */
+       return 1; /* success */
+}
+
+/*
+ * Probe for CMD640x -- pci method 1
+ */
+static int __init probe_for_cmd640_pci1(void)
+{
+       __get_cmd640_reg = get_cmd640_reg_pci1;
+       __put_cmd640_reg = put_cmd640_reg_pci1;
+       for (cmd640_key = 0x80000000;
+            cmd640_key <= 0x8000f800;
+            cmd640_key += 0x800) {
+               if (match_pci_cmd640_device())
+                       return 1; /* success */
+       }
+       return 0;
+}
+
+/*
+ * Probe for CMD640x -- pci method 2
+ */
+static int __init probe_for_cmd640_pci2(void)
+{
+       __get_cmd640_reg = get_cmd640_reg_pci2;
+       __put_cmd640_reg = put_cmd640_reg_pci2;
+       for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) {
+               if (match_pci_cmd640_device())
+                       return 1; /* success */
+       }
+       return 0;
+}
+
+/*
+ * Probe for CMD640x -- vlb
+ */
+static int __init probe_for_cmd640_vlb(void)
+{
+       u8 b;
+
+       __get_cmd640_reg = get_cmd640_reg_vlb;
+       __put_cmd640_reg = put_cmd640_reg_vlb;
+       cmd640_key = 0x178;
+       b = get_cmd640_reg(CFR);
+       if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) {
+               cmd640_key = 0x78;
+               b = get_cmd640_reg(CFR);
+               if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h))
+                       return 0;
+       }
+       return 1; /* success */
+}
+
+/*
+ *  Returns 1 if an IDE interface/drive exists at 0x170,
+ *  Returns 0 otherwise.
+ */
+static int __init secondary_port_responding(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cmd640_lock, flags);
+
+       outb_p(0x0a, 0x176);    /* select drive0 */
+       udelay(100);
+       if ((inb_p(0x176) & 0x1f) != 0x0a) {
+               outb_p(0x1a, 0x176); /* select drive1 */
+               udelay(100);
+               if ((inb_p(0x176) & 0x1f) != 0x1a) {
+                       spin_unlock_irqrestore(&cmd640_lock, flags);
+                       return 0; /* nothing responded */
+               }
+       }
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+       return 1; /* success */
+}
+
+#ifdef CMD640_DUMP_REGS
+/*
+ * Dump out all cmd640 registers.  May be called from ide.c
+ */
+static void cmd640_dump_regs(void)
+{
+       unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
+
+       /* Dump current state of chip registers */
+       printk("ide: cmd640 internal register dump:");
+       for (; reg <= 0x59; reg++) {
+               if (!(reg & 0x0f))
+                       printk("\n%04x:", reg);
+               printk(" %02x", get_cmd640_reg(reg));
+       }
+       printk("\n");
+}
+#endif
+
+static void __set_prefetch_mode(ide_drive_t *drive, int mode)
+{
+       if (mode) {     /* want prefetch on? */
+#if CMD640_PREFETCH_MASKS
+               drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+#endif
+               drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
+       } else {
+               drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
+               drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
+               drive->io_32bit = 0;
+       }
+}
+
+#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED
+/*
+ * Check whether prefetch is on for a drive,
+ * and initialize the unmask flags for safe operation.
+ */
+static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
+{
+       u8 b = get_cmd640_reg(prefetch_regs[index]);
+
+       __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1);
+}
+#else
+
+/*
+ * Sets prefetch mode for a drive.
+ */
+static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
+{
+       unsigned long flags;
+       int reg = prefetch_regs[index];
+       u8 b;
+
+       spin_lock_irqsave(&cmd640_lock, flags);
+       b = __get_cmd640_reg(reg);
+       __set_prefetch_mode(drive, mode);
+       if (mode)
+               b &= ~prefetch_masks[index];    /* enable prefetch */
+       else
+               b |= prefetch_masks[index];     /* disable prefetch */
+       __put_cmd640_reg(reg, b);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+}
+
+/*
+ * Dump out current drive clocks settings
+ */
+static void display_clocks(unsigned int index)
+{
+       u8 active_count, recovery_count;
+
+       active_count = active_counts[index];
+       if (active_count == 1)
+               ++active_count;
+       recovery_count = recovery_counts[index];
+       if (active_count > 3 && recovery_count == 1)
+               ++recovery_count;
+       if (cmd640_chip_version > 1)
+               recovery_count += 1;  /* cmd640b uses (count + 1)*/
+       printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count);
+}
+
+/*
+ * Pack active and recovery counts into single byte representation
+ * used by controller
+ */
+static inline u8 pack_nibbles(u8 upper, u8 lower)
+{
+       return ((upper & 0x0f) << 4) | (lower & 0x0f);
+}
+
+/*
+ * This routine writes the prepared setup/active/recovery counts
+ * for a drive into the cmd640 chipset registers to active them.
+ */
+static void program_drive_counts(ide_drive_t *drive, unsigned int index)
+{
+       unsigned long flags;
+       u8 setup_count    = setup_counts[index];
+       u8 active_count   = active_counts[index];
+       u8 recovery_count = recovery_counts[index];
+
+       /*
+        * Set up address setup count and drive read/write timing registers.
+        * Primary interface has individual count/timing registers for
+        * each drive.  Secondary interface has one common set of registers,
+        * so we merge the timings, using the slowest value for each timing.
+        */
+       if (index > 1) {
+               ide_hwif_t *hwif = drive->hwif;
+               ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
+               unsigned int mate = index ^ 1;
+
+               if (peer->dev_flags & IDE_DFLAG_PRESENT) {
+                       if (setup_count < setup_counts[mate])
+                               setup_count = setup_counts[mate];
+                       if (active_count < active_counts[mate])
+                               active_count = active_counts[mate];
+                       if (recovery_count < recovery_counts[mate])
+                               recovery_count = recovery_counts[mate];
+               }
+       }
+
+       /*
+        * Convert setup_count to internal chipset representation
+        */
+       switch (setup_count) {
+       case 4:  setup_count = 0x00; break;
+       case 3:  setup_count = 0x80; break;
+       case 1:
+       case 2:  setup_count = 0x40; break;
+       default: setup_count = 0xc0; /* case 5 */
+       }
+
+       /*
+        * Now that everything is ready, program the new timings
+        */
+       spin_lock_irqsave(&cmd640_lock, flags);
+       /*
+        * Program the address_setup clocks into ARTTIM reg,
+        * and then the active/recovery counts into the DRWTIM reg
+        * (this converts counts of 16 into counts of zero -- okay).
+        */
+       setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
+       __put_cmd640_reg(arttim_regs[index], setup_count);
+       __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+}
+
+/*
+ * Set a specific pio_mode for a drive
+ */
+static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
+                           u8 pio_mode, unsigned int cycle_time)
+{
+       struct ide_timing *t;
+       int setup_time, active_time, recovery_time, clock_time;
+       u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
+       int bus_speed;
+
+       if (cmd640_vlb)
+               bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
+       else
+               bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+
+       if (pio_mode > 5)
+               pio_mode = 5;
+
+       t = ide_timing_find_mode(XFER_PIO_0 + pio_mode);
+       setup_time  = t->setup;
+       active_time = t->active;
+
+       recovery_time = cycle_time - (setup_time + active_time);
+       clock_time = 1000 / bus_speed;
+       cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
+
+       setup_count = DIV_ROUND_UP(setup_time, clock_time);
+
+       active_count = DIV_ROUND_UP(active_time, clock_time);
+       if (active_count < 2)
+               active_count = 2; /* minimum allowed by cmd640 */
+
+       recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
+       recovery_count2 = cycle_count - (setup_count + active_count);
+       if (recovery_count2 > recovery_count)
+               recovery_count = recovery_count2;
+       if (recovery_count < 2)
+               recovery_count = 2; /* minimum allowed by cmd640 */
+       if (recovery_count > 17) {
+               active_count += recovery_count - 17;
+               recovery_count = 17;
+       }
+       if (active_count > 16)
+               active_count = 16; /* maximum allowed by cmd640 */
+       if (cmd640_chip_version > 1)
+               recovery_count -= 1;  /* cmd640b uses (count + 1)*/
+       if (recovery_count > 16)
+               recovery_count = 16; /* maximum allowed by cmd640 */
+
+       setup_counts[index]    = setup_count;
+       active_counts[index]   = active_count;
+       recovery_counts[index] = recovery_count;
+
+       /*
+        * In a perfect world, we might set the drive pio mode here
+        * (using WIN_SETFEATURE) before continuing.
+        *
+        * But we do not, because:
+        *      1) this is the wrong place to do it (proper is do_special() in ide.c)
+        *      2) in practice this is rarely, if ever, necessary
+        */
+       program_drive_counts(drive, index);
+}
+
+static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       unsigned int index = 0, cycle_time;
+       u8 b;
+
+       switch (pio) {
+       case 6: /* set fast-devsel off */
+       case 7: /* set fast-devsel on */
+               b = get_cmd640_reg(CNTRL) & ~0x27;
+               if (pio & 1)
+                       b |= 0x27;
+               put_cmd640_reg(CNTRL, b);
+               printk("%s: %sabled cmd640 fast host timing (devsel)\n",
+                       drive->name, (pio & 1) ? "en" : "dis");
+               return;
+       case 8: /* set prefetch off */
+       case 9: /* set prefetch on */
+               set_prefetch_mode(drive, index, pio & 1);
+               printk("%s: %sabled cmd640 prefetch\n",
+                       drive->name, (pio & 1) ? "en" : "dis");
+               return;
+       }
+
+       cycle_time = ide_pio_cycle_time(drive, pio);
+       cmd640_set_mode(drive, index, pio, cycle_time);
+
+       printk("%s: selected cmd640 PIO mode%d (%dns)",
+               drive->name, pio, cycle_time);
+
+       display_clocks(index);
+}
+#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+static void cmd640_init_dev(ide_drive_t *drive)
+{
+       unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
+
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+       /*
+        * Reset timing to the slowest speed and turn off prefetch.
+        * This way, the drive identify code has a better chance.
+        */
+       setup_counts[i]    =  4;        /* max possible */
+       active_counts[i]   = 16;        /* max possible */
+       recovery_counts[i] = 16;        /* max possible */
+       program_drive_counts(drive, i);
+       set_prefetch_mode(drive, i, 0);
+       printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i);
+#else
+       /*
+        * Set the drive unmask flags to match the prefetch setting.
+        */
+       check_prefetch(drive, i);
+       printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
+               i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on");
+#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+}
+
+
+static const struct ide_port_ops cmd640_port_ops = {
+       .init_dev               = cmd640_init_dev,
+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+       .set_pio_mode           = cmd640_set_pio_mode,
+#endif
+};
+
+static int pci_conf1(void)
+{
+       unsigned long flags;
+       u32 tmp;
+
+       spin_lock_irqsave(&cmd640_lock, flags);
+       outb(0x01, 0xCFB);
+       tmp = inl(0xCF8);
+       outl(0x80000000, 0xCF8);
+       if (inl(0xCF8) == 0x80000000) {
+               outl(tmp, 0xCF8);
+               spin_unlock_irqrestore(&cmd640_lock, flags);
+               return 1;
+       }
+       outl(tmp, 0xCF8);
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+       return 0;
+}
+
+static int pci_conf2(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cmd640_lock, flags);
+       outb(0x00, 0xCFB);
+       outb(0x00, 0xCF8);
+       outb(0x00, 0xCFA);
+       if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) {
+               spin_unlock_irqrestore(&cmd640_lock, flags);
+               return 1;
+       }
+       spin_unlock_irqrestore(&cmd640_lock, flags);
+       return 0;
+}
+
+static const struct ide_port_info cmd640_port_info __initdata = {
+       .chipset                = ide_cmd640,
+       .host_flags             = IDE_HFLAG_SERIALIZE |
+                                 IDE_HFLAG_NO_DMA |
+                                 IDE_HFLAG_ABUSE_PREFETCH |
+                                 IDE_HFLAG_ABUSE_FAST_DEVSEL,
+       .port_ops               = &cmd640_port_ops,
+       .pio_mask               = ATA_PIO5,
+};
+
+static int cmd640x_init_one(unsigned long base, unsigned long ctl)
+{
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+/*
+ * Probe for a cmd640 chipset, and initialize it if found.
+ */
+static int __init cmd640x_init(void)
+{
+       int second_port_cmd640 = 0, rc;
+       const char *bus_type, *port2;
+       u8 b, cfr;
+       hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
+
+       if (cmd640_vlb && probe_for_cmd640_vlb()) {
+               bus_type = "VLB";
+       } else {
+               cmd640_vlb = 0;
+               /* Find out what kind of PCI probing is supported otherwise
+                  Justin Gibbs will sulk.. */
+               if (pci_conf1() && probe_for_cmd640_pci1())
+                       bus_type = "PCI (type1)";
+               else if (pci_conf2() && probe_for_cmd640_pci2())
+                       bus_type = "PCI (type2)";
+               else
+                       return 0;
+       }
+       /*
+        * Undocumented magic (there is no 0x5b reg in specs)
+        */
+       put_cmd640_reg(0x5b, 0xbd);
+       if (get_cmd640_reg(0x5b) != 0xbd) {
+               printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n");
+               return 0;
+       }
+       put_cmd640_reg(0x5b, 0);
+
+#ifdef CMD640_DUMP_REGS
+       cmd640_dump_regs();
+#endif
+
+       /*
+        * Documented magic begins here
+        */
+       cfr = get_cmd640_reg(CFR);
+       cmd640_chip_version = cfr & CFR_DEVREV;
+       if (cmd640_chip_version == 0) {
+               printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
+               return 0;
+       }
+
+       rc = cmd640x_init_one(0x1f0, 0x3f6);
+       if (rc)
+               return rc;
+
+       rc = cmd640x_init_one(0x170, 0x376);
+       if (rc) {
+               release_region(0x3f6, 1);
+               release_region(0x1f0, 8);
+               return rc;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+
+       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
+       hw[0].irq = 14;
+       hw[0].chipset = ide_cmd640;
+
+       ide_std_init_ports(&hw[1], 0x170, 0x376);
+       hw[1].irq = 15;
+       hw[1].chipset = ide_cmd640;
+
+       printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
+                        "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
+
+       /*
+        * Initialize data for primary port
+        */
+       hws[0] = &hw[0];
+
+       /*
+        * Ensure compatibility by always using the slowest timings
+        * for access to the drive's command register block,
+        * and reset the prefetch burstsize to default (512 bytes).
+        *
+        * Maybe we need a way to NOT do these on *some* systems?
+        */
+       put_cmd640_reg(CMDTIM, 0);
+       put_cmd640_reg(BRST, 0x40);
+
+       b = get_cmd640_reg(CNTRL);
+
+       /*
+        * Try to enable the secondary interface, if not already enabled
+        */
+       if (secondary_port_responding()) {
+               if ((b & CNTRL_ENA_2ND)) {
+                       second_port_cmd640 = 1;
+                       port2 = "okay";
+               } else if (cmd640_vlb) {
+                       second_port_cmd640 = 1;
+                       port2 = "alive";
+               } else
+                       port2 = "not cmd640";
+       } else {
+               put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
+               if (secondary_port_responding()) {
+                       second_port_cmd640 = 1;
+                       port2 = "enabled";
+               } else {
+                       put_cmd640_reg(CNTRL, b); /* restore original setting */
+                       port2 = "not responding";
+               }
+       }
+
+       /*
+        * Initialize data for secondary cmd640 port, if enabled
+        */
+       if (second_port_cmd640)
+               hws[1] = &hw[1];
+
+       printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
+                        second_port_cmd640 ? "" : "not ", port2);
+
+#ifdef CMD640_DUMP_REGS
+       cmd640_dump_regs();
+#endif
+
+       return ide_host_add(&cmd640_port_info, hws, NULL);
+}
+
+module_param_named(probe_vlb, cmd640_vlb, bool, 0);
+MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset");
+
+module_init(cmd640x_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
new file mode 100644 (file)
index 0000000..935385c
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
+ *           Due to massive hardware bugs, UltraDMA is only supported
+ *           on the 646U2 and not on the 646U.
+ *
+ * Copyright (C) 1998          Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 1998          David S. Miller (davem@redhat.com)
+ *
+ * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "cmd64x"
+
+#define CMD_DEBUG 0
+
+#if CMD_DEBUG
+#define cmdprintk(x...)        printk(x)
+#else
+#define cmdprintk(x...)
+#endif
+
+/*
+ * CMD64x specific registers definition.
+ */
+#define CFR            0x50
+#define   CFR_INTR_CH0         0x04
+
+#define        CMDTIM          0x52
+#define        ARTTIM0         0x53
+#define        DRWTIM0         0x54
+#define ARTTIM1        0x55
+#define DRWTIM1                0x56
+#define ARTTIM23       0x57
+#define   ARTTIM23_DIS_RA2     0x04
+#define   ARTTIM23_DIS_RA3     0x08
+#define   ARTTIM23_INTR_CH1    0x10
+#define DRWTIM2                0x58
+#define BRST           0x59
+#define DRWTIM3                0x5b
+
+#define BMIDECR0       0x70
+#define MRDMODE                0x71
+#define   MRDMODE_INTR_CH0     0x04
+#define   MRDMODE_INTR_CH1     0x08
+#define UDIDETCR0      0x73
+#define DTPR0          0x74
+#define BMIDECR1       0x78
+#define BMIDECSR       0x79
+#define UDIDETCR1      0x7B
+#define DTPR1          0x7C
+
+static u8 quantize_timing(int timing, int quant)
+{
+       return (timing + quant - 1) / quant;
+}
+
+/*
+ * This routine calculates active/recovery counts and then writes them into
+ * the chipset registers.
+ */
+static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
+       u8  cycle_count, active_count, recovery_count, drwtim;
+       static const u8 recovery_values[] =
+               {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
+       static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
+
+       cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",
+                 cycle_time, active_time);
+
+       cycle_count     = quantize_timing( cycle_time, clock_time);
+       active_count    = quantize_timing(active_time, clock_time);
+       recovery_count  = cycle_count - active_count;
+
+       /*
+        * In case we've got too long recovery phase, try to lengthen
+        * the active phase
+        */
+       if (recovery_count > 16) {
+               active_count += recovery_count - 16;
+               recovery_count = 16;
+       }
+       if (active_count > 16)          /* shouldn't actually happen... */
+               active_count = 16;
+
+       cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
+                 cycle_count, active_count, recovery_count);
+
+       /*
+        * Convert values to internal chipset representation
+        */
+       recovery_count = recovery_values[recovery_count];
+       active_count  &= 0x0f;
+
+       /* Program the active/recovery counts into the DRWTIM register */
+       drwtim = (active_count << 4) | recovery_count;
+       (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
+       cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
+}
+
+/*
+ * This routine writes into the chipset registers
+ * PIO setup/active/recovery timings.
+ */
+static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_timing *t    = ide_timing_find_mode(XFER_PIO_0 + pio);
+       unsigned int cycle_time;
+       u8 setup_count, arttim = 0;
+
+       static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+       static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
+
+       cycle_time = ide_pio_cycle_time(drive, pio);
+
+       program_cycle_times(drive, cycle_time, t->active);
+
+       setup_count = quantize_timing(t->setup,
+                       1000 / (ide_pci_clk ? ide_pci_clk : 33));
+
+       /*
+        * The primary channel has individual address setup timing registers
+        * for each drive and the hardware selects the slowest timing itself.
+        * The secondary channel has one common register and we have to select
+        * the slowest address setup timing ourselves.
+        */
+       if (hwif->channel) {
+               ide_drive_t *drives = hwif->drives;
+
+               drive->drive_data = setup_count;
+               setup_count = max(drives[0].drive_data, drives[1].drive_data);
+       }
+
+       if (setup_count > 5)            /* shouldn't actually happen... */
+               setup_count = 5;
+       cmdprintk("Final address setup count: %d\n", setup_count);
+
+       /*
+        * Program the address setup clocks into the ARTTIM registers.
+        * Avoid clearing the secondary channel's interrupt bit.
+        */
+       (void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);
+       if (hwif->channel)
+               arttim &= ~ARTTIM23_INTR_CH1;
+       arttim &= ~0xc0;
+       arttim |= setup_values[setup_count];
+       (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
+       cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
+}
+
+/*
+ * Attempts to set drive's PIO mode.
+ * Special cases are 8: prefetch off, 9: prefetch on (both never worked)
+ */
+
+static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       /*
+        * Filter out the prefetch control values
+        * to prevent PIO5 from being programmed
+        */
+       if (pio == 8 || pio == 9)
+               return;
+
+       cmd64x_tune_pio(drive, pio);
+}
+
+static void cmd64x_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 unit                 = drive->dn & 0x01;
+       u8 regU = 0, pciU       = hwif->channel ? UDIDETCR1 : UDIDETCR0;
+
+       if (speed >= XFER_SW_DMA_0) {
+               (void) pci_read_config_byte(dev, pciU, &regU);
+               regU &= ~(unit ? 0xCA : 0x35);
+       }
+
+       switch(speed) {
+       case XFER_UDMA_5:
+               regU |= unit ? 0x0A : 0x05;
+               break;
+       case XFER_UDMA_4:
+               regU |= unit ? 0x4A : 0x15;
+               break;
+       case XFER_UDMA_3:
+               regU |= unit ? 0x8A : 0x25;
+               break;
+       case XFER_UDMA_2:
+               regU |= unit ? 0x42 : 0x11;
+               break;
+       case XFER_UDMA_1:
+               regU |= unit ? 0x82 : 0x21;
+               break;
+       case XFER_UDMA_0:
+               regU |= unit ? 0xC2 : 0x31;
+               break;
+       case XFER_MW_DMA_2:
+               program_cycle_times(drive, 120, 70);
+               break;
+       case XFER_MW_DMA_1:
+               program_cycle_times(drive, 150, 80);
+               break;
+       case XFER_MW_DMA_0:
+               program_cycle_times(drive, 480, 215);
+               break;
+       }
+
+       if (speed >= XFER_SW_DMA_0)
+               (void) pci_write_config_byte(dev, pciU, regU);
+}
+
+static int cmd648_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       unsigned long base      = hwif->dma_base - (hwif->channel * 8);
+       int err                 = ide_dma_end(drive);
+       u8  irq_mask            = hwif->channel ? MRDMODE_INTR_CH1 :
+                                                 MRDMODE_INTR_CH0;
+       u8  mrdmode             = inb(base + 1);
+
+       /* clear the interrupt bit */
+       outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
+            base + 1);
+
+       return err;
+}
+
+static int cmd64x_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
+       u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
+                                                 CFR_INTR_CH0;
+       u8  irq_stat            = 0;
+       int err                 = ide_dma_end(drive);
+
+       (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
+       /* clear the interrupt bit */
+       (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
+
+       return err;
+}
+
+static int cmd648_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       unsigned long base      = hwif->dma_base - (hwif->channel * 8);
+       u8 irq_mask             = hwif->channel ? MRDMODE_INTR_CH1 :
+                                                 MRDMODE_INTR_CH0;
+       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
+       u8 mrdmode              = inb(base + 1);
+
+#ifdef DEBUG
+       printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
+              drive->name, dma_stat, mrdmode, irq_mask);
+#endif
+       if (!(mrdmode & irq_mask))
+               return 0;
+
+       /* return 1 if INTR asserted */
+       if (dma_stat & 4)
+               return 1;
+
+       return 0;
+}
+
+static int cmd64x_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
+       u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
+                                                 CFR_INTR_CH0;
+       u8  dma_stat            = inb(hwif->dma_base + ATA_DMA_STATUS);
+       u8  irq_stat            = 0;
+
+       (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
+
+#ifdef DEBUG
+       printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
+              drive->name, dma_stat, irq_stat, irq_mask);
+#endif
+       if (!(irq_stat & irq_mask))
+               return 0;
+
+       /* return 1 if INTR asserted */
+       if (dma_stat & 4)
+               return 1;
+
+       return 0;
+}
+
+/*
+ * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
+ * event order for DMA transfers.
+ */
+
+static int cmd646_1_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u8 dma_stat = 0, dma_cmd = 0;
+
+       drive->waiting_for_dma = 0;
+       /* get DMA status */
+       dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
+       /* read DMA command state */
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+       /* stop DMA */
+       outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+       /* clear the INTR & ERROR bits */
+       outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+       /* and free any DMA resources */
+       ide_destroy_dmatable(drive);
+       /* verify good DMA status */
+       return (dma_stat & 7) != 4;
+}
+
+static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
+{
+       u8 mrdmode = 0;
+
+       /* Set a good latency timer and cache line size value. */
+       (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+       /* FIXME: pci_set_master() to ensure a good latency timer value */
+
+       /*
+        * Enable interrupts, select MEMORY READ LINE for reads.
+        *
+        * NOTE: although not mentioned in the PCI0646U specs,
+        * bits 0-1 are write only and won't be read back as
+        * set or not -- PCI0646U2 specs clarify this point.
+        */
+       (void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
+       mrdmode &= ~0x30;
+       (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
+
+       return 0;
+}
+
+static u8 cmd64x_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev  *dev    = to_pci_dev(hwif->dev);
+       u8 bmidecsr = 0, mask   = hwif->channel ? 0x02 : 0x01;
+
+       switch (dev->device) {
+       case PCI_DEVICE_ID_CMD_648:
+       case PCI_DEVICE_ID_CMD_649:
+               pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
+               return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+       default:
+               return ATA_CBL_PATA40;
+       }
+}
+
+static const struct ide_port_ops cmd64x_port_ops = {
+       .set_pio_mode           = cmd64x_set_pio_mode,
+       .set_dma_mode           = cmd64x_set_dma_mode,
+       .cable_detect           = cmd64x_cable_detect,
+};
+
+static const struct ide_dma_ops cmd64x_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                = cmd64x_dma_end,
+       .dma_test_irq           = cmd64x_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_dma_ops cmd646_rev1_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                = cmd646_1_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_dma_ops cmd648_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                = cmd648_dma_end,
+       .dma_test_irq           = cmd648_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+       {       /* 0: CMD643 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_cmd64x,
+               .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd64x_dma_ops,
+               .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
+                                 IDE_HFLAG_ABUSE_PREFETCH,
+               .pio_mask       = ATA_PIO5,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = 0x00, /* no udma */
+       },
+       {       /* 1: CMD646 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_cmd64x,
+               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+               .chipset        = ide_cmd646,
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd648_dma_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
+               .pio_mask       = ATA_PIO5,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA2,
+       },
+       {       /* 2: CMD648 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_cmd64x,
+               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd648_dma_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
+               .pio_mask       = ATA_PIO5,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA4,
+       },
+       {       /* 3: CMD649 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_cmd64x,
+               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+               .port_ops       = &cmd64x_port_ops,
+               .dma_ops        = &cmd648_dma_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
+               .pio_mask       = ATA_PIO5,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       }
+};
+
+static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+
+       d = cmd64x_chipsets[idx];
+
+       if (idx == 1) {
+               /*
+                * UltraDMA only supported on PCI646U and PCI646U2, which
+                * correspond to revisions 0x03, 0x05 and 0x07 respectively.
+                * Actually, although the CMD tech support people won't
+                * tell me the details, the 0x03 revision cannot support
+                * UDMA correctly without hardware modifications, and even
+                * then it only works with Quantum disks due to some
+                * hold time assumptions in the 646U part which are fixed
+                * in the 646U2.
+                *
+                * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
+                */
+               if (dev->revision < 5) {
+                       d.udma_mask = 0x00;
+                       /*
+                        * The original PCI0646 didn't have the primary
+                        * channel enable bit, it appeared starting with
+                        * PCI0646U (i.e. revision ID 3).
+                        */
+                       if (dev->revision < 3) {
+                               d.enablebits[0].reg = 0;
+                               if (dev->revision == 1)
+                                       d.dma_ops = &cmd646_rev1_dma_ops;
+                               else
+                                       d.dma_ops = &cmd64x_dma_ops;
+                       }
+               }
+       }
+
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static const struct pci_device_id cmd64x_pci_tbl[] = {
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 },
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
+
+static struct pci_driver cmd64x_pci_driver = {
+       .name           = "CMD64x_IDE",
+       .id_table       = cmd64x_pci_tbl,
+       .probe          = cmd64x_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init cmd64x_ide_init(void)
+{
+       return ide_pci_register_driver(&cmd64x_pci_driver);
+}
+
+static void __exit cmd64x_ide_exit(void)
+{
+       pci_unregister_driver(&cmd64x_pci_driver);
+}
+
+module_init(cmd64x_ide_init);
+module_exit(cmd64x_ide_exit);
+
+MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c
new file mode 100644 (file)
index 0000000..5efb467
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ *     IDE tuning and bus mastering support for the CS5510/CS5520
+ *     chipsets
+ *
+ *     The CS5510/CS5520 are slightly unusual devices. Unlike the 
+ *     typical IDE controllers they do bus mastering with the drive in
+ *     PIO mode and smarter silicon.
+ *
+ *     The practical upshot of this is that we must always tune the
+ *     drive for the right PIO mode. We must also ignore all the blacklists
+ *     and the drive bus mastering DMA information.
+ *
+ *     *** This driver is strictly experimental ***
+ *
+ *     (c) Copyright Red Hat Inc 2002
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open non patent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ *
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/dma-mapping.h>
+
+#define DRV_NAME "cs5520"
+
+struct pio_clocks
+{
+       int address;
+       int assert;
+       int recovery;
+};
+
+static struct pio_clocks cs5520_pio_clocks[]={
+       {3, 6, 11},
+       {2, 5, 6},
+       {1, 4, 3},
+       {1, 3, 2},
+       {1, 2, 1}
+};
+
+static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       int controller = drive->dn > 1 ? 1 : 0;
+
+       /* 8bit CAT/CRT - 8bit command timing for channel */
+       pci_write_config_byte(pdev, 0x62 + controller, 
+               (cs5520_pio_clocks[pio].recovery << 4) |
+               (cs5520_pio_clocks[pio].assert));
+
+       /* 0x64 - 16bit Primary, 0x68 - 16bit Secondary */
+
+       /* FIXME: should these use address ? */
+       /* Data read timing */
+       pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1),
+               (cs5520_pio_clocks[pio].recovery << 4) |
+               (cs5520_pio_clocks[pio].assert));
+       /* Write command timing */
+       pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
+               (cs5520_pio_clocks[pio].recovery << 4) |
+               (cs5520_pio_clocks[pio].assert));
+}
+
+static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       printk(KERN_ERR "cs55x0: bad ide timing.\n");
+
+       cs5520_set_pio_mode(drive, 0);
+}
+
+static const struct ide_port_ops cs5520_port_ops = {
+       .set_pio_mode           = cs5520_set_pio_mode,
+       .set_dma_mode           = cs5520_set_dma_mode,
+};
+
+static const struct ide_port_info cyrix_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
+       .port_ops       = &cs5520_port_ops,
+       .host_flags     = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520,
+       .pio_mask       = ATA_PIO4,
+};
+
+/*
+ *     The 5510/5520 are a bit weird. They don't quite set up the way
+ *     the PCI helper layer expects so we must do much of the set up 
+ *     work longhand.
+ */
+static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       const struct ide_port_info *d = &cyrix_chipset;
+       hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
+
+       ide_setup_pci_noise(dev, d);
+
+       /* We must not grab the entire device, it has 'ISA' space in its
+        * BARS too and we will freak out other bits of the kernel
+        */
+       if (pci_enable_device_io(dev)) {
+               printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
+               return -ENODEV;
+       }
+       pci_set_master(dev);
+       if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
+               printk(KERN_WARNING "%s: No suitable DMA available.\n",
+                       d->name);
+               return -ENODEV;
+       }
+
+       /*
+        *      Now the chipset is configured we can let the core
+        *      do all the device setup for us
+        */
+
+       ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
+
+       return ide_host_add(d, hws, NULL);
+}
+
+static const struct pci_device_id cs5520_pci_tbl[] = {
+       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), 0 },
+       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), 1 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
+
+static struct pci_driver cs5520_pci_driver = {
+       .name           = "Cyrix_IDE",
+       .id_table       = cs5520_pci_tbl,
+       .probe          = cs5520_init_one,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init cs5520_ide_init(void)
+{
+       return ide_pci_register_driver(&cs5520_pci_driver);
+}
+
+module_init(cs5520_ide_init);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for Cyrix 5510/5520 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
new file mode 100644 (file)
index 0000000..53f079c
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2000                  Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2000                  Mark Lord <mlord@pobox.com>
+ * Copyright (C) 2007                  Bartlomiej Zolnierkiewicz
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Development of this chipset driver was funded
+ * by the nice folks at National Semiconductor.
+ *
+ * Documentation:
+ *     CS5530 documentation available from National Semiconductor.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "cs5530"
+
+/*
+ * Here are the standard PIO mode 0-4 timings for each "format".
+ * Format-0 uses fast data reg timings, with slower command reg timings.
+ * Format-1 uses fast timings for all registers, but won't work with all drives.
+ */
+static unsigned int cs5530_pio_timings[2][5] = {
+       {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
+       {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}
+};
+
+/*
+ * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
+ */
+#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
+#define CS5530_BASEREG(hwif)   (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
+
+/**
+ *     cs5530_set_pio_mode     -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Handles setting of PIO mode for the chipset.
+ *
+ *     The init_hwif_cs5530() routine guarantees that all drives
+ *     will have valid default PIO timings set up before we get here.
+ */
+
+static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       unsigned long basereg = CS5530_BASEREG(drive->hwif);
+       unsigned int format = (inl(basereg + 4) >> 31) & 1;
+
+       outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
+}
+
+/**
+ *     cs5530_udma_filter      -       UDMA filter
+ *     @drive: drive
+ *
+ *     cs5530_udma_filter() does UDMA mask filtering for the given drive
+ *     taking into the consideration capabilities of the mate device.
+ *
+ *     The CS5530 specifies that two drives sharing a cable cannot mix
+ *     UDMA/MDMA.  It has to be one or the other, for the pair, though
+ *     different timings can still be chosen for each drive.  We could
+ *     set the appropriate timing bits on the fly, but that might be
+ *     a bit confusing.  So, for now we statically handle this requirement
+ *     by looking at our mate drive to see what it is capable of, before
+ *     choosing a mode for our own drive.
+ *
+ *     Note: This relies on the fact we never fail from UDMA to MWDMA2
+ *     but instead drop to PIO.
+ */
+
+static u8 cs5530_udma_filter(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       ide_drive_t *mate = ide_get_pair_dev(drive);
+       u16 *mateid = mate->id;
+       u8 mask = hwif->ultra_mask;
+
+       if (mate == NULL)
+               goto out;
+
+       if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
+               if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
+                   (mateid[ATA_ID_UDMA_MODES] & 7))
+                       goto out;
+               if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
+                   (mateid[ATA_ID_MWDMA_MODES] & 7))
+                       mask = 0;
+       }
+out:
+       return mask;
+}
+
+static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+       unsigned long basereg;
+       unsigned int reg, timings = 0;
+
+       switch (mode) {
+               case XFER_UDMA_0:       timings = 0x00921250; break;
+               case XFER_UDMA_1:       timings = 0x00911140; break;
+               case XFER_UDMA_2:       timings = 0x00911030; break;
+               case XFER_MW_DMA_0:     timings = 0x00077771; break;
+               case XFER_MW_DMA_1:     timings = 0x00012121; break;
+               case XFER_MW_DMA_2:     timings = 0x00002020; break;
+       }
+       basereg = CS5530_BASEREG(drive->hwif);
+       reg = inl(basereg + 4);                 /* get drive0 config register */
+       timings |= reg & 0x80000000;            /* preserve PIO format bit */
+       if ((drive-> dn & 1) == 0) {            /* are we configuring drive0? */
+               outl(timings, basereg + 4);     /* write drive0 config register */
+       } else {
+               if (timings & 0x00100000)
+                       reg |=  0x00100000;     /* enable UDMA timings for both drives */
+               else
+                       reg &= ~0x00100000;     /* disable UDMA timings for both drives */
+               outl(reg, basereg + 4);         /* write drive0 config register */
+               outl(timings, basereg + 12);    /* write drive1 config register */
+       }
+}
+
+/**
+ *     init_chipset_5530       -       set up 5530 bridge
+ *     @dev: PCI device
+ *
+ *     Initialize the cs5530 bridge for reliable IDE DMA operation.
+ */
+
+static unsigned int init_chipset_cs5530(struct pci_dev *dev)
+{
+       struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
+
+       if (pci_resource_start(dev, 4) == 0)
+               return -EFAULT;
+
+       dev = NULL;
+       while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
+               switch (dev->device) {
+                       case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
+                               master_0 = pci_dev_get(dev);
+                               break;
+                       case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
+                               cs5530_0 = pci_dev_get(dev);
+                               break;
+               }
+       }
+       if (!master_0) {
+               printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
+               goto out;
+       }
+       if (!cs5530_0) {
+               printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
+               goto out;
+       }
+
+       /*
+        * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
+        * -->  OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
+        */
+
+       pci_set_master(cs5530_0);
+       pci_try_set_mwi(cs5530_0);
+
+       /*
+        * Set PCI CacheLineSize to 16-bytes:
+        * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
+        */
+
+       pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
+
+       /*
+        * Disable trapping of UDMA register accesses (Win98 hack):
+        * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
+        */
+
+       pci_write_config_word(cs5530_0, 0xd0, 0x5006);
+
+       /*
+        * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
+        * The other settings are what is necessary to get the register
+        * into a sane state for IDE DMA operation.
+        */
+
+       pci_write_config_byte(master_0, 0x40, 0x1e);
+
+       /* 
+        * Set max PCI burst size (16-bytes seems to work best):
+        *         16bytes: set bit-1 at 0x41 (reg value of 0x16)
+        *      all others: clear bit-1 at 0x41, and do:
+        *        128bytes: OR 0x00 at 0x41
+        *        256bytes: OR 0x04 at 0x41
+        *        512bytes: OR 0x08 at 0x41
+        *       1024bytes: OR 0x0c at 0x41
+        */
+
+       pci_write_config_byte(master_0, 0x41, 0x14);
+
+       /*
+        * These settings are necessary to get the chip
+        * into a sane state for IDE DMA operation.
+        */
+
+       pci_write_config_byte(master_0, 0x42, 0x00);
+       pci_write_config_byte(master_0, 0x43, 0xc1);
+
+out:
+       pci_dev_put(master_0);
+       pci_dev_put(cs5530_0);
+       return 0;
+}
+
+/**
+ *     init_hwif_cs5530        -       initialise an IDE channel
+ *     @hwif: IDE to initialize
+ *
+ *     This gets invoked by the IDE driver once for each channel. It
+ *     performs channel-specific pre-initialization before drive probing.
+ */
+
+static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
+{
+       unsigned long basereg;
+       u32 d0_timings;
+
+       basereg = CS5530_BASEREG(hwif);
+       d0_timings = inl(basereg + 0);
+       if (CS5530_BAD_PIO(d0_timings))
+               outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
+       if (CS5530_BAD_PIO(inl(basereg + 8)))
+               outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
+}
+
+static const struct ide_port_ops cs5530_port_ops = {
+       .set_pio_mode           = cs5530_set_pio_mode,
+       .set_dma_mode           = cs5530_set_dma_mode,
+       .udma_filter            = cs5530_udma_filter,
+};
+
+static const struct ide_port_info cs5530_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_cs5530,
+       .init_hwif      = init_hwif_cs5530,
+       .port_ops       = &cs5530_port_ops,
+       .host_flags     = IDE_HFLAG_SERIALIZE |
+                         IDE_HFLAG_POST_SET_MODE,
+       .pio_mask       = ATA_PIO4,
+       .mwdma_mask     = ATA_MWDMA2,
+       .udma_mask      = ATA_UDMA2,
+};
+
+static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &cs5530_chipset, NULL);
+}
+
+static const struct pci_device_id cs5530_pci_tbl[] = {
+       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
+
+static struct pci_driver cs5530_pci_driver = {
+       .name           = "CS5530 IDE",
+       .id_table       = cs5530_pci_tbl,
+       .probe          = cs5530_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init cs5530_ide_init(void)
+{
+       return ide_pci_register_driver(&cs5530_pci_driver);
+}
+
+static void __exit cs5530_ide_exit(void)
+{
+       pci_unregister_driver(&cs5530_pci_driver);
+}
+
+module_init(cs5530_ide_init);
+module_exit(cs5530_ide_exit);
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cs5535.c b/drivers/ide/cs5535.c
new file mode 100644 (file)
index 0000000..983d957
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
+ * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
+ *
+ * History:
+ * 09/20/2005 - Jaya Kumar <jayakumar.ide@gmail.com>
+ * - Reworked tuneproc, set_drive, misc mods to prep for mainline
+ * - Work was sponsored by CIS (M) Sdn Bhd.
+ * Ported to Kernel 2.6.11 on June 26, 2005 by
+ *   Wolfgang Zuleger <wolfgang.zuleger@gmx.de>
+ *   Alexander Kiausch <alex.kiausch@t-online.de>
+ * Originally developed by AMD for 2.4/2.6
+ *
+ * Development of this chipset driver was funded
+ * by the nice folks at National Semiconductor/AMD.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Documentation:
+ *  CS5535 documentation available from AMD
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#define DRV_NAME "cs5535"
+
+#define MSR_ATAC_BASE          0x51300000
+#define ATAC_GLD_MSR_CAP       (MSR_ATAC_BASE+0)
+#define ATAC_GLD_MSR_CONFIG    (MSR_ATAC_BASE+0x01)
+#define ATAC_GLD_MSR_SMI       (MSR_ATAC_BASE+0x02)
+#define ATAC_GLD_MSR_ERROR     (MSR_ATAC_BASE+0x03)
+#define ATAC_GLD_MSR_PM                (MSR_ATAC_BASE+0x04)
+#define ATAC_GLD_MSR_DIAG      (MSR_ATAC_BASE+0x05)
+#define ATAC_IO_BAR            (MSR_ATAC_BASE+0x08)
+#define ATAC_RESET             (MSR_ATAC_BASE+0x10)
+#define ATAC_CH0D0_PIO         (MSR_ATAC_BASE+0x20)
+#define ATAC_CH0D0_DMA         (MSR_ATAC_BASE+0x21)
+#define ATAC_CH0D1_PIO         (MSR_ATAC_BASE+0x22)
+#define ATAC_CH0D1_DMA         (MSR_ATAC_BASE+0x23)
+#define ATAC_PCI_ABRTERR       (MSR_ATAC_BASE+0x24)
+#define ATAC_BM0_CMD_PRIM      0x00
+#define ATAC_BM0_STS_PRIM      0x02
+#define ATAC_BM0_PRD           0x04
+#define CS5535_CABLE_DETECT    0x48
+
+/* Format I PIO settings. We separate out cmd and data for safer timings */
+
+static unsigned int cs5535_pio_cmd_timings[5] =
+{ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 };
+static unsigned int cs5535_pio_dta_timings[5] =
+{ 0xF7F4, 0xF173, 0x8141, 0x5131, 0x1131 };
+
+static unsigned int cs5535_mwdma_timings[3] =
+{ 0x7F0FFFF3, 0x7F035352, 0x7f024241 };
+
+static unsigned int cs5535_udma_timings[5] =
+{ 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061 };
+
+/* Macros to check if the register is the reset value -  reset value is an
+   invalid timing and indicates the register has not been set previously */
+
+#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL) == 0x00009172 )
+#define CS5535_BAD_DMA(timings) ( (timings & 0x000FFFFF) == 0x00077771 )
+
+/****
+ *     cs5535_set_speed         -     Configure the chipset to the new speed
+ *     @drive: Drive to set up
+ *     @speed: desired speed
+ *
+ *     cs5535_set_speed() configures the chipset to a new speed.
+ */
+static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
+{
+       u32 reg = 0, dummy;
+       u8 unit = drive->dn & 1;
+
+       /* Set the PIO timings */
+       if (speed < XFER_SW_DMA_0) {
+               ide_drive_t *pair = ide_get_pair_dev(drive);
+               u8 cmd, pioa;
+
+               cmd = pioa = speed - XFER_PIO_0;
+
+               if (pair) {
+                       u8 piob = ide_get_best_pio_mode(pair, 255, 4);
+
+                       if (piob < cmd)
+                               cmd = piob;
+               }
+
+               /* Write the speed of the current drive */
+               reg = (cs5535_pio_cmd_timings[cmd] << 16) |
+                       cs5535_pio_dta_timings[pioa];
+               wrmsr(unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, reg, 0);
+
+               /* And if nessesary - change the speed of the other drive */
+               rdmsr(unit ?  ATAC_CH0D0_PIO : ATAC_CH0D1_PIO, reg, dummy);
+
+               if (((reg >> 16) & cs5535_pio_cmd_timings[cmd]) !=
+                       cs5535_pio_cmd_timings[cmd]) {
+                       reg &= 0x0000FFFF;
+                       reg |= cs5535_pio_cmd_timings[cmd] << 16;
+                       wrmsr(unit ? ATAC_CH0D0_PIO : ATAC_CH0D1_PIO, reg, 0);
+               }
+
+               /* Set bit 31 of the DMA register for PIO format 1 timings */
+               rdmsr(unit ?  ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
+               wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA,
+                                       reg | 0x80000000UL, 0);
+       } else {
+               rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
+
+               reg &= 0x80000000UL;  /* Preserve the PIO format bit */
+
+               if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_4)
+                       reg |= cs5535_udma_timings[speed - XFER_UDMA_0];
+               else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+                       reg |= cs5535_mwdma_timings[speed - XFER_MW_DMA_0];
+               else
+                       return;
+
+               wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, 0);
+       }
+}
+
+/**
+ *     cs5535_set_dma_mode     -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Programs the chipset for DMA mode.
+ */
+
+static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       cs5535_set_speed(drive, speed);
+}
+
+/**
+ *     cs5535_set_pio_mode     -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     A callback from the upper layers for PIO-only tuning.
+ */
+
+static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       cs5535_set_speed(drive, XFER_PIO_0 + pio);
+}
+
+static u8 cs5535_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u8 bit;
+
+       /* if a 80 wire cable was detected */
+       pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
+
+       return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+}
+
+static const struct ide_port_ops cs5535_port_ops = {
+       .set_pio_mode           = cs5535_set_pio_mode,
+       .set_dma_mode           = cs5535_set_dma_mode,
+       .cable_detect           = cs5535_cable_detect,
+};
+
+static const struct ide_port_info cs5535_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .port_ops       = &cs5535_port_ops,
+       .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
+       .pio_mask       = ATA_PIO4,
+       .mwdma_mask     = ATA_MWDMA2,
+       .udma_mask      = ATA_UDMA4,
+};
+
+static int __devinit cs5535_init_one(struct pci_dev *dev,
+                                       const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &cs5535_chipset, NULL);
+}
+
+static const struct pci_device_id cs5535_pci_tbl[] = {
+       { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_CS5535_IDE), 0 },
+       { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
+
+static struct pci_driver cs5535_pci_driver = {
+       .name           = "CS5535_IDE",
+       .id_table       = cs5535_pci_tbl,
+       .probe          = cs5535_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init cs5535_ide_init(void)
+{
+       return ide_pci_register_driver(&cs5535_pci_driver);
+}
+
+static void __exit cs5535_ide_exit(void)
+{
+       pci_unregister_driver(&cs5535_pci_driver);
+}
+
+module_init(cs5535_ide_init);
+module_exit(cs5535_ide_exit);
+
+MODULE_AUTHOR("AMD");
+MODULE_DESCRIPTION("PCI driver module for AMD/NS CS5535 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
new file mode 100644 (file)
index 0000000..5297f07
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
+ *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
+ *
+ * CYPRESS CY82C693 chipset IDE controller
+ *
+ * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
+ * Writing the driver was quite simple, since most of the job is
+ * done by the generic pci-ide support.
+ * The hard part was finding the CY82C693's datasheet on Cypress's
+ * web page :-(. But Altavista solved this problem :-).
+ *
+ *
+ * Notes:
+ * - I recently got a 16.8G IBM DTTA, so I was able to test it with
+ *   a large and fast disk - the results look great, so I'd say the
+ *   driver is working fine :-)
+ *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
+ * - this is my first linux driver, so there's probably a lot  of room
+ *   for optimizations and bug fixing, so feel free to do it.
+ * - if using PIO mode it's a good idea to set the PIO mode and
+ *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
+ * - I had some problems with my IBM DHEA with PIO modes < 2
+ *   (lost interrupts) ?????
+ * - first tests with DMA look okay, they seem to work, but there is a
+ *   problem with sound - the BusMaster IDE TimeOut should fixed this
+ *
+ * Ancient History:
+ * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693
+ * ASK@1999-01-23: v0.33 made a few minor code clean ups
+ *                       removed DMA clock speed setting by default
+ *                       added boot message
+ * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut
+ *                       added support to set DMA Controller Clock Speed
+ * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes
+ *                       on some drives.
+ * ASK@1998-10-29: v0.3 added support to set DMA modes
+ * ASK@1998-10-28: v0.2 added support to set PIO modes
+ * ASK@1998-10-27: v0.1 first version - chipset detection
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "cy82c693"
+
+/*
+ *     The following are used to debug the driver.
+ */
+#define CY82C693_DEBUG_INFO    0
+
+/*
+ *     NOTE: the value for busmaster timeout is tricky and I got it by
+ *     trial and error!  By using a to low value will cause DMA timeouts
+ *     and drop IDE performance, and by using a to high value will cause
+ *     audio playback to scatter.
+ *     If you know a better value or how to calc it, please let me know.
+ */
+
+/* twice the value written in cy82c693ub datasheet */
+#define BUSMASTER_TIMEOUT      0x50
+/*
+ * the value above was tested on my machine and it seems to work okay
+ */
+
+/* here are the offset definitions for the registers */
+#define CY82_IDE_CMDREG                0x04
+#define CY82_IDE_ADDRSETUP     0x48
+#define CY82_IDE_MASTER_IOR    0x4C
+#define CY82_IDE_MASTER_IOW    0x4D
+#define CY82_IDE_SLAVE_IOR     0x4E
+#define CY82_IDE_SLAVE_IOW     0x4F
+#define CY82_IDE_MASTER_8BIT   0x50
+#define CY82_IDE_SLAVE_8BIT    0x51
+
+#define CY82_INDEX_PORT                0x22
+#define CY82_DATA_PORT         0x23
+
+#define CY82_INDEX_CHANNEL0    0x30
+#define CY82_INDEX_CHANNEL1    0x31
+#define CY82_INDEX_TIMEOUT     0x32
+
+/* the min and max PCI bus speed in MHz - from datasheet */
+#define CY82C963_MIN_BUS_SPEED 25
+#define CY82C963_MAX_BUS_SPEED 33
+
+/* the struct for the PIO mode timings */
+typedef struct pio_clocks_s {
+       u8      address_time;   /* Address setup (clocks) */
+       u8      time_16r;       /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
+       u8      time_16w;       /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
+       u8      time_8;         /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
+} pio_clocks_t;
+
+/*
+ * calc clocks using bus_speed
+ * returns (rounded up) time in bus clocks for time in ns
+ */
+static int calc_clk(int time, int bus_speed)
+{
+       int clocks;
+
+       clocks = (time*bus_speed+999)/1000 - 1;
+
+       if (clocks < 0)
+               clocks = 0;
+
+       if (clocks > 0x0F)
+               clocks = 0x0F;
+
+       return clocks;
+}
+
+/*
+ * compute the values for the clock registers for PIO
+ * mode and pci_clk [MHz] speed
+ *
+ * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
+ *       for mode 3 and 4 drives 8 and 16-bit timings are the same
+ *
+ */
+static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
+{
+       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+       int clk1, clk2;
+       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+
+       /* we don't check against CY82C693's min and max speed,
+        * so you can play with the idebus=xx parameter
+        */
+
+       /* let's calc the address setup time clocks */
+       p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);
+
+       /* let's calc the active and recovery time clocks */
+       clk1 = calc_clk(t->active, bus_speed);
+
+       /* calc recovery timing */
+       clk2 = t->cycle - t->active - t->setup;
+
+       clk2 = calc_clk(clk2, bus_speed);
+
+       clk1 = (clk1<<4)|clk2;  /* combine active and recovery clocks */
+
+       /* note: we use the same values for 16bit IOR and IOW
+        *      those are all the same, since I don't have other
+        *      timings than those from ide-lib.c
+        */
+
+       p_pclk->time_16r = (u8)clk1;
+       p_pclk->time_16w = (u8)clk1;
+
+       /* what are good values for 8bit ?? */
+       p_pclk->time_8 = (u8)clk1;
+}
+
+/*
+ * set DMA mode a specific channel for CY82C693
+ */
+
+static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
+
+       index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
+
+       data = (mode & 3) | (single << 2);
+
+       outb(index, CY82_INDEX_PORT);
+       outb(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+       printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
+               drive->name, hwif->channel, drive->dn & 1, mode & 3, single);
+#endif /* CY82C693_DEBUG_INFO */
+
+       /*
+        * note: below we set the value for Bus Master IDE TimeOut Register
+        * I'm not absolutly sure what this does, but it solved my problem
+        * with IDE DMA and sound, so I now can play sound and work with
+        * my IDE driver at the same time :-)
+        *
+        * If you know the correct (best) value for this register please
+        * let me know - ASK
+        */
+
+       data = BUSMASTER_TIMEOUT;
+       outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+       outb(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+       printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
+               drive->name, data);
+#endif /* CY82C693_DEBUG_INFO */
+}
+
+static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       pio_clocks_t pclk;
+       unsigned int addrCtrl;
+
+       /* select primary or secondary channel */
+       if (hwif->index > 0) {  /* drive is on the secondary channel */
+               dev = pci_get_slot(dev->bus, dev->devfn+1);
+               if (!dev) {
+                       printk(KERN_ERR "%s: tune_drive: "
+                               "Cannot find secondary interface!\n",
+                               drive->name);
+                       return;
+               }
+       }
+
+       /* let's calc the values for this PIO mode */
+       compute_clocks(pio, &pclk);
+
+       /* now let's write  the clocks registers */
+       if ((drive->dn & 1) == 0) {
+               /*
+                * set master drive
+                * address setup control register
+                * is 32 bit !!!
+                */
+               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+               addrCtrl &= (~0xF);
+               addrCtrl |= (unsigned int)pclk.address_time;
+               pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+
+               /* now let's set the remaining registers */
+               pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
+               pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
+               pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
+
+               addrCtrl &= 0xF;
+       } else {
+               /*
+                * set slave drive
+                * address setup control register
+                * is 32 bit !!!
+                */
+               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+               addrCtrl &= (~0xF0);
+               addrCtrl |= ((unsigned int)pclk.address_time<<4);
+               pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+
+               /* now let's set the remaining registers */
+               pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
+               pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
+               pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
+
+               addrCtrl >>= 4;
+               addrCtrl &= 0xF;
+       }
+
+#if CY82C693_DEBUG_INFO
+       printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
+               "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
+               drive->name, hwif->channel, drive->dn & 1,
+               addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+#endif /* CY82C693_DEBUG_INFO */
+}
+
+static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
+{
+       static ide_hwif_t *primary;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       if (PCI_FUNC(dev->devfn) == 1)
+               primary = hwif;
+       else {
+               hwif->mate = primary;
+               hwif->channel = 1;
+       }
+}
+
+static const struct ide_port_ops cy82c693_port_ops = {
+       .set_pio_mode           = cy82c693_set_pio_mode,
+       .set_dma_mode           = cy82c693_set_dma_mode,
+};
+
+static const struct ide_port_info cy82c693_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_iops      = init_iops_cy82c693,
+       .port_ops       = &cy82c693_port_ops,
+       .chipset        = ide_cy82c693,
+       .host_flags     = IDE_HFLAG_SINGLE,
+       .pio_mask       = ATA_PIO4,
+       .swdma_mask     = ATA_SWDMA2,
+       .mwdma_mask     = ATA_MWDMA2,
+};
+
+static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct pci_dev *dev2;
+       int ret = -ENODEV;
+
+       /* CY82C693 is more than only a IDE controller.
+          Function 1 is primary IDE channel, function 2 - secondary. */
+       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+           PCI_FUNC(dev->devfn) == 1) {
+               dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
+               ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
+               if (ret)
+                       pci_dev_put(dev2);
+       }
+       return ret;
+}
+
+static void __devexit cy82c693_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+       ide_pci_remove(dev);
+       pci_dev_put(dev2);
+}
+
+static const struct pci_device_id cy82c693_pci_tbl[] = {
+       { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
+
+static struct pci_driver cy82c693_pci_driver = {
+       .name           = "Cypress_IDE",
+       .id_table       = cy82c693_pci_tbl,
+       .probe          = cy82c693_init_one,
+       .remove         = __devexit_p(cy82c693_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init cy82c693_ide_init(void)
+{
+       return ide_pci_register_driver(&cy82c693_pci_driver);
+}
+
+static void __exit cy82c693_ide_exit(void)
+{
+       pci_unregister_driver(&cy82c693_pci_driver);
+}
+
+module_init(cy82c693_ide_init);
+module_exit(cy82c693_ide_exit);
+
+MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c
new file mode 100644 (file)
index 0000000..8f1b2d9
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ *  Created 20 Oct 2004 by Mark Lord
+ *
+ *  Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
+ *
+ *  Modeled after the 16-bit PCMCIA driver: ide-cs.c
+ *
+ *  This is slightly peculiar, in that it is a PCI driver,
+ *  but is NOT an IDE PCI driver -- the IDE layer does not directly
+ *  support hot insertion/removal of PCI interfaces, so this driver
+ *  is unable to use the IDE PCI interfaces.  Instead, it uses the
+ *  same interfaces as the ide-cs (PCMCIA) driver uses.
+ *  On the plus side, the driver is also smaller/simpler this way.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+
+/*
+ * No chip documentation has yet been found,
+ * so these configuration values were pulled from
+ * a running Win98 system using "debug".
+ * This gives around 3MByte/second read performance,
+ * which is about 2/3 of what the chip is capable of.
+ *
+ * There is also a 4KByte mmio region on the card,
+ * but its purpose has yet to be reverse-engineered.
+ */
+static const u8 setup[] = {
+       0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00,
+       0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
+};
+
+static const struct ide_port_ops delkin_cb_port_ops = {
+       .quirkproc              = ide_undecoded_slave,
+};
+
+static unsigned int delkin_cb_init_chipset(struct pci_dev *dev)
+{
+       unsigned long base = pci_resource_start(dev, 0);
+       int i;
+
+       outb(0x02, base + 0x1e);        /* set nIEN to block interrupts */
+       inb(base + 0x17);               /* read status to clear interrupts */
+
+       for (i = 0; i < sizeof(setup); ++i) {
+               if (setup[i])
+                       outb(setup[i], base + i);
+       }
+
+       return 0;
+}
+
+static const struct ide_port_info delkin_cb_port_info = {
+       .port_ops               = &delkin_cb_port_ops,
+       .host_flags             = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS |
+                                 IDE_HFLAG_NO_DMA,
+       .init_chipset           = delkin_cb_init_chipset,
+};
+
+static int __devinit
+delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_host *host;
+       unsigned long base;
+       int rc;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+       rc = pci_enable_device(dev);
+       if (rc) {
+               printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc);
+               return rc;
+       }
+       rc = pci_request_regions(dev, "delkin_cb");
+       if (rc) {
+               printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc);
+               pci_disable_device(dev);
+               return rc;
+       }
+       base = pci_resource_start(dev, 0);
+
+       delkin_cb_init_chipset(dev);
+
+       memset(&hw, 0, sizeof(hw));
+       ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
+       hw.irq = dev->irq;
+       hw.dev = &dev->dev;
+       hw.chipset = ide_pci;           /* this enables IRQ sharing */
+
+       rc = ide_host_add(&delkin_cb_port_info, hws, &host);
+       if (rc)
+               goto out_disable;
+
+       pci_set_drvdata(dev, host);
+
+       return 0;
+
+out_disable:
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+       return rc;
+}
+
+static void
+delkin_cb_remove (struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       ide_host_remove(host);
+
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+}
+
+#ifdef CONFIG_PM
+static int delkin_cb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       pci_save_state(dev);
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+
+       return 0;
+}
+
+static int delkin_cb_resume(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       int rc;
+
+       pci_set_power_state(dev, PCI_D0);
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               return rc;
+
+       pci_restore_state(dev);
+       pci_set_master(dev);
+
+       if (host->init_chipset)
+               host->init_chipset(dev);
+
+       return 0;
+}
+#else
+#define delkin_cb_suspend NULL
+#define delkin_cb_resume NULL
+#endif
+
+static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
+       { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
+
+static struct pci_driver delkin_cb_pci_driver = {
+       .name           = "Delkin-ASKA-Workbit Cardbus IDE",
+       .id_table       = delkin_cb_pci_tbl,
+       .probe          = delkin_cb_probe,
+       .remove         = delkin_cb_remove,
+       .suspend        = delkin_cb_suspend,
+       .resume         = delkin_cb_resume,
+};
+
+static int __init delkin_cb_init(void)
+{
+       return pci_register_driver(&delkin_cb_pci_driver);
+}
+
+static void __exit delkin_cb_exit(void)
+{
+       pci_unregister_driver(&delkin_cb_pci_driver);
+}
+
+module_init(delkin_cb_init);
+module_exit(delkin_cb_exit);
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
new file mode 100644 (file)
index 0000000..689b2e4
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (C) 1996  Linus Torvalds & author (see below)
+ */
+
+#include <linux/module.h>
+#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/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "dtc2278"
+
+/*
+ * Changing this #undef to #define may solve start up problems in some systems.
+ */
+#undef ALWAYS_SET_DTC2278_PIO_MODE
+
+/*
+ * From: andy@cercle.cts.com (Dyan Wile)
+ *
+ * Below is a patch for DTC-2278 - alike software-programmable controllers
+ * The code enables the secondary IDE controller and the PIO4 (3?) timings on
+ * the primary (EIDE). You may probably have to enable the 32-bit support to
+ * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
+ * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
+ * filesystem  corrupted with -u1, but under heavy disk load only :-)
+ *
+ * This card is now forced to use the "serialize" feature,
+ * and irq-unmasking is disallowed.  If io_32bit is enabled,
+ * it must be done for BOTH drives on each interface.
+ *
+ * This code was written for the DTC2278E, but might work with any of these:
+ *
+ * DTC2278S has only a single IDE interface.
+ * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
+ * DTC2278E also has serial ports and a printer port
+ * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
+ *
+ * There may be a fourth controller type. The S and D versions use the
+ * Winbond chip, and I think the E version does also.
+ *
+ */
+
+static void sub22 (char b, char c)
+{
+       int i;
+
+       for(i = 0; i < 3; ++i) {
+               inb(0x3f6);
+               outb_p(b,0xb0);
+               inb(0x3f6);
+               outb_p(c,0xb4);
+               inb(0x3f6);
+               if(inb(0xb4) == c) {
+                       outb_p(7,0xb0);
+                       inb(0x3f6);
+                       return; /* success */
+               }
+       }
+}
+
+static DEFINE_SPINLOCK(dtc2278_lock);
+
+static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       unsigned long flags;
+
+       if (pio >= 3) {
+               spin_lock_irqsave(&dtc2278_lock, flags);
+               /*
+                * This enables PIO mode4 (3?) on the first interface
+                */
+               sub22(1,0xc3);
+               sub22(0,0xa0);
+               spin_unlock_irqrestore(&dtc2278_lock, flags);
+       } else {
+               /* we don't know how to set it back again.. */
+               /* Actually we do - there is a data sheet available for the
+                  Winbond but does anyone actually care */
+       }
+}
+
+static const struct ide_port_ops dtc2278_port_ops = {
+       .set_pio_mode           = dtc2278_set_pio_mode,
+};
+
+static const struct ide_port_info dtc2278_port_info __initdata = {
+       .name                   = DRV_NAME,
+       .chipset                = ide_dtc2278,
+       .port_ops               = &dtc2278_port_ops,
+       .host_flags             = IDE_HFLAG_SERIALIZE |
+                                 IDE_HFLAG_NO_UNMASK_IRQS |
+                                 IDE_HFLAG_IO_32BIT |
+                                 /* disallow ->io_32bit changes */
+                                 IDE_HFLAG_NO_IO_32BIT |
+                                 IDE_HFLAG_NO_DMA,
+       .pio_mask               = ATA_PIO4,
+};
+
+static int __init dtc2278_probe(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       /*
+        * This enables the second interface
+        */
+       outb_p(4,0xb0);
+       inb(0x3f6);
+       outb_p(0x20,0xb4);
+       inb(0x3f6);
+#ifdef ALWAYS_SET_DTC2278_PIO_MODE
+       /*
+        * This enables PIO mode4 (3?) on the first interface
+        * and may solve start-up problems for some people.
+        */
+       sub22(1,0xc3);
+       sub22(0,0xa0);
+#endif
+       local_irq_restore(flags);
+
+       return ide_legacy_device_add(&dtc2278_port_info, 0);
+}
+
+static int probe_dtc2278;
+
+module_param_named(probe, probe_dtc2278, bool, 0);
+MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
+
+static int __init dtc2278_init(void)
+{
+       if (probe_dtc2278 == 0)
+               return -ENODEV;
+
+       if (dtc2278_probe()) {
+               printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
+               return -EBUSY;
+       }
+       return 0;
+}
+
+module_init(dtc2278_init);
+
+MODULE_AUTHOR("See Local File");
+MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c
new file mode 100644 (file)
index 0000000..39d500d
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Atari Falcon IDE Driver
+ *
+ *     Created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atari_stdma.h>
+
+#define DRV_NAME "falconide"
+
+    /*
+     *  Base of the IDE interface
+     */
+
+#define ATA_HD_BASE    0xfff00000
+
+    /*
+     *  Offsets from the above base
+     */
+
+#define ATA_HD_CONTROL 0x39
+
+    /*
+     *  falconide_intr_lock is used to obtain access to the IDE interrupt,
+     *  which is shared between several drivers.
+     */
+
+int falconide_intr_lock;
+EXPORT_SYMBOL(falconide_intr_lock);
+
+static void falconide_input_data(ide_drive_t *drive, struct request *rq,
+                                void *buf, unsigned int len)
+{
+       unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
+       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+               return insw(data_addr, buf, (len + 1) / 2);
+
+       insw_swapw(data_addr, buf, (len + 1) / 2);
+}
+
+static void falconide_output_data(ide_drive_t *drive, struct request *rq,
+                                 void *buf, unsigned int len)
+{
+       unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
+       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+               return outsw(data_addr, buf, (len + 1) / 2);
+
+       outsw_swapw(data_addr, buf, (len + 1) / 2);
+}
+
+/* Atari has a byte-swapped IDE interface */
+static const struct ide_tp_ops falconide_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = falconide_input_data,
+       .output_data            = falconide_output_data,
+};
+
+static const struct ide_port_info falconide_port_info = {
+       .tp_ops                 = &falconide_tp_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+};
+
+static void __init falconide_setup_ports(hw_regs_t *hw)
+{
+       int i;
+
+       memset(hw, 0, sizeof(*hw));
+
+       hw->io_ports.data_addr = ATA_HD_BASE;
+
+       for (i = 1; i < 8; i++)
+               hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4;
+
+       hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL;
+
+       hw->irq = IRQ_MFP_IDE;
+       hw->ack_intr = NULL;
+
+       hw->chipset = ide_generic;
+}
+
+    /*
+     *  Probe for a Falcon IDE interface
+     */
+
+static int __init falconide_init(void)
+{
+       struct ide_host *host;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+       int rc;
+
+       if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
+               return -ENODEV;
+
+       printk(KERN_INFO "ide: Falcon IDE controller\n");
+
+       if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
+               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+               return -EBUSY;
+       }
+
+       falconide_setup_ports(&hw);
+
+       host = ide_host_alloc(&falconide_port_info, hws);
+       if (host == NULL) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       ide_get_lock(NULL, NULL);
+       rc = ide_host_register(host, &falconide_port_info, hws);
+       ide_release_lock();
+
+       if (rc)
+               goto err_free;
+
+       return 0;
+err_free:
+       ide_host_free(host);
+err:
+       release_mem_region(ATA_HD_BASE, 0x40);
+       return rc;
+}
+
+module_init(falconide_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
new file mode 100644 (file)
index 0000000..6915068
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *  Amiga Gayle IDE Driver
+ *
+ *     Created 9 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/zorro.h>
+#include <linux/module.h>
+
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amigayle.h>
+
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define GAYLE_BASE_4000        0xdd2020        /* A4000/A4000T */
+#define GAYLE_BASE_1200        0xda0000        /* A1200/A600 and E-Matrix 530 */
+
+#define GAYLE_IDEREG_SIZE      0x2000
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define GAYLE_CONTROL  0x101a
+
+    /*
+     *  These are at different offsets from the base
+     */
+
+#define GAYLE_IRQ_4000 0xdd3020        /* MSB = 1, Harddisk is source of */
+#define GAYLE_IRQ_1200 0xda9000        /* interrupt */
+
+
+    /*
+     *  Offset of the secondary port for IDE doublers
+     *  Note that GAYLE_CONTROL is NOT available then!
+     */
+
+#define GAYLE_NEXT_PORT        0x1000
+
+#ifndef CONFIG_BLK_DEV_IDEDOUBLER
+#define GAYLE_NUM_HWIFS                1
+#define GAYLE_NUM_PROBE_HWIFS  GAYLE_NUM_HWIFS
+#define GAYLE_HAS_CONTROL_REG  1
+#else /* CONFIG_BLK_DEV_IDEDOUBLER */
+#define GAYLE_NUM_HWIFS                2
+#define GAYLE_NUM_PROBE_HWIFS  (ide_doubler ? GAYLE_NUM_HWIFS : \
+                                              GAYLE_NUM_HWIFS-1)
+#define GAYLE_HAS_CONTROL_REG  (!ide_doubler)
+
+static int ide_doubler;
+module_param_named(doubler, ide_doubler, bool, 0);
+MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = z_readb(hwif->io_ports.irq_addr);
+    if (!(ch & GAYLE_IRQ_IDE))
+       return 0;
+    return 1;
+}
+
+static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = z_readb(hwif->io_ports.irq_addr);
+    if (!(ch & GAYLE_IRQ_IDE))
+       return 0;
+    (void)z_readb(hwif->io_ports.status_addr);
+    z_writeb(0x7c, hwif->io_ports.irq_addr);
+    return 1;
+}
+
+static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
+                                    unsigned long ctl, unsigned long irq_port,
+                                    ide_ack_intr_t *ack_intr)
+{
+       int i;
+
+       memset(hw, 0, sizeof(*hw));
+
+       hw->io_ports.data_addr = base;
+
+       for (i = 1; i < 8; i++)
+               hw->io_ports_array[i] = base + 2 + i * 4;
+
+       hw->io_ports.ctl_addr = ctl;
+       hw->io_ports.irq_addr = irq_port;
+
+       hw->irq = IRQ_AMIGA_PORTS;
+       hw->ack_intr = ack_intr;
+
+       hw->chipset = ide_generic;
+}
+
+    /*
+     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+     */
+
+static int __init gayle_init(void)
+{
+    unsigned long phys_base, res_start, res_n;
+    unsigned long base, ctrlport, irqport;
+    ide_ack_intr_t *ack_intr;
+    int a4000, i, rc;
+    hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
+
+    if (!MACH_IS_AMIGA)
+       return -ENODEV;
+
+    if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
+       goto found;
+
+#ifdef CONFIG_ZORRO
+    if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
+                         NULL))
+       goto found;
+#endif
+    return -ENODEV;
+
+found:
+       printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
+                        a4000 ? 4000 : 1200,
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+                        ide_doubler ? ", IDE doubler" :
+#endif
+                        "");
+
+       if (a4000) {
+           phys_base = GAYLE_BASE_4000;
+           irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
+           ack_intr = gayle_ack_intr_a4000;
+       } else {
+           phys_base = GAYLE_BASE_1200;
+           irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
+           ack_intr = gayle_ack_intr_a1200;
+       }
+/*
+ * FIXME: we now have selectable modes between mmio v/s iomio
+ */
+
+       res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
+       res_n = GAYLE_IDEREG_SIZE;
+
+       if (!request_mem_region(res_start, res_n, "IDE"))
+               return -EBUSY;
+
+    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+       base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
+       ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
+
+       gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
+
+       hws[i] = &hw[i];
+    }
+
+    rc = ide_host_add(NULL, hws, NULL);
+    if (rc)
+       release_mem_region(res_start, res_n);
+
+    return rc;
+}
+
+module_init(gayle_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/generic.c b/drivers/ide/generic.c
new file mode 100644 (file)
index 0000000..474f96a
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *  Copyright (C) 2001-2002    Andre Hedrick <andre@linux-ide.org>
+ *  Portions (C) Copyright 2002  Red Hat Inc <alan@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open non patent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "ide_pci_generic"
+
+static int ide_generic_all;            /* Set to claim all devices */
+
+module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
+MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
+
+#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
+
+#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
+       { \
+               .name           = DRV_NAME, \
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
+                                 extra_flags, \
+               .swdma_mask     = ATA_SWDMA2, \
+               .mwdma_mask     = ATA_MWDMA2, \
+               .udma_mask      = ATA_UDMA6, \
+       }
+
+static const struct ide_port_info generic_chipsets[] __devinitdata = {
+       /*  0: Unknown */
+       DECLARE_GENERIC_PCI_DEV(0),
+
+       {       /* 1: NS87410 */
+               .name           = DRV_NAME,
+               .enablebits     = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+               .swdma_mask     = ATA_SWDMA2,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+       },
+
+       /*  2: SAMURAI / HT6565 / HINT_IDE */
+       DECLARE_GENERIC_PCI_DEV(0),
+       /*  3: UM8673F / UM8886A / UM8886BF */
+       DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
+       /*  4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
+       DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
+
+       {       /* 5: VIA8237SATA */
+               .name           = DRV_NAME,
+               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+                                 IDE_HFLAG_OFF_BOARD,
+               .swdma_mask     = ATA_SWDMA2,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+       },
+
+       {       /* 6: Revolution */
+               .name           = DRV_NAME,
+               .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
+                                 IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+                                 IDE_HFLAG_OFF_BOARD,
+               .swdma_mask     = ATA_SWDMA2,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+       }
+};
+
+/**
+ *     generic_init_one        -       called when a PIIX is found
+ *     @dev: the generic device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+
+static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       const struct ide_port_info *d = &generic_chipsets[id->driver_data];
+       int ret = -ENODEV;
+
+       /* Don't use the generic entry unless instructed to do so */
+       if (id->driver_data == 0 && ide_generic_all == 0)
+                       goto out;
+
+       switch (dev->vendor) {
+       case PCI_VENDOR_ID_UMC:
+               if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
+                               !(PCI_FUNC(dev->devfn) & 1))
+                       goto out; /* UM8886A/BF pair */
+               break;
+       case PCI_VENDOR_ID_OPTI:
+               if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
+                               !(PCI_FUNC(dev->devfn) & 1))
+                       goto out;
+               break;
+       case PCI_VENDOR_ID_JMICRON:
+               if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
+                               PCI_FUNC(dev->devfn) != 1)
+                       goto out;
+               break;
+       case PCI_VENDOR_ID_NS:
+               if (dev->device == PCI_DEVICE_ID_NS_87410 &&
+                               (dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+                       goto out;
+               break;
+       }
+
+       if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
+               u16 command;
+               pci_read_config_word(dev, PCI_COMMAND, &command);
+               if (!(command & PCI_COMMAND_IO)) {
+                       printk(KERN_INFO "%s %s: skipping disabled "
+                               "controller\n", d->name, pci_name(dev));
+                       goto out;
+               }
+       }
+       ret = ide_pci_init_one(dev, d, NULL);
+out:
+       return ret;
+}
+
+static const struct pci_device_id generic_pci_tbl[] = {
+       { PCI_VDEVICE(NS,       PCI_DEVICE_ID_NS_87410),                 1 },
+       { PCI_VDEVICE(PCTECH,   PCI_DEVICE_ID_PCTECH_SAMURAI_IDE),       2 },
+       { PCI_VDEVICE(HOLTEK,   PCI_DEVICE_ID_HOLTEK_6565),              2 },
+       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8673F),              3 },
+       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886A),              3 },
+       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886BF),             3 },
+       { PCI_VDEVICE(HINT,     PCI_DEVICE_ID_HINT_VXPROII_IDE),         2 },
+       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_82C561),               4 },
+       { PCI_VDEVICE(OPTI,     PCI_DEVICE_ID_OPTI_82C558),              4 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_8237_SATA),            5 },
+#endif
+       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO),          4 },
+       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_1),        4 },
+       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),        4 },
+       { PCI_VDEVICE(NETCELL,  PCI_DEVICE_ID_REVOLUTION),               6 },
+       /*
+        * Must come last.  If you add entries adjust
+        * this table and generic_chipsets[] appropriately.
+        */
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
+
+static struct pci_driver generic_pci_driver = {
+       .name           = "PCI_IDE",
+       .id_table       = generic_pci_tbl,
+       .probe          = generic_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init generic_ide_init(void)
+{
+       return ide_pci_register_driver(&generic_pci_driver);
+}
+
+static void __exit generic_ide_exit(void)
+{
+       pci_unregister_driver(&generic_pci_driver);
+}
+
+module_init(generic_ide_init);
+module_exit(generic_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile
deleted file mode 100644 (file)
index 5eba16f..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-obj-$(CONFIG_IDE_H8300)                        += ide-h8300.o
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
deleted file mode 100644 (file)
index e2cdd2e..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * H8/300 generic IDE interface
- */
-
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define DRV_NAME "ide-h8300"
-
-#define bswap(d) \
-({                                     \
-       u16 r;                          \
-       __asm__("mov.b %w1,r1h\n\t"     \
-               "mov.b %x1,r1l\n\t"     \
-               "mov.w r1,%0"           \
-               :"=r"(r)                \
-               :"r"(d)                 \
-               :"er1");                \
-       (r);                            \
-})
-
-static void mm_outw(u16 d, unsigned long a)
-{
-       __asm__("mov.b %w0,r2h\n\t"
-               "mov.b %x0,r2l\n\t"
-               "mov.w r2,@%1"
-               :
-               :"r"(d),"r"(a)
-               :"er2");
-}
-
-static u16 mm_inw(unsigned long a)
-{
-       register u16 r __asm__("er0");
-       __asm__("mov.w @%1,r2\n\t"
-               "mov.b r2l,%x0\n\t"
-               "mov.b r2h,%w0"
-               :"=r"(r)
-               :"r"(a)
-               :"er2");
-       return r;
-}
-
-static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-       struct ide_taskfile *tf = &task->tf;
-       u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
-
-       if (task->tf_flags & IDE_TFLAG_FLAGGED)
-               HIHI = 0xFF;
-
-       if (task->tf_flags & IDE_TFLAG_OUT_DATA)
-               mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr);
-
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-               outb(tf->hob_feature, io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-               outb(tf->hob_nsect, io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-               outb(tf->hob_lbal, io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-               outb(tf->hob_lbam, io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-               outb(tf->hob_lbah, io_ports->lbah_addr);
-
-       if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
-               outb(tf->feature, io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
-               outb(tf->nsect, io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
-               outb(tf->lbal, io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
-               outb(tf->lbam, io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
-               outb(tf->lbah, io_ports->lbah_addr);
-
-       if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               outb((tf->device & HIHI) | drive->select,
-                    io_ports->device_addr);
-}
-
-static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-       struct ide_taskfile *tf = &task->tf;
-
-       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-               u16 data = mm_inw(io_ports->data_addr);
-
-               tf->data = data & 0xff;
-               tf->hob_data = (data >> 8) & 0xff;
-       }
-
-       /* be sure we're looking at the low order bits */
-       outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
-
-       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
-               tf->feature = inb(io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-               tf->nsect  = inb(io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-               tf->lbal   = inb(io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-               tf->lbam   = inb(io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-               tf->lbah   = inb(io_ports->lbah_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-               tf->device = inb(io_ports->device_addr);
-
-       if (task->tf_flags & IDE_TFLAG_LBA48) {
-               outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
-
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-                       tf->hob_feature = inb(io_ports->feature_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-                       tf->hob_nsect   = inb(io_ports->nsect_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-                       tf->hob_lbal    = inb(io_ports->lbal_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-                       tf->hob_lbam    = inb(io_ports->lbam_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-                       tf->hob_lbah    = inb(io_ports->lbah_addr);
-       }
-}
-
-static void mm_outsw(unsigned long addr, void *buf, u32 len)
-{
-       unsigned short *bp = (unsigned short *)buf;
-       for (; len > 0; len--, bp++)
-               *(volatile u16 *)addr = bswap(*bp);
-}
-
-static void mm_insw(unsigned long addr, void *buf, u32 len)
-{
-       unsigned short *bp = (unsigned short *)buf;
-       for (; len > 0; len--, bp++)
-               *bp = bswap(*(volatile u16 *)addr);
-}
-
-static void h8300_input_data(ide_drive_t *drive, struct request *rq,
-                            void *buf, unsigned int len)
-{
-       mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static void h8300_output_data(ide_drive_t *drive, struct request *rq,
-                             void *buf, unsigned int len)
-{
-       mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static const struct ide_tp_ops h8300_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = ide_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
-
-       .set_irq                = ide_set_irq,
-
-       .tf_load                = h8300_tf_load,
-       .tf_read                = h8300_tf_read,
-
-       .input_data             = h8300_input_data,
-       .output_data            = h8300_output_data,
-};
-
-#define H8300_IDE_GAP (2)
-
-static inline void hw_setup(hw_regs_t *hw)
-{
-       int i;
-
-       memset(hw, 0, sizeof(hw_regs_t));
-       for (i = 0; i <= 7; i++)
-               hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
-       hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
-       hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
-       hw->chipset = ide_generic;
-}
-
-static const struct ide_port_info h8300_port_info = {
-       .tp_ops                 = &h8300_tp_ops,
-       .host_flags             = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
-};
-
-static int __init h8300_ide_init(void)
-{
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-       printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
-
-       if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
-               goto out_busy;
-       if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) {
-               release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8);
-               goto out_busy;
-       }
-
-       hw_setup(&hw);
-
-       return ide_host_add(&h8300_port_info, hws, NULL);
-
-out_busy:
-       printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
-
-       return -EBUSY;
-}
-
-module_init(h8300_ide_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
new file mode 100644 (file)
index 0000000..a7909e9
--- /dev/null
@@ -0,0 +1,1643 @@
+/*
+ * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
+ * Portions Copyright (C) 2001         Sun Microsystems, Inc.
+ * Portions Copyright (C) 2003         Red Hat Inc
+ * Portions Copyright (C) 2007         Bartlomiej Zolnierkiewicz
+ * Portions Copyright (C) 2005-2008    MontaVista Software, Inc.
+ *
+ * Thanks to HighPoint Technologies for their assistance, and hardware.
+ * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
+ * donation of an ABit BP6 mainboard, processor, and memory acellerated
+ * development and support.
+ *
+ *
+ * HighPoint has its own drivers (open source except for the RAID part)
+ * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
+ * This may be useful to anyone wanting to work on this driver, however  do not
+ * trust  them too much since the code tends to become less and less meaningful
+ * as the time passes... :-/
+ *
+ * Note that final HPT370 support was done by force extraction of GPL.
+ *
+ * - add function for getting/setting power status of drive
+ * - the HPT370's state machine can get confused. reset it before each dma 
+ *   xfer to prevent that from happening.
+ * - reset state engine whenever we get an error.
+ * - check for busmaster state at end of dma. 
+ * - use new highpoint timings.
+ * - detect bus speed using highpoint register.
+ * - use pll if we don't have a clock table. added a 66MHz table that's
+ *   just 2x the 33MHz table.
+ * - removed turnaround. NOTE: we never want to switch between pll and
+ *   pci clocks as the chip can glitch in those cases. the highpoint
+ *   approved workaround slows everything down too much to be useful. in
+ *   addition, we would have to serialize access to each chip.
+ *     Adrian Sun <a.sun@sun.com>
+ *
+ * add drive timings for 66MHz PCI bus,
+ * fix ATA Cable signal detection, fix incorrect /proc info
+ * add /proc display for per-drive PIO/DMA/UDMA mode and
+ * per-channel ATA-33/66 Cable detect.
+ *     Duncan Laurie <void@sun.com>
+ *
+ * fixup /proc output for multiple controllers
+ *     Tim Hockin <thockin@sun.com>
+ *
+ * On hpt366: 
+ * Reset the hpt366 on error, reset on dma
+ * Fix disabling Fast Interrupt hpt366.
+ *     Mike Waychison <crlf@sun.com>
+ *
+ * Added support for 372N clocking and clock switching. The 372N needs
+ * different clocks on read/write. This requires overloading rw_disk and
+ * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
+ * keeping me sane. 
+ *             Alan Cox <alan@redhat.com>
+ *
+ * - fix the clock turnaround code: it was writing to the wrong ports when
+ *   called for the secondary channel, caching the current clock mode per-
+ *   channel caused the cached register value to get out of sync with the
+ *   actual one, the channels weren't serialized, the turnaround shouldn't
+ *   be done on 66 MHz PCI bus
+ * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used
+ *   does not allow for this speed anyway
+ * - avoid touching disabled channels (e.g. HPT371/N are single channel chips,
+ *   their primary channel is kind of virtual, it isn't tied to any pins)
+ * - fix/remove bad/unused timing tables and use one set of tables for the whole
+ *   HPT37x chip family; save space by introducing the separate transfer mode
+ *   table in which the mode lookup is done
+ * - use f_CNT value saved by  the HighPoint BIOS as reading it directly gives
+ *   the wrong PCI frequency since DPLL has already been calibrated by BIOS;
+ *   read it only from the function 0 of HPT374 chips
+ * - fix the hotswap code:  it caused RESET- to glitch when tristating the bus,
+ *   and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
+ * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
+ *   they tamper with its fields
+ * - pass  to the init_setup handlers a copy of the ide_pci_device_t structure
+ *   since they may tamper with its fields
+ * - prefix the driver startup messages with the real chip name
+ * - claim the extra 240 bytes of I/O space for all chips
+ * - optimize the UltraDMA filtering and the drive list lookup code
+ * - use pci_get_slot() to get to the function 1 of HPT36x/374
+ * - cache offset of the channel's misc. control registers (MCRs) being used
+ *   throughout the driver
+ * - only touch the relevant MCR when detecting the cable type on HPT374's
+ *   function 1
+ * - rename all the register related variables consistently
+ * - move all the interrupt twiddling code from the speedproc handlers into
+ *   init_hwif_hpt366(), also grouping all the DMA related code together there
+ * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
+ *   separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
+ *   when setting an UltraDMA mode
+ * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
+ *   the best possible one
+ * - clean up DMA timeout handling for HPT370
+ * - switch to using the enumeration type to differ between the numerous chip
+ *   variants, matching PCI device/revision ID with the chip type early, at the
+ *   init_setup stage
+ * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies,
+ *   stop duplicating it for each channel by storing the pointer in the pci_dev
+ *   structure: first, at the init_setup stage, point it to a static "template"
+ *   with only the chip type and its specific base DPLL frequency, the highest
+ *   UltraDMA mode, and the chip settings table pointer filled,  then, at the
+ *   init_chipset stage, allocate per-chip instance  and fill it with the rest
+ *   of the necessary information
+ * - get rid of the constant thresholds in the HPT37x PCI clock detection code,
+ *   switch  to calculating  PCI clock frequency based on the chip's base DPLL
+ *   frequency
+ * - switch to using the  DPLL clock and enable UltraATA/133 mode by default on
+ *   anything  newer than HPT370/A (except HPT374 that is not capable of this
+ *   mode according to the manual)
+ * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
+ *   also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
+ *   unify HPT36x/37x timing setup code and the speedproc handlers by joining
+ *   the register setting lists into the table indexed by the clock selected
+ * - set the correct hwif->ultra_mask for each individual chip
+ * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
+ *     Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define DRV_NAME "hpt366"
+
+/* various tuning parameters */
+#define HPT_RESET_STATE_ENGINE
+#undef HPT_DELAY_INTERRUPT
+#define HPT_SERIALIZE_IO       0
+
+static const char *quirk_drives[] = {
+       "QUANTUM FIREBALLlct08 08",
+       "QUANTUM FIREBALLP KA6.4",
+       "QUANTUM FIREBALLP LM20.4",
+       "QUANTUM FIREBALLP LM20.5",
+       NULL
+};
+
+static const char *bad_ata100_5[] = {
+       "IBM-DTLA-307075",
+       "IBM-DTLA-307060",
+       "IBM-DTLA-307045",
+       "IBM-DTLA-307030",
+       "IBM-DTLA-307020",
+       "IBM-DTLA-307015",
+       "IBM-DTLA-305040",
+       "IBM-DTLA-305030",
+       "IBM-DTLA-305020",
+       "IC35L010AVER07-0",
+       "IC35L020AVER07-0",
+       "IC35L030AVER07-0",
+       "IC35L040AVER07-0",
+       "IC35L060AVER07-0",
+       "WDC AC310200R",
+       NULL
+};
+
+static const char *bad_ata66_4[] = {
+       "IBM-DTLA-307075",
+       "IBM-DTLA-307060",
+       "IBM-DTLA-307045",
+       "IBM-DTLA-307030",
+       "IBM-DTLA-307020",
+       "IBM-DTLA-307015",
+       "IBM-DTLA-305040",
+       "IBM-DTLA-305030",
+       "IBM-DTLA-305020",
+       "IC35L010AVER07-0",
+       "IC35L020AVER07-0",
+       "IC35L030AVER07-0",
+       "IC35L040AVER07-0",
+       "IC35L060AVER07-0",
+       "WDC AC310200R",
+       "MAXTOR STM3320620A",
+       NULL
+};
+
+static const char *bad_ata66_3[] = {
+       "WDC AC310200R",
+       NULL
+};
+
+static const char *bad_ata33[] = {
+       "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
+       "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+       "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+       "Maxtor 90510D4",
+       "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
+       "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+       "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+       NULL
+};
+
+static u8 xfer_speeds[] = {
+       XFER_UDMA_6,
+       XFER_UDMA_5,
+       XFER_UDMA_4,
+       XFER_UDMA_3,
+       XFER_UDMA_2,
+       XFER_UDMA_1,
+       XFER_UDMA_0,
+
+       XFER_MW_DMA_2,
+       XFER_MW_DMA_1,
+       XFER_MW_DMA_0,
+
+       XFER_PIO_4,
+       XFER_PIO_3,
+       XFER_PIO_2,
+       XFER_PIO_1,
+       XFER_PIO_0
+};
+
+/* Key for bus clock timings
+ * 36x   37x
+ * bits  bits
+ * 0:3  0:3    data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
+ *             cycles = value + 1
+ * 4:7  4:8    data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
+ *             cycles = value + 1
+ * 8:11  9:12  cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
+ *             register access.
+ * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
+ *             register access.
+ * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
+ * -    21     CLK frequency: 0=ATA clock, 1=dual ATA clock.
+ * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
+ *             MW DMA xfer.
+ * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
+ *             task file register access.
+ * 28   28     UDMA enable.
+ * 29   29     DMA  enable.
+ * 30   30     PIO MST enable. If set, the chip is in bus master mode during
+ *             PIO xfer.
+ * 31   31     FIFO enable.
+ */
+
+static u32 forty_base_hpt36x[] = {
+       /* XFER_UDMA_6 */       0x900fd943,
+       /* XFER_UDMA_5 */       0x900fd943,
+       /* XFER_UDMA_4 */       0x900fd943,
+       /* XFER_UDMA_3 */       0x900ad943,
+       /* XFER_UDMA_2 */       0x900bd943,
+       /* XFER_UDMA_1 */       0x9008d943,
+       /* XFER_UDMA_0 */       0x9008d943,
+
+       /* XFER_MW_DMA_2 */     0xa008d943,
+       /* XFER_MW_DMA_1 */     0xa010d955,
+       /* XFER_MW_DMA_0 */     0xa010d9fc,
+
+       /* XFER_PIO_4 */        0xc008d963,
+       /* XFER_PIO_3 */        0xc010d974,
+       /* XFER_PIO_2 */        0xc010d997,
+       /* XFER_PIO_1 */        0xc010d9c7,
+       /* XFER_PIO_0 */        0xc018d9d9
+};
+
+static u32 thirty_three_base_hpt36x[] = {
+       /* XFER_UDMA_6 */       0x90c9a731,
+       /* XFER_UDMA_5 */       0x90c9a731,
+       /* XFER_UDMA_4 */       0x90c9a731,
+       /* XFER_UDMA_3 */       0x90cfa731,
+       /* XFER_UDMA_2 */       0x90caa731,
+       /* XFER_UDMA_1 */       0x90cba731,
+       /* XFER_UDMA_0 */       0x90c8a731,
+
+       /* XFER_MW_DMA_2 */     0xa0c8a731,
+       /* XFER_MW_DMA_1 */     0xa0c8a732,     /* 0xa0c8a733 */
+       /* XFER_MW_DMA_0 */     0xa0c8a797,
+
+       /* XFER_PIO_4 */        0xc0c8a731,
+       /* XFER_PIO_3 */        0xc0c8a742,
+       /* XFER_PIO_2 */        0xc0d0a753,
+       /* XFER_PIO_1 */        0xc0d0a7a3,     /* 0xc0d0a793 */
+       /* XFER_PIO_0 */        0xc0d0a7aa      /* 0xc0d0a7a7 */
+};
+
+static u32 twenty_five_base_hpt36x[] = {
+       /* XFER_UDMA_6 */       0x90c98521,
+       /* XFER_UDMA_5 */       0x90c98521,
+       /* XFER_UDMA_4 */       0x90c98521,
+       /* XFER_UDMA_3 */       0x90cf8521,
+       /* XFER_UDMA_2 */       0x90cf8521,
+       /* XFER_UDMA_1 */       0x90cb8521,
+       /* XFER_UDMA_0 */       0x90cb8521,
+
+       /* XFER_MW_DMA_2 */     0xa0ca8521,
+       /* XFER_MW_DMA_1 */     0xa0ca8532,
+       /* XFER_MW_DMA_0 */     0xa0ca8575,
+
+       /* XFER_PIO_4 */        0xc0ca8521,
+       /* XFER_PIO_3 */        0xc0ca8532,
+       /* XFER_PIO_2 */        0xc0ca8542,
+       /* XFER_PIO_1 */        0xc0d08572,
+       /* XFER_PIO_0 */        0xc0d08585
+};
+
+#if 0
+/* These are the timing tables from the HighPoint open source drivers... */
+static u32 thirty_three_base_hpt37x[] = {
+       /* XFER_UDMA_6 */       0x12446231,     /* 0x12646231 ?? */
+       /* XFER_UDMA_5 */       0x12446231,
+       /* XFER_UDMA_4 */       0x12446231,
+       /* XFER_UDMA_3 */       0x126c6231,
+       /* XFER_UDMA_2 */       0x12486231,
+       /* XFER_UDMA_1 */       0x124c6233,
+       /* XFER_UDMA_0 */       0x12506297,
+
+       /* XFER_MW_DMA_2 */     0x22406c31,
+       /* XFER_MW_DMA_1 */     0x22406c33,
+       /* XFER_MW_DMA_0 */     0x22406c97,
+
+       /* XFER_PIO_4 */        0x06414e31,
+       /* XFER_PIO_3 */        0x06414e42,
+       /* XFER_PIO_2 */        0x06414e53,
+       /* XFER_PIO_1 */        0x06814e93,
+       /* XFER_PIO_0 */        0x06814ea7
+};
+
+static u32 fifty_base_hpt37x[] = {
+       /* XFER_UDMA_6 */       0x12848242,
+       /* XFER_UDMA_5 */       0x12848242,
+       /* XFER_UDMA_4 */       0x12ac8242,
+       /* XFER_UDMA_3 */       0x128c8242,
+       /* XFER_UDMA_2 */       0x120c8242,
+       /* XFER_UDMA_1 */       0x12148254,
+       /* XFER_UDMA_0 */       0x121882ea,
+
+       /* XFER_MW_DMA_2 */     0x22808242,
+       /* XFER_MW_DMA_1 */     0x22808254,
+       /* XFER_MW_DMA_0 */     0x228082ea,
+
+       /* XFER_PIO_4 */        0x0a81f442,
+       /* XFER_PIO_3 */        0x0a81f443,
+       /* XFER_PIO_2 */        0x0a81f454,
+       /* XFER_PIO_1 */        0x0ac1f465,
+       /* XFER_PIO_0 */        0x0ac1f48a
+};
+
+static u32 sixty_six_base_hpt37x[] = {
+       /* XFER_UDMA_6 */       0x1c869c62,
+       /* XFER_UDMA_5 */       0x1cae9c62,     /* 0x1c8a9c62 */
+       /* XFER_UDMA_4 */       0x1c8a9c62,
+       /* XFER_UDMA_3 */       0x1c8e9c62,
+       /* XFER_UDMA_2 */       0x1c929c62,
+       /* XFER_UDMA_1 */       0x1c9a9c62,
+       /* XFER_UDMA_0 */       0x1c829c62,
+
+       /* XFER_MW_DMA_2 */     0x2c829c62,
+       /* XFER_MW_DMA_1 */     0x2c829c66,
+       /* XFER_MW_DMA_0 */     0x2c829d2e,
+
+       /* XFER_PIO_4 */        0x0c829c62,
+       /* XFER_PIO_3 */        0x0c829c84,
+       /* XFER_PIO_2 */        0x0c829ca6,
+       /* XFER_PIO_1 */        0x0d029d26,
+       /* XFER_PIO_0 */        0x0d029d5e
+};
+#else
+/*
+ * The following are the new timing tables with PIO mode data/taskfile transfer
+ * overclocking fixed...
+ */
+
+/* This table is taken from the HPT370 data manual rev. 1.02 */
+static u32 thirty_three_base_hpt37x[] = {
+       /* XFER_UDMA_6 */       0x16455031,     /* 0x16655031 ?? */
+       /* XFER_UDMA_5 */       0x16455031,
+       /* XFER_UDMA_4 */       0x16455031,
+       /* XFER_UDMA_3 */       0x166d5031,
+       /* XFER_UDMA_2 */       0x16495031,
+       /* XFER_UDMA_1 */       0x164d5033,
+       /* XFER_UDMA_0 */       0x16515097,
+
+       /* XFER_MW_DMA_2 */     0x26515031,
+       /* XFER_MW_DMA_1 */     0x26515033,
+       /* XFER_MW_DMA_0 */     0x26515097,
+
+       /* XFER_PIO_4 */        0x06515021,
+       /* XFER_PIO_3 */        0x06515022,
+       /* XFER_PIO_2 */        0x06515033,
+       /* XFER_PIO_1 */        0x06915065,
+       /* XFER_PIO_0 */        0x06d1508a
+};
+
+static u32 fifty_base_hpt37x[] = {
+       /* XFER_UDMA_6 */       0x1a861842,
+       /* XFER_UDMA_5 */       0x1a861842,
+       /* XFER_UDMA_4 */       0x1aae1842,
+       /* XFER_UDMA_3 */       0x1a8e1842,
+       /* XFER_UDMA_2 */       0x1a0e1842,
+       /* XFER_UDMA_1 */       0x1a161854,
+       /* XFER_UDMA_0 */       0x1a1a18ea,
+
+       /* XFER_MW_DMA_2 */     0x2a821842,
+       /* XFER_MW_DMA_1 */     0x2a821854,
+       /* XFER_MW_DMA_0 */     0x2a8218ea,
+
+       /* XFER_PIO_4 */        0x0a821842,
+       /* XFER_PIO_3 */        0x0a821843,
+       /* XFER_PIO_2 */        0x0a821855,
+       /* XFER_PIO_1 */        0x0ac218a8,
+       /* XFER_PIO_0 */        0x0b02190c
+};
+
+static u32 sixty_six_base_hpt37x[] = {
+       /* XFER_UDMA_6 */       0x1c86fe62,
+       /* XFER_UDMA_5 */       0x1caefe62,     /* 0x1c8afe62 */
+       /* XFER_UDMA_4 */       0x1c8afe62,
+       /* XFER_UDMA_3 */       0x1c8efe62,
+       /* XFER_UDMA_2 */       0x1c92fe62,
+       /* XFER_UDMA_1 */       0x1c9afe62,
+       /* XFER_UDMA_0 */       0x1c82fe62,
+
+       /* XFER_MW_DMA_2 */     0x2c82fe62,
+       /* XFER_MW_DMA_1 */     0x2c82fe66,
+       /* XFER_MW_DMA_0 */     0x2c82ff2e,
+
+       /* XFER_PIO_4 */        0x0c82fe62,
+       /* XFER_PIO_3 */        0x0c82fe84,
+       /* XFER_PIO_2 */        0x0c82fea6,
+       /* XFER_PIO_1 */        0x0d02ff26,
+       /* XFER_PIO_0 */        0x0d42ff7f
+};
+#endif
+
+#define HPT366_DEBUG_DRIVE_INFO                0
+#define HPT371_ALLOW_ATA133_6          1
+#define HPT302_ALLOW_ATA133_6          1
+#define HPT372_ALLOW_ATA133_6          1
+#define HPT370_ALLOW_ATA100_5          0
+#define HPT366_ALLOW_ATA66_4           1
+#define HPT366_ALLOW_ATA66_3           1
+#define HPT366_MAX_DEVS                        8
+
+/* Supported ATA clock frequencies */
+enum ata_clock {
+       ATA_CLOCK_25MHZ,
+       ATA_CLOCK_33MHZ,
+       ATA_CLOCK_40MHZ,
+       ATA_CLOCK_50MHZ,
+       ATA_CLOCK_66MHZ,
+       NUM_ATA_CLOCKS
+};
+
+struct hpt_timings {
+       u32 pio_mask;
+       u32 dma_mask;
+       u32 ultra_mask;
+       u32 *clock_table[NUM_ATA_CLOCKS];
+};
+
+/*
+ *     Hold all the HighPoint chip information in one place.
+ */
+
+struct hpt_info {
+       char *chip_name;        /* Chip name */
+       u8 chip_type;           /* Chip type */
+       u8 udma_mask;           /* Allowed UltraDMA modes mask. */
+       u8 dpll_clk;            /* DPLL clock in MHz */
+       u8 pci_clk;             /* PCI  clock in MHz */
+       struct hpt_timings *timings; /* Chipset timing data */
+       u8 clock;               /* ATA clock selected */
+};
+
+/* Supported HighPoint chips */
+enum {
+       HPT36x,
+       HPT370,
+       HPT370A,
+       HPT374,
+       HPT372,
+       HPT372A,
+       HPT302,
+       HPT371,
+       HPT372N,
+       HPT302N,
+       HPT371N
+};
+
+static struct hpt_timings hpt36x_timings = {
+       .pio_mask       = 0xc1f8ffff,
+       .dma_mask       = 0x303800ff,
+       .ultra_mask     = 0x30070000,
+       .clock_table    = {
+               [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
+               [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
+               [ATA_CLOCK_40MHZ] = forty_base_hpt36x,
+               [ATA_CLOCK_50MHZ] = NULL,
+               [ATA_CLOCK_66MHZ] = NULL
+       }
+};
+
+static struct hpt_timings hpt37x_timings = {
+       .pio_mask       = 0xcfc3ffff,
+       .dma_mask       = 0x31c001ff,
+       .ultra_mask     = 0x303c0000,
+       .clock_table    = {
+               [ATA_CLOCK_25MHZ] = NULL,
+               [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
+               [ATA_CLOCK_40MHZ] = NULL,
+               [ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
+               [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
+       }
+};
+
+static const struct hpt_info hpt36x __devinitdata = {
+       .chip_name      = "HPT36x",
+       .chip_type      = HPT36x,
+       .udma_mask      = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
+       .dpll_clk       = 0,    /* no DPLL */
+       .timings        = &hpt36x_timings
+};
+
+static const struct hpt_info hpt370 __devinitdata = {
+       .chip_name      = "HPT370",
+       .chip_type      = HPT370,
+       .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
+       .dpll_clk       = 48,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt370a __devinitdata = {
+       .chip_name      = "HPT370A",
+       .chip_type      = HPT370A,
+       .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
+       .dpll_clk       = 48,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt374 __devinitdata = {
+       .chip_name      = "HPT374",
+       .chip_type      = HPT374,
+       .udma_mask      = ATA_UDMA5,
+       .dpll_clk       = 48,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt372 __devinitdata = {
+       .chip_name      = "HPT372",
+       .chip_type      = HPT372,
+       .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 55,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt372a __devinitdata = {
+       .chip_name      = "HPT372A",
+       .chip_type      = HPT372A,
+       .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 66,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt302 __devinitdata = {
+       .chip_name      = "HPT302",
+       .chip_type      = HPT302,
+       .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 66,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt371 __devinitdata = {
+       .chip_name      = "HPT371",
+       .chip_type      = HPT371,
+       .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 66,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt372n __devinitdata = {
+       .chip_name      = "HPT372N",
+       .chip_type      = HPT372N,
+       .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 77,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt302n __devinitdata = {
+       .chip_name      = "HPT302N",
+       .chip_type      = HPT302N,
+       .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 77,
+       .timings        = &hpt37x_timings
+};
+
+static const struct hpt_info hpt371n __devinitdata = {
+       .chip_name      = "HPT371N",
+       .chip_type      = HPT371N,
+       .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+       .dpll_clk       = 77,
+       .timings        = &hpt37x_timings
+};
+
+static int check_in_drive_list(ide_drive_t *drive, const char **list)
+{
+       char *m = (char *)&drive->id[ATA_ID_PROD];
+
+       while (*list)
+               if (!strcmp(*list++, m))
+                       return 1;
+       return 0;
+}
+
+static struct hpt_info *hpt3xx_get_info(struct device *dev)
+{
+       struct ide_host *host   = dev_get_drvdata(dev);
+       struct hpt_info *info   = (struct hpt_info *)host->host_priv;
+
+       return dev == host->dev[1] ? info + 1 : info;
+}
+
+/*
+ * The Marvell bridge chips used on the HighPoint SATA cards do not seem
+ * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
+ */
+
+static u8 hpt3xx_udma_filter(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
+       u8 mask                 = hwif->ultra_mask;
+
+       switch (info->chip_type) {
+       case HPT36x:
+               if (!HPT366_ALLOW_ATA66_4 ||
+                   check_in_drive_list(drive, bad_ata66_4))
+                       mask = ATA_UDMA3;
+
+               if (!HPT366_ALLOW_ATA66_3 ||
+                   check_in_drive_list(drive, bad_ata66_3))
+                       mask = ATA_UDMA2;
+               break;
+       case HPT370:
+               if (!HPT370_ALLOW_ATA100_5 ||
+                   check_in_drive_list(drive, bad_ata100_5))
+                       mask = ATA_UDMA4;
+               break;
+       case HPT370A:
+               if (!HPT370_ALLOW_ATA100_5 ||
+                   check_in_drive_list(drive, bad_ata100_5))
+                       return ATA_UDMA4;
+       case HPT372 :
+       case HPT372A:
+       case HPT372N:
+       case HPT374 :
+               if (ata_id_is_sata(drive->id))
+                       mask &= ~0x0e;
+               /* Fall thru */
+       default:
+               return mask;
+       }
+
+       return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
+}
+
+static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
+
+       switch (info->chip_type) {
+       case HPT372 :
+       case HPT372A:
+       case HPT372N:
+       case HPT374 :
+               if (ata_id_is_sata(drive->id))
+                       return 0x00;
+               /* Fall thru */
+       default:
+               return 0x07;
+       }
+}
+
+static u32 get_speed_setting(u8 speed, struct hpt_info *info)
+{
+       int i;
+
+       /*
+        * Lookup the transfer mode table to get the index into
+        * the timing table.
+        *
+        * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
+        */
+       for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
+               if (xfer_speeds[i] == speed)
+                       break;
+
+       return info->timings->clock_table[info->clock][i];
+}
+
+static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif        = drive->hwif;
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
+       struct hpt_timings *t   = info->timings;
+       u8  itr_addr            = 0x40 + (drive->dn * 4);
+       u32 old_itr             = 0;
+       u32 new_itr             = get_speed_setting(speed, info);
+       u32 itr_mask            = speed < XFER_MW_DMA_0 ? t->pio_mask :
+                                (speed < XFER_UDMA_0   ? t->dma_mask :
+                                                         t->ultra_mask);
+
+       pci_read_config_dword(dev, itr_addr, &old_itr);
+       new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
+       /*
+        * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
+        * to avoid problems handling I/O errors later
+        */
+       new_itr &= ~0xc0000000;
+
+       pci_write_config_dword(dev, itr_addr, new_itr);
+}
+
+static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
+}
+
+static void hpt3xx_quirkproc(ide_drive_t *drive)
+{
+       char *m                 = (char *)&drive->id[ATA_ID_PROD];
+       const  char **list      = quirk_drives;
+
+       while (*list)
+               if (strstr(m, *list++)) {
+                       drive->quirk_list = 1;
+                       return;
+               }
+
+       drive->quirk_list = 0;
+}
+
+static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev  *dev    = to_pci_dev(hwif->dev);
+       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
+
+       if (drive->quirk_list == 0)
+               return;
+
+       if (info->chip_type >= HPT370) {
+               u8 scr1 = 0;
+
+               pci_read_config_byte(dev, 0x5a, &scr1);
+               if (((scr1 & 0x10) >> 4) != mask) {
+                       if (mask)
+                               scr1 |=  0x10;
+                       else
+                               scr1 &= ~0x10;
+                       pci_write_config_byte(dev, 0x5a, scr1);
+               }
+       } else if (mask)
+               disable_irq(hwif->irq);
+       else
+               enable_irq(hwif->irq);
+}
+
+/*
+ * This is specific to the HPT366 UDMA chipset
+ * by HighPoint|Triones Technologies, Inc.
+ */
+static void hpt366_dma_lost_irq(ide_drive_t *drive)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
+
+       pci_read_config_byte(dev, 0x50, &mcr1);
+       pci_read_config_byte(dev, 0x52, &mcr3);
+       pci_read_config_byte(dev, 0x5a, &scr1);
+       printk("%s: (%s)  mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",
+               drive->name, __func__, mcr1, mcr3, scr1);
+       if (scr1 & 0x10)
+               pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
+       ide_dma_lost_irq(drive);
+}
+
+static void hpt370_clear_engine(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       pci_write_config_byte(dev, hwif->select_data, 0x37);
+       udelay(10);
+}
+
+static void hpt370_irq_timeout(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u16 bfifo               = 0;
+       u8  dma_cmd;
+
+       pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
+       printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
+
+       /* get DMA command mode */
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+       /* stop DMA */
+       outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
+       hpt370_clear_engine(drive);
+}
+
+static void hpt370_dma_start(ide_drive_t *drive)
+{
+#ifdef HPT_RESET_STATE_ENGINE
+       hpt370_clear_engine(drive);
+#endif
+       ide_dma_start(drive);
+}
+
+static int hpt370_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       u8  dma_stat            = inb(hwif->dma_base + ATA_DMA_STATUS);
+
+       if (dma_stat & 0x01) {
+               /* wait a little */
+               udelay(20);
+               dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
+               if (dma_stat & 0x01)
+                       hpt370_irq_timeout(drive);
+       }
+       return ide_dma_end(drive);
+}
+
+static void hpt370_dma_timeout(ide_drive_t *drive)
+{
+       hpt370_irq_timeout(drive);
+       ide_dma_timeout(drive);
+}
+
+/* returns 1 if DMA IRQ issued, 0 otherwise */
+static int hpt374_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u16 bfifo               = 0;
+       u8  dma_stat;
+
+       pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
+       if (bfifo & 0x1FF) {
+//             printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
+               return 0;
+       }
+
+       dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
+       /* return 1 if INTR asserted */
+       if (dma_stat & 4)
+               return 1;
+
+       return 0;
+}
+
+static int hpt374_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u8 mcr  = 0, mcr_addr   = hwif->select_data;
+       u8 bwsr = 0, mask       = hwif->channel ? 0x02 : 0x01;
+
+       pci_read_config_byte(dev, 0x6a, &bwsr);
+       pci_read_config_byte(dev, mcr_addr, &mcr);
+       if (bwsr & mask)
+               pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
+       return ide_dma_end(drive);
+}
+
+/**
+ *     hpt3xxn_set_clock       -       perform clock switching dance
+ *     @hwif: hwif to switch
+ *     @mode: clocking mode (0x21 for write, 0x23 otherwise)
+ *
+ *     Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
+ */
+
+static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
+{
+       unsigned long base = hwif->extra_base;
+       u8 scr2 = inb(base + 0x6b);
+
+       if ((scr2 & 0x7f) == mode)
+               return;
+
+       /* Tristate the bus */
+       outb(0x80, base + 0x63);
+       outb(0x80, base + 0x67);
+
+       /* Switch clock and reset channels */
+       outb(mode, base + 0x6b);
+       outb(0xc0, base + 0x69);
+
+       /*
+        * Reset the state machines.
+        * NOTE: avoid accidentally enabling the disabled channels.
+        */
+       outb(inb(base + 0x60) | 0x32, base + 0x60);
+       outb(inb(base + 0x64) | 0x32, base + 0x64);
+
+       /* Complete reset */
+       outb(0x00, base + 0x69);
+
+       /* Reconnect channels to bus */
+       outb(0x00, base + 0x63);
+       outb(0x00, base + 0x67);
+}
+
+/**
+ *     hpt3xxn_rw_disk         -       prepare for I/O
+ *     @drive: drive for command
+ *     @rq: block request structure
+ *
+ *     This is called when a disk I/O is issued to HPT3xxN.
+ *     We need it because of the clock switching.
+ */
+
+static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
+{
+       hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
+}
+
+/**
+ *     hpt37x_calibrate_dpll   -       calibrate the DPLL
+ *     @dev: PCI device
+ *
+ *     Perform a calibration cycle on the DPLL.
+ *     Returns 1 if this succeeds
+ */
+static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
+{
+       u32 dpll = (f_high << 16) | f_low | 0x100;
+       u8  scr2;
+       int i;
+
+       pci_write_config_dword(dev, 0x5c, dpll);
+
+       /* Wait for oscillator ready */
+       for(i = 0; i < 0x5000; ++i) {
+               udelay(50);
+               pci_read_config_byte(dev, 0x5b, &scr2);
+               if (scr2 & 0x80)
+                       break;
+       }
+       /* See if it stays ready (we'll just bail out if it's not yet) */
+       for(i = 0; i < 0x1000; ++i) {
+               pci_read_config_byte(dev, 0x5b, &scr2);
+               /* DPLL destabilized? */
+               if(!(scr2 & 0x80))
+                       return 0;
+       }
+       /* Turn off tuning, we have the DPLL set */
+       pci_read_config_dword (dev, 0x5c, &dpll);
+       pci_write_config_dword(dev, 0x5c, (dpll & ~0x100));
+       return 1;
+}
+
+static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
+{
+       struct ide_host *host   = pci_get_drvdata(dev);
+       struct hpt_info *info   = host->host_priv + (&dev->dev == host->dev[1]);
+       u8  chip_type           = info->chip_type;
+       u8  new_mcr, old_mcr    = 0;
+
+       /*
+        * Disable the "fast interrupt" prediction.  Don't hold off
+        * on interrupts. (== 0x01 despite what the docs say)
+        */
+       pci_read_config_byte(dev, mcr_addr + 1, &old_mcr);
+
+       if (chip_type >= HPT374)
+               new_mcr = old_mcr & ~0x07;
+       else if (chip_type >= HPT370) {
+               new_mcr = old_mcr;
+               new_mcr &= ~0x02;
+#ifdef HPT_DELAY_INTERRUPT
+               new_mcr &= ~0x01;
+#else
+               new_mcr |=  0x01;
+#endif
+       } else                                  /* HPT366 and HPT368  */
+               new_mcr = old_mcr & ~0x80;
+
+       if (new_mcr != old_mcr)
+               pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
+}
+
+static unsigned int init_chipset_hpt366(struct pci_dev *dev)
+{
+       unsigned long io_base   = pci_resource_start(dev, 4);
+       struct hpt_info *info   = hpt3xx_get_info(&dev->dev);
+       const char *name        = DRV_NAME;
+       u8 pci_clk,  dpll_clk   = 0;    /* PCI and DPLL clock in MHz */
+       u8 chip_type;
+       enum ata_clock  clock;
+
+       chip_type = info->chip_type;
+
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+       pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+       pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+
+       /*
+        * First, try to estimate the PCI clock frequency...
+        */
+       if (chip_type >= HPT370) {
+               u8  scr1  = 0;
+               u16 f_cnt = 0;
+               u32 temp  = 0;
+
+               /* Interrupt force enable. */
+               pci_read_config_byte(dev, 0x5a, &scr1);
+               if (scr1 & 0x10)
+                       pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
+
+               /*
+                * HighPoint does this for HPT372A.
+                * NOTE: This register is only writeable via I/O space.
+                */
+               if (chip_type == HPT372A)
+                       outb(0x0e, io_base + 0x9c);
+
+               /*
+                * Default to PCI clock. Make sure MA15/16 are set to output
+                * to prevent drives having problems with 40-pin cables.
+                */
+               pci_write_config_byte(dev, 0x5b, 0x23);
+
+               /*
+                * We'll have to read f_CNT value in order to determine
+                * the PCI clock frequency according to the following ratio:
+                *
+                * f_CNT = Fpci * 192 / Fdpll
+                *
+                * First try reading the register in which the HighPoint BIOS
+                * saves f_CNT value before  reprogramming the DPLL from its
+                * default setting (which differs for the various chips).
+                *
+                * NOTE: This register is only accessible via I/O space;
+                * HPT374 BIOS only saves it for the function 0, so we have to
+                * always read it from there -- no need to check the result of
+                * pci_get_slot() for the function 0 as the whole device has
+                * been already "pinned" (via function 1) in init_setup_hpt374()
+                */
+               if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
+                       struct pci_dev  *dev1 = pci_get_slot(dev->bus,
+                                                            dev->devfn - 1);
+                       unsigned long io_base = pci_resource_start(dev1, 4);
+
+                       temp =  inl(io_base + 0x90);
+                       pci_dev_put(dev1);
+               } else
+                       temp =  inl(io_base + 0x90);
+
+               /*
+                * In case the signature check fails, we'll have to
+                * resort to reading the f_CNT register itself in hopes
+                * that nobody has touched the DPLL yet...
+                */
+               if ((temp & 0xFFFFF000) != 0xABCDE000) {
+                       int i;
+
+                       printk(KERN_WARNING "%s %s: no clock data saved by "
+                               "BIOS\n", name, pci_name(dev));
+
+                       /* Calculate the average value of f_CNT. */
+                       for (temp = i = 0; i < 128; i++) {
+                               pci_read_config_word(dev, 0x78, &f_cnt);
+                               temp += f_cnt & 0x1ff;
+                               mdelay(1);
+                       }
+                       f_cnt = temp / 128;
+               } else
+                       f_cnt = temp & 0x1ff;
+
+               dpll_clk = info->dpll_clk;
+               pci_clk  = (f_cnt * dpll_clk) / 192;
+
+               /* Clamp PCI clock to bands. */
+               if (pci_clk < 40)
+                       pci_clk = 33;
+               else if(pci_clk < 45)
+                       pci_clk = 40;
+               else if(pci_clk < 55)
+                       pci_clk = 50;
+               else
+                       pci_clk = 66;
+
+               printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
+                       "assuming %d MHz PCI\n", name, pci_name(dev),
+                       dpll_clk, f_cnt, pci_clk);
+       } else {
+               u32 itr1 = 0;
+
+               pci_read_config_dword(dev, 0x40, &itr1);
+
+               /* Detect PCI clock by looking at cmd_high_time. */
+               switch((itr1 >> 8) & 0x07) {
+                       case 0x09:
+                               pci_clk = 40;
+                               break;
+                       case 0x05:
+                               pci_clk = 25;
+                               break;
+                       case 0x07:
+                       default:
+                               pci_clk = 33;
+                               break;
+               }
+       }
+
+       /* Let's assume we'll use PCI clock for the ATA clock... */
+       switch (pci_clk) {
+               case 25:
+                       clock = ATA_CLOCK_25MHZ;
+                       break;
+               case 33:
+               default:
+                       clock = ATA_CLOCK_33MHZ;
+                       break;
+               case 40:
+                       clock = ATA_CLOCK_40MHZ;
+                       break;
+               case 50:
+                       clock = ATA_CLOCK_50MHZ;
+                       break;
+               case 66:
+                       clock = ATA_CLOCK_66MHZ;
+                       break;
+       }
+
+       /*
+        * Only try the DPLL if we don't have a table for the PCI clock that
+        * we are running at for HPT370/A, always use it  for anything newer...
+        *
+        * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI.
+        * We also  don't like using  the DPLL because this causes glitches
+        * on PRST-/SRST- when the state engine gets reset...
+        */
+       if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
+               u16 f_low, delta = pci_clk < 50 ? 2 : 4;
+               int adjust;
+
+                /*
+                 * Select 66 MHz DPLL clock only if UltraATA/133 mode is
+                 * supported/enabled, use 50 MHz DPLL clock otherwise...
+                 */
+               if (info->udma_mask == ATA_UDMA6) {
+                       dpll_clk = 66;
+                       clock = ATA_CLOCK_66MHZ;
+               } else if (dpll_clk) {  /* HPT36x chips don't have DPLL */
+                       dpll_clk = 50;
+                       clock = ATA_CLOCK_50MHZ;
+               }
+
+               if (info->timings->clock_table[clock] == NULL) {
+                       printk(KERN_ERR "%s %s: unknown bus timing!\n",
+                               name, pci_name(dev));
+                       return -EIO;
+               }
+
+               /* Select the DPLL clock. */
+               pci_write_config_byte(dev, 0x5b, 0x21);
+
+               /*
+                * Adjust the DPLL based upon PCI clock, enable it,
+                * and wait for stabilization...
+                */
+               f_low = (pci_clk * 48) / dpll_clk;
+
+               for (adjust = 0; adjust < 8; adjust++) {
+                       if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta))
+                               break;
+
+                       /*
+                        * See if it'll settle at a fractionally different clock
+                        */
+                       if (adjust & 1)
+                               f_low -= adjust >> 1;
+                       else
+                               f_low += adjust >> 1;
+               }
+               if (adjust == 8) {
+                       printk(KERN_ERR "%s %s: DPLL did not stabilize!\n",
+                               name, pci_name(dev));
+                       return -EIO;
+               }
+
+               printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n",
+                       name, pci_name(dev), dpll_clk);
+       } else {
+               /* Mark the fact that we're not using the DPLL. */
+               dpll_clk = 0;
+
+               printk(KERN_INFO "%s %s: using %d MHz PCI clock\n",
+                       name, pci_name(dev), pci_clk);
+       }
+
+       /* Store the clock frequencies. */
+       info->dpll_clk  = dpll_clk;
+       info->pci_clk   = pci_clk;
+       info->clock     = clock;
+
+       if (chip_type >= HPT370) {
+               u8  mcr1, mcr4;
+
+               /*
+                * Reset the state engines.
+                * NOTE: Avoid accidentally enabling the disabled channels.
+                */
+               pci_read_config_byte (dev, 0x50, &mcr1);
+               pci_read_config_byte (dev, 0x54, &mcr4);
+               pci_write_config_byte(dev, 0x50, (mcr1 | 0x32));
+               pci_write_config_byte(dev, 0x54, (mcr4 | 0x32));
+               udelay(100);
+       }
+
+       /*
+        * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
+        * the MISC. register to stretch the UltraDMA Tss timing.
+        * NOTE: This register is only writeable via I/O space.
+        */
+       if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
+               outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
+
+       hpt3xx_disable_fast_irq(dev, 0x50);
+       hpt3xx_disable_fast_irq(dev, 0x54);
+
+       return dev->irq;
+}
+
+static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev  *dev    = to_pci_dev(hwif->dev);
+       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
+       u8 chip_type            = info->chip_type;
+       u8 scr1 = 0, ata66      = hwif->channel ? 0x01 : 0x02;
+
+       /*
+        * The HPT37x uses the CBLID pins as outputs for MA15/MA16
+        * address lines to access an external EEPROM.  To read valid
+        * cable detect state the pins must be enabled as inputs.
+        */
+       if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
+               /*
+                * HPT374 PCI function 1
+                * - set bit 15 of reg 0x52 to enable TCBLID as input
+                * - set bit 15 of reg 0x56 to enable FCBLID as input
+                */
+               u8  mcr_addr = hwif->select_data + 2;
+               u16 mcr;
+
+               pci_read_config_word(dev, mcr_addr, &mcr);
+               pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
+               /* now read cable id register */
+               pci_read_config_byte(dev, 0x5a, &scr1);
+               pci_write_config_word(dev, mcr_addr, mcr);
+       } else if (chip_type >= HPT370) {
+               /*
+                * HPT370/372 and 374 pcifn 0
+                * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
+                */
+               u8 scr2 = 0;
+
+               pci_read_config_byte(dev, 0x5b, &scr2);
+               pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
+               /* now read cable id register */
+               pci_read_config_byte(dev, 0x5a, &scr1);
+               pci_write_config_byte(dev, 0x5b,  scr2);
+       } else
+               pci_read_config_byte(dev, 0x5a, &scr1);
+
+       return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+{
+       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
+       int serialize           = HPT_SERIALIZE_IO;
+       u8  chip_type           = info->chip_type;
+
+       /* Cache the channel's MISC. control registers' offset */
+       hwif->select_data       = hwif->channel ? 0x54 : 0x50;
+
+       /*
+        * HPT3xxN chips have some complications:
+        *
+        * - on 33 MHz PCI we must clock switch
+        * - on 66 MHz PCI we must NOT use the PCI clock
+        */
+       if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) {
+               /*
+                * Clock is shared between the channels,
+                * so we'll have to serialize them... :-(
+                */
+               serialize = 1;
+               hwif->rw_disk = &hpt3xxn_rw_disk;
+       }
+
+       /* Serialize access to this device if needed */
+       if (serialize && hwif->mate)
+               hwif->serialized = hwif->mate->serialized = 1;
+}
+
+static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
+                                    const struct ide_port_info *d)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long flags, base = ide_pci_dma_base(hwif, d);
+       u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
+
+       if (base == 0)
+               return -1;
+
+       hwif->dma_base = base;
+
+       if (ide_pci_check_simplex(hwif, d) < 0)
+               return -1;
+
+       if (ide_pci_set_master(dev, d->name) < 0)
+               return -1;
+
+       dma_old = inb(base + 2);
+
+       local_irq_save(flags);
+
+       dma_new = dma_old;
+       pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma);
+       pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47,  &slavedma);
+
+       if (masterdma & 0x30)   dma_new |= 0x20;
+       if ( slavedma & 0x30)   dma_new |= 0x40;
+       if (dma_new != dma_old)
+               outb(dma_new, base + 2);
+
+       local_irq_restore(flags);
+
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+                        hwif->name, base, base + 7);
+
+       hwif->extra_base = base + (hwif->channel ? 8 : 16);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       hwif->dma_ops = &sff_dma_ops;
+
+       return 0;
+}
+
+static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
+{
+       if (dev2->irq != dev->irq) {
+               /* FIXME: we need a core pci_set_interrupt() */
+               dev2->irq = dev->irq;
+               printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
+                       "fixed\n", pci_name(dev2));
+       }
+}
+
+static void __devinit hpt371_init(struct pci_dev *dev)
+{
+       u8 mcr1 = 0;
+
+       /*
+        * HPT371 chips physically have only one channel, the secondary one,
+        * but the primary channel registers do exist!  Go figure...
+        * So,  we manually disable the non-existing channel here
+        * (if the BIOS hasn't done this already).
+        */
+       pci_read_config_byte(dev, 0x50, &mcr1);
+       if (mcr1 & 0x04)
+               pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
+}
+
+static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
+{
+       u8 mcr1 = 0, pin1 = 0, pin2 = 0;
+
+       /*
+        * Now we'll have to force both channels enabled if
+        * at least one of them has been enabled by BIOS...
+        */
+       pci_read_config_byte(dev, 0x50, &mcr1);
+       if (mcr1 & 0x30)
+               pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
+
+       pci_read_config_byte(dev,  PCI_INTERRUPT_PIN, &pin1);
+       pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
+
+       if (pin1 != pin2 && dev->irq == dev2->irq) {
+               printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
+                       "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2);
+               return 1;
+       }
+
+       return 0;
+}
+
+#define IDE_HFLAGS_HPT3XX \
+       (IDE_HFLAG_NO_ATAPI_DMA | \
+        IDE_HFLAG_OFF_BOARD)
+
+static const struct ide_port_ops hpt3xx_port_ops = {
+       .set_pio_mode           = hpt3xx_set_pio_mode,
+       .set_dma_mode           = hpt3xx_set_mode,
+       .quirkproc              = hpt3xx_quirkproc,
+       .maskproc               = hpt3xx_maskproc,
+       .mdma_filter            = hpt3xx_mdma_filter,
+       .udma_filter            = hpt3xx_udma_filter,
+       .cable_detect           = hpt3xx_cable_detect,
+};
+
+static const struct ide_dma_ops hpt37x_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                = hpt374_dma_end,
+       .dma_test_irq           = hpt374_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_dma_ops hpt370_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = hpt370_dma_start,
+       .dma_end                = hpt370_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = hpt370_dma_timeout,
+};
+
+static const struct ide_dma_ops hpt36x_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_lost_irq           = hpt366_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+       {       /* 0: HPT36x */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               /*
+                * HPT36x chips have one channel per function and have
+                * both channel enable bits located differently and visible
+                * to both functions -- really stupid design decision... :-(
+                * Bit 4 is for the primary channel, bit 5 for the secondary.
+                */
+               .enablebits     = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt36x_dma_ops,
+               .host_flags     = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+       },
+       {       /* 1: HPT3xx */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+               .port_ops       = &hpt3xx_port_ops,
+               .dma_ops        = &hpt37x_dma_ops,
+               .host_flags     = IDE_HFLAGS_HPT3XX,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+       }
+};
+
+/**
+ *     hpt366_init_one -       called when an HPT366 is found
+ *     @dev: the hpt366 device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       const struct hpt_info *info = NULL;
+       struct hpt_info *dyn_info;
+       struct pci_dev *dev2 = NULL;
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+       u8 rev = dev->revision;
+       int ret;
+
+       if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
+               return -ENODEV;
+
+       switch (idx) {
+       case 0:
+               if (rev < 3)
+                       info = &hpt36x;
+               else {
+                       switch (min_t(u8, rev, 6)) {
+                       case 3: info = &hpt370;  break;
+                       case 4: info = &hpt370a; break;
+                       case 5: info = &hpt372;  break;
+                       case 6: info = &hpt372n; break;
+                       }
+                       idx++;
+               }
+               break;
+       case 1:
+               info = (rev > 1) ? &hpt372n : &hpt372a;
+               break;
+       case 2:
+               info = (rev > 1) ? &hpt302n : &hpt302;
+               break;
+       case 3:
+               hpt371_init(dev);
+               info = (rev > 1) ? &hpt371n : &hpt371;
+               break;
+       case 4:
+               info = &hpt374;
+               break;
+       case 5:
+               info = &hpt372n;
+               break;
+       }
+
+       printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name);
+
+       d = hpt366_chipsets[min_t(u8, idx, 1)];
+
+       d.udma_mask = info->udma_mask;
+
+       /* fixup ->dma_ops for HPT370/HPT370A */
+       if (info == &hpt370 || info == &hpt370a)
+               d.dma_ops = &hpt370_dma_ops;
+
+       if (info == &hpt36x || info == &hpt374)
+               dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
+
+       dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
+       if (dyn_info == NULL) {
+               printk(KERN_ERR "%s %s: out of memory!\n",
+                       d.name, pci_name(dev));
+               pci_dev_put(dev2);
+               return -ENOMEM;
+       }
+
+       /*
+        * Copy everything from a static "template" structure
+        * to just allocated per-chip hpt_info structure.
+        */
+       memcpy(dyn_info, info, sizeof(*dyn_info));
+
+       if (dev2) {
+               memcpy(dyn_info + 1, info, sizeof(*dyn_info));
+
+               if (info == &hpt374)
+                       hpt374_init(dev, dev2);
+               else {
+                       if (hpt36x_init(dev, dev2))
+                               d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
+               }
+
+               ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
+               if (ret < 0) {
+                       pci_dev_put(dev2);
+                       kfree(dyn_info);
+               }
+               return ret;
+       }
+
+       ret = ide_pci_init_one(dev, &d, dyn_info);
+       if (ret < 0)
+               kfree(dyn_info);
+
+       return ret;
+}
+
+static void __devexit hpt366_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct ide_info *info = host->host_priv;
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+       ide_pci_remove(dev);
+       pci_dev_put(dev2);
+       kfree(info);
+}
+
+static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
+       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366),  0 },
+       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372),  1 },
+       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302),  2 },
+       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371),  3 },
+       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374),  4 },
+       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
+
+static struct pci_driver hpt366_pci_driver = {
+       .name           = "HPT366_IDE",
+       .id_table       = hpt366_pci_tbl,
+       .probe          = hpt366_init_one,
+       .remove         = __devexit_p(hpt366_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init hpt366_ide_init(void)
+{
+       return ide_pci_register_driver(&hpt366_pci_driver);
+}
+
+static void __exit hpt366_ide_exit(void)
+{
+       pci_unregister_driver(&hpt366_pci_driver);
+}
+
+module_init(hpt366_ide_init);
+module_exit(hpt366_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
new file mode 100644 (file)
index 0000000..c7e5c22
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
+ */
+
+/*
+ *  HT-6560B EIDE-controller support
+ *  To activate controller support use kernel parameter "ide0=ht6560b".
+ *  Use hdparm utility to enable PIO mode support.
+ *
+ *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
+ *             Jan Evert van Grootheest   <j.e.van.grootheest@caiway.nl>
+ *
+ *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
+ */
+
+#define DRV_NAME       "ht6560b"
+#define HT6560B_VERSION "v0.08"
+
+#include <linux/module.h>
+#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/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+/* #define DEBUG */  /* remove comments for DEBUG messages */
+
+/*
+ * The special i/o-port that HT-6560B uses to configuration:
+ *    bit0 (0x01): "1" selects secondary interface
+ *    bit2 (0x04): "1" enables FIFO function
+ *    bit5 (0x20): "1" enables prefetched data read function  (???)
+ *
+ * The special i/o-port that HT-6560A uses to configuration:
+ *    bit0 (0x01): "1" selects secondary interface
+ *    bit1 (0x02): "1" enables prefetched data read function
+ *    bit2 (0x04): "0" enables multi-master system           (?)
+ *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time        (?)
+ */
+#define HT_CONFIG_PORT   0x3e6
+#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
+/*
+ * FIFO + PREFETCH (both a/b-model)
+ */
+#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
+/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
+#define HT_SECONDARY_IF          0x01
+#define HT_PREFETCH_MODE  0x20
+
+/*
+ * ht6560b Timing values:
+ *
+ * I reviewed some assembler source listings of htide drivers and found
+ * out how they setup those cycle time interfacing values, as they at Holtek
+ * call them. IDESETUP.COM that is supplied with the drivers figures out
+ * optimal values and fetches those values to drivers. I found out that
+ * they use Select register to fetch timings to the ide board right after
+ * interface switching. After that it was quite easy to add code to
+ * ht6560b.c.
+ *
+ * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
+ * for hda and hdc. But hdb needed higher values to work, so I guess
+ * that sometimes it is necessary to give higher value than IDESETUP
+ * gives.   [see cmd640.c for an extreme example of this. -ml]
+ *
+ * Perhaps I should explain something about these timing values:
+ * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
+ * of the value is the Active Time  (at). Minimum value 2 is the fastest and
+ * the maximum value 15 is the slowest. Default values should be 15 for both.
+ * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
+ * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
+ * similar. If value is too small there will be all sorts of failures.
+ *
+ * Timing byte consists of
+ *     High nibble:  Recovery Cycle Time  (rt)
+ *          The valid values range from 2 to 15. The default is 15.
+ *
+ *     Low nibble:   Active Cycle Time    (at)
+ *          The valid values range from 2 to 15. The default is 15.
+ *
+ * You can obtain optimized timing values by running Holtek IDESETUP.COM
+ * for DOS. DOS drivers get their timing values from command line, where
+ * the first value is the Recovery Time and the second value is the
+ * Active Time for each drive. Smaller value gives higher speed.
+ * In case of failures you should probably fall back to a higher value.
+ */
+#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
+#define HT_TIMING_DEFAULT 0xff
+
+/*
+ * This routine handles interface switching for the peculiar hardware design
+ * on the F.G.I./Holtek HT-6560B VLB IDE interface.
+ * The HT-6560B can only enable one IDE port at a time, and requires a
+ * silly sequence (below) whenever we switch between primary and secondary.
+ */
+
+/*
+ * This routine is invoked from ide.c to prepare for access to a given drive.
+ */
+static void ht6560b_selectproc (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       unsigned long flags;
+       static u8 current_select = 0;
+       static u8 current_timing = 0;
+       u8 select, timing;
+       
+       local_irq_save(flags);
+
+       select = HT_CONFIG(drive);
+       timing = HT_TIMING(drive);
+
+       /*
+        * Need to enforce prefetch sometimes because otherwise
+        * it'll hang (hard).
+        */
+       if (drive->media != ide_disk ||
+           (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
+               select |= HT_PREFETCH_MODE;
+
+       if (select != current_select || timing != current_timing) {
+               current_select = select;
+               current_timing = timing;
+               (void)inb(HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               (void)inb(HT_CONFIG_PORT);
+               outb(select, HT_CONFIG_PORT);
+               /*
+                * Set timing for this drive:
+                */
+               outb(timing, hwif->io_ports.device_addr);
+               (void)inb(hwif->io_ports.status_addr);
+#ifdef DEBUG
+               printk("ht6560b: %s: select=%#x timing=%#x\n",
+                       drive->name, select, timing);
+#endif
+       }
+       local_irq_restore(flags);
+}
+
+/*
+ * Autodetection and initialization of ht6560b
+ */
+static int __init try_to_init_ht6560b(void)
+{
+       u8 orig_value;
+       int i;
+       
+       /* Autodetect ht6560b */
+       if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
+               return 0;
+       
+       for (i=3;i>0;i--) {
+               outb(0x00, HT_CONFIG_PORT);
+               if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
+                       outb(orig_value, HT_CONFIG_PORT);
+                       return 0;
+               }
+       }
+       outb(0x00, HT_CONFIG_PORT);
+       if ((~inb(HT_CONFIG_PORT))& 0x3f) {
+               outb(orig_value, HT_CONFIG_PORT);
+               return 0;
+       }
+       /*
+        * Ht6560b autodetected
+        */
+       outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
+       outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */
+       (void)inb(0x1f7);               /* Status register */
+
+       printk("ht6560b " HT6560B_VERSION
+              ": chipset detected and initialized"
+#ifdef DEBUG
+              " with debug enabled"
+#endif
+              "\n"
+               );
+       return 1;
+}
+
+static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
+{
+       int active_time, recovery_time;
+       int active_cycles, recovery_cycles;
+       int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
+
+        if (pio) {
+               unsigned int cycle_time;
+               struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+
+               cycle_time = ide_pio_cycle_time(drive, pio);
+
+               /*
+                *  Just like opti621.c we try to calculate the
+                *  actual cycle time for recovery and activity
+                *  according system bus speed.
+                */
+               active_time = t->active;
+               recovery_time = cycle_time - active_time - t->setup;
+               /*
+                *  Cycle times should be Vesa bus cycles
+                */
+               active_cycles   = (active_time   * bus_speed + 999) / 1000;
+               recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
+               /*
+                *  Upper and lower limits
+                */
+               if (active_cycles   < 2)  active_cycles   = 2;
+               if (recovery_cycles < 2)  recovery_cycles = 2;
+               if (active_cycles   > 15) active_cycles   = 15;
+               if (recovery_cycles > 15) recovery_cycles = 0;  /* 0==16 */
+               
+#ifdef DEBUG
+               printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
+#endif
+               
+               return (u8)((recovery_cycles << 4) | active_cycles);
+       } else {
+               
+#ifdef DEBUG
+               printk("ht6560b: drive %s setting pio=0\n", drive->name);
+#endif
+               
+               return HT_TIMING_DEFAULT;    /* default setting */
+       }
+}
+
+static DEFINE_SPINLOCK(ht6560b_lock);
+
+/*
+ *  Enable/Disable so called prefetch mode
+ */
+static void ht_set_prefetch(ide_drive_t *drive, u8 state)
+{
+       unsigned long flags;
+       int t = HT_PREFETCH_MODE << 8;
+
+       spin_lock_irqsave(&ht6560b_lock, flags);
+
+       /*
+        *  Prefetch mode and unmask irq seems to conflict
+        */
+       if (state) {
+               drive->drive_data |= t;   /* enable prefetch mode */
+               drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+       } else {
+               drive->drive_data &= ~t;  /* disable prefetch mode */
+               drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
+       }
+
+       spin_unlock_irqrestore(&ht6560b_lock, flags);
+
+#ifdef DEBUG
+       printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
+#endif
+}
+
+static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       unsigned long flags;
+       u8 timing;
+       
+       switch (pio) {
+       case 8:         /* set prefetch off */
+       case 9:         /* set prefetch on */
+               ht_set_prefetch(drive, pio & 1);
+               return;
+       }
+
+       timing = ht_pio2timings(drive, pio);
+
+       spin_lock_irqsave(&ht6560b_lock, flags);
+       drive->drive_data &= 0xff00;
+       drive->drive_data |= timing;
+       spin_unlock_irqrestore(&ht6560b_lock, flags);
+
+#ifdef DEBUG
+       printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
+#endif
+}
+
+static void __init ht6560b_init_dev(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       /* Setting default configurations for drives. */
+       int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
+
+       if (hwif->channel)
+               t |= (HT_SECONDARY_IF << 8);
+
+       drive->drive_data = t;
+}
+
+static int probe_ht6560b;
+
+module_param_named(probe, probe_ht6560b, bool, 0);
+MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
+
+static const struct ide_port_ops ht6560b_port_ops = {
+       .init_dev               = ht6560b_init_dev,
+       .set_pio_mode           = ht6560b_set_pio_mode,
+       .selectproc             = ht6560b_selectproc,
+};
+
+static const struct ide_port_info ht6560b_port_info __initdata = {
+       .name                   = DRV_NAME,
+       .chipset                = ide_ht6560b,
+       .port_ops               = &ht6560b_port_ops,
+       .host_flags             = IDE_HFLAG_SERIALIZE | /* is this needed? */
+                                 IDE_HFLAG_NO_DMA |
+                                 IDE_HFLAG_ABUSE_PREFETCH,
+       .pio_mask               = ATA_PIO4,
+};
+
+static int __init ht6560b_init(void)
+{
+       if (probe_ht6560b == 0)
+               return -ENODEV;
+
+       if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
+               printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       if (!try_to_init_ht6560b()) {
+               printk(KERN_NOTICE "%s: HBA not found\n", __func__);
+               goto release_region;
+       }
+
+       return ide_legacy_device_add(&ht6560b_port_info, 0);
+
+release_region:
+       release_region(HT_CONFIG_PORT, 1);
+       return -ENODEV;
+}
+
+module_init(ht6560b_init);
+
+MODULE_AUTHOR("See Local File");
+MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
new file mode 100644 (file)
index 0000000..76bdc9a
--- /dev/null
@@ -0,0 +1,703 @@
+/*
+ * Copyright (c) 1996-2004 Russell King.
+ *
+ * Please note that this platform does not support 32-bit IDE IO.
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/errno.h>
+#include <linux/ide.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
+
+#include <asm/dma.h>
+#include <asm/ecard.h>
+
+#define DRV_NAME "icside"
+
+#define ICS_IDENT_OFFSET               0x2280
+
+#define ICS_ARCIN_V5_INTRSTAT          0x0000
+#define ICS_ARCIN_V5_INTROFFSET                0x0004
+#define ICS_ARCIN_V5_IDEOFFSET         0x2800
+#define ICS_ARCIN_V5_IDEALTOFFSET      0x2b80
+#define ICS_ARCIN_V5_IDESTEPPING       6
+
+#define ICS_ARCIN_V6_IDEOFFSET_1       0x2000
+#define ICS_ARCIN_V6_INTROFFSET_1      0x2200
+#define ICS_ARCIN_V6_INTRSTAT_1                0x2290
+#define ICS_ARCIN_V6_IDEALTOFFSET_1    0x2380
+#define ICS_ARCIN_V6_IDEOFFSET_2       0x3000
+#define ICS_ARCIN_V6_INTROFFSET_2      0x3200
+#define ICS_ARCIN_V6_INTRSTAT_2                0x3290
+#define ICS_ARCIN_V6_IDEALTOFFSET_2    0x3380
+#define ICS_ARCIN_V6_IDESTEPPING       6
+
+struct cardinfo {
+       unsigned int dataoffset;
+       unsigned int ctrloffset;
+       unsigned int stepping;
+};
+
+static struct cardinfo icside_cardinfo_v5 = {
+       .dataoffset     = ICS_ARCIN_V5_IDEOFFSET,
+       .ctrloffset     = ICS_ARCIN_V5_IDEALTOFFSET,
+       .stepping       = ICS_ARCIN_V5_IDESTEPPING,
+};
+
+static struct cardinfo icside_cardinfo_v6_1 = {
+       .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_1,
+       .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_1,
+       .stepping       = ICS_ARCIN_V6_IDESTEPPING,
+};
+
+static struct cardinfo icside_cardinfo_v6_2 = {
+       .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_2,
+       .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_2,
+       .stepping       = ICS_ARCIN_V6_IDESTEPPING,
+};
+
+struct icside_state {
+       unsigned int channel;
+       unsigned int enabled;
+       void __iomem *irq_port;
+       void __iomem *ioc_base;
+       unsigned int sel;
+       unsigned int type;
+       struct ide_host *host;
+};
+
+#define ICS_TYPE_A3IN  0
+#define ICS_TYPE_A3USER        1
+#define ICS_TYPE_V6    3
+#define ICS_TYPE_V5    15
+#define ICS_TYPE_NOTYPE        ((unsigned int)-1)
+
+/* ---------------- Version 5 PCB Support Functions --------------------- */
+/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
+ * Purpose  : enable interrupts from card
+ */
+static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
+{
+       struct icside_state *state = ec->irq_data;
+
+       writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
+}
+
+/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
+ * Purpose  : disable interrupts from card
+ */
+static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
+{
+       struct icside_state *state = ec->irq_data;
+
+       readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
+}
+
+static const expansioncard_ops_t icside_ops_arcin_v5 = {
+       .irqenable      = icside_irqenable_arcin_v5,
+       .irqdisable     = icside_irqdisable_arcin_v5,
+};
+
+
+/* ---------------- Version 6 PCB Support Functions --------------------- */
+/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
+ * Purpose  : enable interrupts from card
+ */
+static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
+{
+       struct icside_state *state = ec->irq_data;
+       void __iomem *base = state->irq_port;
+
+       state->enabled = 1;
+
+       switch (state->channel) {
+       case 0:
+               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
+               readb(base + ICS_ARCIN_V6_INTROFFSET_2);
+               break;
+       case 1:
+               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
+               readb(base + ICS_ARCIN_V6_INTROFFSET_1);
+               break;
+       }
+}
+
+/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
+ * Purpose  : disable interrupts from card
+ */
+static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
+{
+       struct icside_state *state = ec->irq_data;
+
+       state->enabled = 0;
+
+       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+}
+
+/* Prototype: icside_irqprobe(struct expansion_card *ec)
+ * Purpose  : detect an active interrupt from card
+ */
+static int icside_irqpending_arcin_v6(struct expansion_card *ec)
+{
+       struct icside_state *state = ec->irq_data;
+
+       return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
+              readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
+}
+
+static const expansioncard_ops_t icside_ops_arcin_v6 = {
+       .irqenable      = icside_irqenable_arcin_v6,
+       .irqdisable     = icside_irqdisable_arcin_v6,
+       .irqpending     = icside_irqpending_arcin_v6,
+};
+
+/*
+ * Handle routing of interrupts.  This is called before
+ * we write the command to the drive.
+ */
+static void icside_maskproc(ide_drive_t *drive, int mask)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct expansion_card *ec = ECARD_DEV(hwif->dev);
+       struct icside_state *state = ecard_get_drvdata(ec);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       state->channel = hwif->channel;
+
+       if (state->enabled && !mask) {
+               switch (hwif->channel) {
+               case 0:
+                       writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+                       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+                       break;
+               case 1:
+                       writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+                       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+                       break;
+               }
+       } else {
+               readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+               readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+       }
+
+       local_irq_restore(flags);
+}
+
+static const struct ide_port_ops icside_v6_no_dma_port_ops = {
+       .maskproc               = icside_maskproc,
+};
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
+/*
+ * SG-DMA support.
+ *
+ * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
+ * There is only one DMA controller per card, which means that only
+ * one drive can be accessed at one time.  NOTE! We do not enforce that
+ * here, but we rely on the main IDE driver spotting that both
+ * interfaces use the same IRQ, which should guarantee this.
+ */
+
+/*
+ * Configure the IOMD to give the appropriate timings for the transfer
+ * mode being requested.  We take the advice of the ATA standards, and
+ * calculate the cycle time based on the transfer mode, and the EIDE
+ * MW DMA specs that the drive provides in the IDENTIFY command.
+ *
+ * We have the following IOMD DMA modes to choose from:
+ *
+ *     Type    Active          Recovery        Cycle
+ *     A       250 (250)       312 (550)       562 (800)
+ *     B       187             250             437
+ *     C       125 (125)       125 (375)       250 (500)
+ *     D       62              125             187
+ *
+ * (figures in brackets are actual measured timings)
+ *
+ * However, we also need to take care of the read/write active and
+ * recovery timings:
+ *
+ *                     Read    Write
+ *     Mode    Active  -- Recovery --  Cycle   IOMD type
+ *     MW0     215     50      215     480     A
+ *     MW1     80      50      50      150     C
+ *     MW2     70      25      25      120     C
+ */
+static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
+{
+       int cycle_time, use_dma_info = 0;
+
+       switch (xfer_mode) {
+       case XFER_MW_DMA_2:
+               cycle_time = 250;
+               use_dma_info = 1;
+               break;
+
+       case XFER_MW_DMA_1:
+               cycle_time = 250;
+               use_dma_info = 1;
+               break;
+
+       case XFER_MW_DMA_0:
+               cycle_time = 480;
+               break;
+
+       case XFER_SW_DMA_2:
+       case XFER_SW_DMA_1:
+       case XFER_SW_DMA_0:
+               cycle_time = 480;
+               break;
+       }
+
+       /*
+        * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
+        * take care to note the values in the ID...
+        */
+       if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
+               cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
+
+       drive->drive_data = cycle_time;
+
+       printk("%s: %s selected (peak %dMB/s)\n", drive->name,
+               ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
+}
+
+static const struct ide_port_ops icside_v6_port_ops = {
+       .set_dma_mode           = icside_set_dma_mode,
+       .maskproc               = icside_maskproc,
+};
+
+static void icside_dma_host_set(ide_drive_t *drive, int on)
+{
+}
+
+static int icside_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct expansion_card *ec = ECARD_DEV(hwif->dev);
+
+       drive->waiting_for_dma = 0;
+
+       disable_dma(ec->dma);
+
+       /* Teardown mappings after DMA has completed. */
+       ide_destroy_dmatable(drive);
+
+       return get_dma_residue(ec->dma) != 0;
+}
+
+static void icside_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct expansion_card *ec = ECARD_DEV(hwif->dev);
+
+       /* We can not enable DMA on both channels simultaneously. */
+       BUG_ON(dma_channel_active(ec->dma));
+       enable_dma(ec->dma);
+}
+
+static int icside_dma_setup(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct expansion_card *ec = ECARD_DEV(hwif->dev);
+       struct icside_state *state = ecard_get_drvdata(ec);
+       struct request *rq = hwif->hwgroup->rq;
+       unsigned int dma_mode;
+
+       if (rq_data_dir(rq))
+               dma_mode = DMA_MODE_WRITE;
+       else
+               dma_mode = DMA_MODE_READ;
+
+       /*
+        * We can not enable DMA on both channels.
+        */
+       BUG_ON(dma_channel_active(ec->dma));
+
+       hwif->sg_nents = ide_build_sglist(drive, rq);
+
+       /*
+        * Ensure that we have the right interrupt routed.
+        */
+       icside_maskproc(drive, 0);
+
+       /*
+        * Route the DMA signals to the correct interface.
+        */
+       writeb(state->sel | hwif->channel, state->ioc_base);
+
+       /*
+        * Select the correct timing for this drive.
+        */
+       set_dma_speed(ec->dma, drive->drive_data);
+
+       /*
+        * Tell the DMA engine about the SG table and
+        * data direction.
+        */
+       set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
+       set_dma_mode(ec->dma, dma_mode);
+
+       drive->waiting_for_dma = 1;
+
+       return 0;
+}
+
+static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
+{
+       /* issue cmd to drive */
+       ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL);
+}
+
+static int icside_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct expansion_card *ec = ECARD_DEV(hwif->dev);
+       struct icside_state *state = ecard_get_drvdata(ec);
+
+       return readb(state->irq_port +
+                    (hwif->channel ?
+                       ICS_ARCIN_V6_INTRSTAT_2 :
+                       ICS_ARCIN_V6_INTRSTAT_1)) & 1;
+}
+
+static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       hwif->dmatable_cpu      = NULL;
+       hwif->dmatable_dma      = 0;
+
+       return 0;
+}
+
+static const struct ide_dma_ops icside_v6_dma_ops = {
+       .dma_host_set           = icside_dma_host_set,
+       .dma_setup              = icside_dma_setup,
+       .dma_exec_cmd           = icside_dma_exec_cmd,
+       .dma_start              = icside_dma_start,
+       .dma_end                = icside_dma_end,
+       .dma_test_irq           = icside_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+};
+#else
+#define icside_v6_dma_ops NULL
+#endif
+
+static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       return -EOPNOTSUPP;
+}
+
+static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
+                              struct cardinfo *info, struct expansion_card *ec)
+{
+       unsigned long port = (unsigned long)base + info->dataoffset;
+
+       hw->io_ports.data_addr   = port;
+       hw->io_ports.error_addr  = port + (1 << info->stepping);
+       hw->io_ports.nsect_addr  = port + (2 << info->stepping);
+       hw->io_ports.lbal_addr   = port + (3 << info->stepping);
+       hw->io_ports.lbam_addr   = port + (4 << info->stepping);
+       hw->io_ports.lbah_addr   = port + (5 << info->stepping);
+       hw->io_ports.device_addr = port + (6 << info->stepping);
+       hw->io_ports.status_addr = port + (7 << info->stepping);
+       hw->io_ports.ctl_addr    = (unsigned long)base + info->ctrloffset;
+
+       hw->irq = ec->irq;
+       hw->dev = &ec->dev;
+       hw->chipset = ide_acorn;
+}
+
+static int __init
+icside_register_v5(struct icside_state *state, struct expansion_card *ec)
+{
+       void __iomem *base;
+       struct ide_host *host;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+       int ret;
+
+       base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
+       if (!base)
+               return -ENOMEM;
+
+       state->irq_port = base;
+
+       ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;
+       ec->irqmask  = 1;
+
+       ecard_setirq(ec, &icside_ops_arcin_v5, state);
+
+       /*
+        * Be on the safe side - disable interrupts
+        */
+       icside_irqdisable_arcin_v5(ec, 0);
+
+       icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
+
+       host = ide_host_alloc(NULL, hws);
+       if (host == NULL)
+               return -ENODEV;
+
+       state->host = host;
+
+       ecard_set_drvdata(ec, state);
+
+       ret = ide_host_register(host, NULL, hws);
+       if (ret)
+               goto err_free;
+
+       return 0;
+err_free:
+       ide_host_free(host);
+       ecard_set_drvdata(ec, NULL);
+       return ret;
+}
+
+static const struct ide_port_info icside_v6_port_info __initdata = {
+       .init_dma               = icside_dma_off_init,
+       .port_ops               = &icside_v6_no_dma_port_ops,
+       .dma_ops                = &icside_v6_dma_ops,
+       .host_flags             = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
+       .mwdma_mask             = ATA_MWDMA2,
+       .swdma_mask             = ATA_SWDMA2,
+};
+
+static int __init
+icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+{
+       void __iomem *ioc_base, *easi_base;
+       struct ide_host *host;
+       unsigned int sel = 0;
+       int ret;
+       hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
+       struct ide_port_info d = icside_v6_port_info;
+
+       ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
+       if (!ioc_base) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       easi_base = ioc_base;
+
+       if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
+               easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
+               if (!easi_base) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               /*
+                * Enable access to the EASI region.
+                */
+               sel = 1 << 5;
+       }
+
+       writeb(sel, ioc_base);
+
+       ecard_setirq(ec, &icside_ops_arcin_v6, state);
+
+       state->irq_port   = easi_base;
+       state->ioc_base   = ioc_base;
+       state->sel        = sel;
+
+       /*
+        * Be on the safe side - disable interrupts
+        */
+       icside_irqdisable_arcin_v6(ec, 0);
+
+       icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
+       icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
+
+       host = ide_host_alloc(&d, hws);
+       if (host == NULL)
+               return -ENODEV;
+
+       state->host = host;
+
+       ecard_set_drvdata(ec, state);
+
+       if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
+               d.init_dma = icside_dma_init;
+               d.port_ops = &icside_v6_port_ops;
+               d.dma_ops = NULL;
+       }
+
+       ret = ide_host_register(host, NULL, hws);
+       if (ret)
+               goto err_free;
+
+       return 0;
+err_free:
+       ide_host_free(host);
+       if (d.dma_ops)
+               free_dma(ec->dma);
+       ecard_set_drvdata(ec, NULL);
+out:
+       return ret;
+}
+
+static int __devinit
+icside_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+       struct icside_state *state;
+       void __iomem *idmem;
+       int ret;
+
+       ret = ecard_request_resources(ec);
+       if (ret)
+               goto out;
+
+       state = kzalloc(sizeof(struct icside_state), GFP_KERNEL);
+       if (!state) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       state->type     = ICS_TYPE_NOTYPE;
+
+       idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
+       if (idmem) {
+               unsigned int type;
+
+               type = readb(idmem + ICS_IDENT_OFFSET) & 1;
+               type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
+               type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
+               type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
+               ecardm_iounmap(ec, idmem);
+
+               state->type = type;
+       }
+
+       switch (state->type) {
+       case ICS_TYPE_A3IN:
+               dev_warn(&ec->dev, "A3IN unsupported\n");
+               ret = -ENODEV;
+               break;
+
+       case ICS_TYPE_A3USER:
+               dev_warn(&ec->dev, "A3USER unsupported\n");
+               ret = -ENODEV;
+               break;
+
+       case ICS_TYPE_V5:
+               ret = icside_register_v5(state, ec);
+               break;
+
+       case ICS_TYPE_V6:
+               ret = icside_register_v6(state, ec);
+               break;
+
+       default:
+               dev_warn(&ec->dev, "unknown interface type\n");
+               ret = -ENODEV;
+               break;
+       }
+
+       if (ret == 0)
+               goto out;
+
+       kfree(state);
+ release:
+       ecard_release_resources(ec);
+ out:
+       return ret;
+}
+
+static void __devexit icside_remove(struct expansion_card *ec)
+{
+       struct icside_state *state = ecard_get_drvdata(ec);
+
+       switch (state->type) {
+       case ICS_TYPE_V5:
+               /* FIXME: tell IDE to stop using the interface */
+
+               /* Disable interrupts */
+               icside_irqdisable_arcin_v5(ec, 0);
+               break;
+
+       case ICS_TYPE_V6:
+               /* FIXME: tell IDE to stop using the interface */
+               if (ec->dma != NO_DMA)
+                       free_dma(ec->dma);
+
+               /* Disable interrupts */
+               icside_irqdisable_arcin_v6(ec, 0);
+
+               /* Reset the ROM pointer/EASI selection */
+               writeb(0, state->ioc_base);
+               break;
+       }
+
+       ecard_set_drvdata(ec, NULL);
+
+       kfree(state);
+       ecard_release_resources(ec);
+}
+
+static void icside_shutdown(struct expansion_card *ec)
+{
+       struct icside_state *state = ecard_get_drvdata(ec);
+       unsigned long flags;
+
+       /*
+        * Disable interrupts from this card.  We need to do
+        * this before disabling EASI since we may be accessing
+        * this register via that region.
+        */
+       local_irq_save(flags);
+       ec->ops->irqdisable(ec, 0);
+       local_irq_restore(flags);
+
+       /*
+        * Reset the ROM pointer so that we can read the ROM
+        * after a soft reboot.  This also disables access to
+        * the IDE taskfile via the EASI region.
+        */
+       if (state->ioc_base)
+               writeb(0, state->ioc_base);
+}
+
+static const struct ecard_id icside_ids[] = {
+       { MANU_ICS,  PROD_ICS_IDE  },
+       { MANU_ICS2, PROD_ICS2_IDE },
+       { 0xffff, 0xffff }
+};
+
+static struct ecard_driver icside_driver = {
+       .probe          = icside_probe,
+       .remove         = __devexit_p(icside_remove),
+       .shutdown       = icside_shutdown,
+       .id_table       = icside_ids,
+       .drv = {
+               .name   = "icside",
+       },
+};
+
+static int __init icside_init(void)
+{
+       return ecard_register_driver(&icside_driver);
+}
+
+static void __exit icside_exit(void);
+{
+       ecard_unregister_driver(&icside_driver);
+}
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ICS IDE driver");
+
+module_init(icside_init);
+module_exit(icside_exit);
diff --git a/drivers/ide/ide-4drives.c b/drivers/ide/ide-4drives.c
new file mode 100644 (file)
index 0000000..9e85b1e
--- /dev/null
@@ -0,0 +1,63 @@
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ide.h>
+
+#define DRV_NAME "ide-4drives"
+
+static int probe_4drives;
+
+module_param_named(probe, probe_4drives, bool, 0);
+MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
+
+static void ide_4drives_init_dev(ide_drive_t *drive)
+{
+       if (drive->hwif->channel)
+               drive->select ^= 0x20;
+}
+
+static const struct ide_port_ops ide_4drives_port_ops = {
+       .init_dev               = ide_4drives_init_dev,
+};
+
+static const struct ide_port_info ide_4drives_port_info = {
+       .port_ops               = &ide_4drives_port_ops,
+       .host_flags             = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
+};
+
+static int __init ide_4drives_init(void)
+{
+       unsigned long base = 0x1f0, ctl = 0x3f6;
+       hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
+
+       if (probe_4drives == 0)
+               return -ENODEV;
+
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+
+       ide_std_init_ports(&hw, base, ctl);
+       hw.irq = 14;
+       hw.chipset = ide_4drives;
+
+       return ide_host_add(&ide_4drives_port_info, hws, NULL);
+}
+
+module_init(ide_4drives_init);
+
+MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
+MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
new file mode 100644 (file)
index 0000000..cb199c8
--- /dev/null
@@ -0,0 +1,472 @@
+/*======================================================================
+
+    A driver for PCMCIA IDE/ATA disk cards
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is David A. Hinds
+    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
+    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU General Public License version 2 (the "GPL"), in
+    which case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    and other provisions required by the GPL.  If you do not delete
+    the provisions above, a recipient may use your version of this
+    file under either the MPL or the GPL.
+
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/ide.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ciscode.h>
+
+#define DRV_NAME "ide-cs"
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
+MODULE_LICENSE("Dual MPL/GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+#ifdef CONFIG_PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, 0);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
+
+typedef struct ide_info_t {
+       struct pcmcia_device    *p_dev;
+       struct ide_host         *host;
+    int                ndev;
+    dev_node_t node;
+} ide_info_t;
+
+static void ide_release(struct pcmcia_device *);
+static int ide_config(struct pcmcia_device *);
+
+static void ide_detach(struct pcmcia_device *p_dev);
+
+
+
+
+/*======================================================================
+
+    ide_attach() creates an "instance" of the driver, allocating
+    local data structures for one device.  The device is registered
+    with Card Services.
+
+======================================================================*/
+
+static int ide_probe(struct pcmcia_device *link)
+{
+    ide_info_t *info;
+
+    DEBUG(0, "ide_attach()\n");
+
+    /* Create new ide device */
+    info = kzalloc(sizeof(*info), GFP_KERNEL);
+    if (!info)
+       return -ENOMEM;
+
+    info->p_dev = link;
+    link->priv = info;
+
+    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+    link->io.IOAddrLines = 3;
+    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
+    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->conf.IntType = INT_MEMORY_AND_IO;
+
+    return ide_config(link);
+} /* ide_attach */
+
+/*======================================================================
+
+    This deletes a driver "instance".  The device is de-registered
+    with Card Services.  If it has been released, all local data
+    structures are freed.  Otherwise, the structures will be freed
+    when the device is released.
+
+======================================================================*/
+
+static void ide_detach(struct pcmcia_device *link)
+{
+    ide_info_t *info = link->priv;
+    ide_hwif_t *hwif = info->host->ports[0];
+    unsigned long data_addr, ctl_addr;
+
+    DEBUG(0, "ide_detach(0x%p)\n", link);
+
+    data_addr = hwif->io_ports.data_addr;
+    ctl_addr  = hwif->io_ports.ctl_addr;
+
+    ide_release(link);
+
+    release_region(ctl_addr, 1);
+    release_region(data_addr, 8);
+
+    kfree(info);
+} /* ide_detach */
+
+static const struct ide_port_ops idecs_port_ops = {
+       .quirkproc              = ide_undecoded_slave,
+};
+
+static const struct ide_port_info idecs_port_info = {
+       .port_ops               = &idecs_port_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+};
+
+static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
+                               unsigned long irq, struct pcmcia_device *handle)
+{
+    struct ide_host *host;
+    ide_hwif_t *hwif;
+    int i, rc;
+    hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+    if (!request_region(io, 8, DRV_NAME)) {
+       printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                       DRV_NAME, io, io + 7);
+       return NULL;
+    }
+
+    if (!request_region(ctl, 1, DRV_NAME)) {
+       printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                       DRV_NAME, ctl);
+       release_region(io, 8);
+       return NULL;
+    }
+
+    memset(&hw, 0, sizeof(hw));
+    ide_std_init_ports(&hw, io, ctl);
+    hw.irq = irq;
+    hw.chipset = ide_pci;
+    hw.dev = &handle->dev;
+
+    rc = ide_host_add(&idecs_port_info, hws, &host);
+    if (rc)
+       goto out_release;
+
+    hwif = host->ports[0];
+
+    if (hwif->present)
+       return host;
+
+    /* retry registration in case device is still spinning up */
+    for (i = 0; i < 10; i++) {
+       msleep(100);
+       ide_port_scan(hwif);
+       if (hwif->present)
+           return host;
+    }
+
+    return host;
+
+out_release:
+    release_region(ctl, 1);
+    release_region(io, 8);
+    return NULL;
+}
+
+/*======================================================================
+
+    ide_config() is scheduled to run after a CARD_INSERTION event
+    is received, to configure the PCMCIA socket, and to make the
+    ide device available to the system.
+
+======================================================================*/
+
+#define CS_CHECK(fn, ret) \
+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+struct pcmcia_config_check {
+       unsigned long ctl_base;
+       int skip_vcc;
+       int is_kme;
+};
+
+static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+                                  cistpl_cftable_entry_t *cfg,
+                                  cistpl_cftable_entry_t *dflt,
+                                  unsigned int vcc,
+                                  void *priv_data)
+{
+       struct pcmcia_config_check *stk = priv_data;
+
+       /* Check for matching Vcc, unless we're desperate */
+       if (!stk->skip_vcc) {
+               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               }
+       }
+
+       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               pdev->conf.ConfigIndex = cfg->index;
+               pdev->io.BasePort1 = io->win[0].base;
+               pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               if (io->nwin == 2) {
+                       pdev->io.NumPorts1 = 8;
+                       pdev->io.BasePort2 = io->win[1].base;
+                       pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
+                               return -ENODEV;
+                       stk->ctl_base = pdev->io.BasePort2;
+               } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+                       pdev->io.NumPorts1 = io->win[0].len;
+                       pdev->io.NumPorts2 = 0;
+                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
+                               return -ENODEV;
+                       stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+               } else
+                       return -ENODEV;
+               /* If we've got this far, we're done */
+               return 0;
+       }
+       return -ENODEV;
+}
+
+static int ide_config(struct pcmcia_device *link)
+{
+    ide_info_t *info = link->priv;
+    struct pcmcia_config_check *stk = NULL;
+    int last_ret = 0, last_fn = 0, is_kme = 0;
+    unsigned long io_base, ctl_base;
+    struct ide_host *host;
+
+    DEBUG(0, "ide_config(0x%p)\n", link);
+
+    is_kme = ((link->manf_id == MANFID_KME) &&
+             ((link->card_id == PRODID_KME_KXLC005_A) ||
+              (link->card_id == PRODID_KME_KXLC005_B)));
+
+    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+    if (!stk)
+           goto err_mem;
+    stk->is_kme = is_kme;
+    stk->skip_vcc = io_base = ctl_base = 0;
+
+    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
+           stk->skip_vcc = 1;
+           if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+                   goto failed; /* No suitable config found */
+    }
+    io_base = link->io.BasePort1;
+    ctl_base = stk->ctl_base;
+
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
+    /* disable drive interrupts during IDE probe */
+    outb(0x02, ctl_base);
+
+    /* special setup for KXLC005 card */
+    if (is_kme)
+       outb(0x81, ctl_base+1);
+
+     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+     if (host == NULL && link->io.NumPorts1 == 0x20) {
+           outb(0x02, ctl_base + 0x10);
+           host = idecs_register(io_base + 0x10, ctl_base + 0x10,
+                                 link->irq.AssignedIRQ, link);
+    }
+
+    if (host == NULL)
+       goto failed;
+
+    info->ndev = 1;
+    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
+    info->node.major = host->ports[0]->major;
+    info->node.minor = 0;
+    info->host = host;
+    link->dev_node = &info->node;
+    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
+          info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
+
+    kfree(stk);
+    return 0;
+
+err_mem:
+    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
+    goto failed;
+
+cs_failed:
+    cs_error(link, last_fn, last_ret);
+failed:
+    kfree(stk);
+    ide_release(link);
+    return -ENODEV;
+} /* ide_config */
+
+/*======================================================================
+
+    After a card is removed, ide_release() will unregister the net
+    device, and release the PCMCIA configuration.  If the device is
+    still open, this will be postponed until it is closed.
+
+======================================================================*/
+
+static void ide_release(struct pcmcia_device *link)
+{
+    ide_info_t *info = link->priv;
+    struct ide_host *host = info->host;
+
+    DEBUG(0, "ide_release(0x%p)\n", link);
+
+    if (info->ndev)
+       /* FIXME: if this fails we need to queue the cleanup somehow
+          -- need to investigate the required PCMCIA magic */
+       ide_host_remove(host);
+
+    info->ndev = 0;
+
+    pcmcia_disable_device(link);
+} /* ide_release */
+
+
+/*======================================================================
+
+    The card status event handler.  Mostly, this schedules other
+    stuff to run after an event is received.  A CARD_REMOVAL event
+    also sets some flags to discourage the ide drivers from
+    talking to the ports.
+
+======================================================================*/
+
+static struct pcmcia_device_id ide_ids[] = {
+       PCMCIA_DEVICE_FUNC_ID(4),
+       PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
+       PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
+       PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+       PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
+       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
+       PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
+       PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
+       PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
+       PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
+       PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
+       PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
+       PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
+       PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
+       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
+       PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
+       PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
+       PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
+       PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
+       PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
+       PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
+       PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
+       PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
+       PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
+       PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
+       PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
+       PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
+       PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
+       PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
+       PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
+       PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
+       PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
+       PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
+       PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
+       PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
+       PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
+       PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
+       PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
+       PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
+       PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
+       PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
+       PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
+       PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
+       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
+       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
+       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
+       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
+       PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
+       PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
+       PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+       PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
+       PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
+       PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, ide_ids);
+
+static struct pcmcia_driver ide_cs_driver = {
+       .owner          = THIS_MODULE,
+       .drv            = {
+               .name   = "ide-cs",
+       },
+       .probe          = ide_probe,
+       .remove         = ide_detach,
+       .id_table       = ide_ids,
+};
+
+static int __init init_ide_cs(void)
+{
+       return pcmcia_register_driver(&ide_cs_driver);
+}
+
+static void __exit exit_ide_cs(void)
+{
+       pcmcia_unregister_driver(&ide_cs_driver);
+}
+
+late_initcall(init_ide_cs);
+module_exit(exit_ide_cs);
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c
new file mode 100644 (file)
index 0000000..e2cdd2e
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * H8/300 generic IDE interface
+ */
+
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define DRV_NAME "ide-h8300"
+
+#define bswap(d) \
+({                                     \
+       u16 r;                          \
+       __asm__("mov.b %w1,r1h\n\t"     \
+               "mov.b %x1,r1l\n\t"     \
+               "mov.w r1,%0"           \
+               :"=r"(r)                \
+               :"r"(d)                 \
+               :"er1");                \
+       (r);                            \
+})
+
+static void mm_outw(u16 d, unsigned long a)
+{
+       __asm__("mov.b %w0,r2h\n\t"
+               "mov.b %x0,r2l\n\t"
+               "mov.w r2,@%1"
+               :
+               :"r"(d),"r"(a)
+               :"er2");
+}
+
+static u16 mm_inw(unsigned long a)
+{
+       register u16 r __asm__("er0");
+       __asm__("mov.w @%1,r2\n\t"
+               "mov.b r2l,%x0\n\t"
+               "mov.b r2h,%w0"
+               :"=r"(r)
+               :"r"(a)
+               :"er2");
+       return r;
+}
+
+static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+       u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+       if (task->tf_flags & IDE_TFLAG_FLAGGED)
+               HIHI = 0xFF;
+
+       if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+               mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+               outb(tf->hob_feature, io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+               outb(tf->hob_nsect, io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+               outb(tf->hob_lbal, io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+               outb(tf->hob_lbam, io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+               outb(tf->hob_lbah, io_ports->lbah_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+               outb(tf->feature, io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+               outb(tf->nsect, io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+               outb(tf->lbal, io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+               outb(tf->lbam, io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+               outb(tf->lbah, io_ports->lbah_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+               outb((tf->device & HIHI) | drive->select,
+                    io_ports->device_addr);
+}
+
+static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+
+       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+               u16 data = mm_inw(io_ports->data_addr);
+
+               tf->data = data & 0xff;
+               tf->hob_data = (data >> 8) & 0xff;
+       }
+
+       /* be sure we're looking at the low order bits */
+       outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+               tf->feature = inb(io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+               tf->nsect  = inb(io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+               tf->lbal   = inb(io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+               tf->lbam   = inb(io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+               tf->lbah   = inb(io_ports->lbah_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+               tf->device = inb(io_ports->device_addr);
+
+       if (task->tf_flags & IDE_TFLAG_LBA48) {
+               outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+                       tf->hob_feature = inb(io_ports->feature_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+                       tf->hob_nsect   = inb(io_ports->nsect_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+                       tf->hob_lbal    = inb(io_ports->lbal_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+                       tf->hob_lbam    = inb(io_ports->lbam_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+                       tf->hob_lbah    = inb(io_ports->lbah_addr);
+       }
+}
+
+static void mm_outsw(unsigned long addr, void *buf, u32 len)
+{
+       unsigned short *bp = (unsigned short *)buf;
+       for (; len > 0; len--, bp++)
+               *(volatile u16 *)addr = bswap(*bp);
+}
+
+static void mm_insw(unsigned long addr, void *buf, u32 len)
+{
+       unsigned short *bp = (unsigned short *)buf;
+       for (; len > 0; len--, bp++)
+               *bp = bswap(*(volatile u16 *)addr);
+}
+
+static void h8300_input_data(ide_drive_t *drive, struct request *rq,
+                            void *buf, unsigned int len)
+{
+       mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
+}
+
+static void h8300_output_data(ide_drive_t *drive, struct request *rq,
+                             void *buf, unsigned int len)
+{
+       mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
+}
+
+static const struct ide_tp_ops h8300_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = h8300_tf_load,
+       .tf_read                = h8300_tf_read,
+
+       .input_data             = h8300_input_data,
+       .output_data            = h8300_output_data,
+};
+
+#define H8300_IDE_GAP (2)
+
+static inline void hw_setup(hw_regs_t *hw)
+{
+       int i;
+
+       memset(hw, 0, sizeof(hw_regs_t));
+       for (i = 0; i <= 7; i++)
+               hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
+       hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
+       hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
+       hw->chipset = ide_generic;
+}
+
+static const struct ide_port_info h8300_port_info = {
+       .tp_ops                 = &h8300_tp_ops,
+       .host_flags             = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
+};
+
+static int __init h8300_ide_init(void)
+{
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+       printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
+
+       if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
+               goto out_busy;
+       if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) {
+               release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8);
+               goto out_busy;
+       }
+
+       hw_setup(&hw);
+
+       return ide_host_add(&h8300_port_info, hws, NULL);
+
+out_busy:
+       printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
+
+       return -EBUSY;
+}
+
+module_init(h8300_ide_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide_arm.c b/drivers/ide/ide_arm.c
new file mode 100644 (file)
index 0000000..f728f29
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * ARM default IDE host driver
+ *
+ * Copyright (C) 2004 Bartlomiej Zolnierkiewicz
+ * Based on code by: Russell King, Ian Molton and Alexander Schulz.
+ *
+ * May be copied or modified under the terms of the GNU General Public License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/irq.h>
+
+#define DRV_NAME "ide_arm"
+
+#ifdef CONFIG_ARCH_CLPS7500
+# include <mach/hardware.h>
+#
+# define IDE_ARM_IO    (ISASLOT_IO + 0x1f0)
+# define IDE_ARM_IRQ   IRQ_ISA_14
+#else
+# define IDE_ARM_IO    0x1f0
+# define IDE_ARM_IRQ   IRQ_HARDDISK
+#endif
+
+static int __init ide_arm_init(void)
+{
+       unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+       if (!request_region(base, 8, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+                               DRV_NAME, base, base + 7);
+               return -EBUSY;
+       }
+
+       if (!request_region(ctl, 1, DRV_NAME)) {
+               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+                               DRV_NAME, ctl);
+               release_region(base, 8);
+               return -EBUSY;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+       ide_std_init_ports(&hw, base, ctl);
+       hw.irq = IDE_ARM_IRQ;
+       hw.chipset = ide_generic;
+
+       return ide_host_add(NULL, hws, NULL);
+}
+
+module_init(ide_arm_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide_platform.c b/drivers/ide/ide_platform.c
new file mode 100644 (file)
index 0000000..051b4ab
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Platform IDE driver
+ *
+ * Copyright (C) 2007 MontaVista Software
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/ata_platform.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
+                                          void __iomem *base,
+                                          void __iomem *ctrl,
+                                          struct pata_platform_info *pdata,
+                                          int irq)
+{
+       unsigned long port = (unsigned long)base;
+       int i;
+
+       hw->io_ports.data_addr = port;
+
+       port += (1 << pdata->ioport_shift);
+       for (i = 1; i <= 7;
+            i++, port += (1 << pdata->ioport_shift))
+               hw->io_ports_array[i] = port;
+
+       hw->io_ports.ctl_addr = (unsigned long)ctrl;
+
+       hw->irq = irq;
+
+       hw->chipset = ide_generic;
+}
+
+static const struct ide_port_info platform_ide_port_info = {
+       .host_flags             = IDE_HFLAG_NO_DMA,
+};
+
+static int __devinit plat_ide_probe(struct platform_device *pdev)
+{
+       struct resource *res_base, *res_alt, *res_irq;
+       void __iomem *base, *alt_base;
+       struct pata_platform_info *pdata;
+       struct ide_host *host;
+       int ret = 0, mmio = 0;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+       struct ide_port_info d = platform_ide_port_info;
+
+       pdata = pdev->dev.platform_data;
+
+       /* get a pointer to the register memory */
+       res_base = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res_alt = platform_get_resource(pdev, IORESOURCE_IO, 1);
+
+       if (!res_base || !res_alt) {
+               res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               if (!res_base || !res_alt) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               mmio = 1;
+       }
+
+       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res_irq) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (mmio) {
+               base = devm_ioremap(&pdev->dev,
+                       res_base->start, res_base->end - res_base->start + 1);
+               alt_base = devm_ioremap(&pdev->dev,
+                       res_alt->start, res_alt->end - res_alt->start + 1);
+       } else {
+               base = devm_ioport_map(&pdev->dev,
+                       res_base->start, res_base->end - res_base->start + 1);
+               alt_base = devm_ioport_map(&pdev->dev,
+                       res_alt->start, res_alt->end - res_alt->start + 1);
+       }
+
+       memset(&hw, 0, sizeof(hw));
+       plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
+       hw.dev = &pdev->dev;
+
+       if (mmio)
+               d.host_flags |= IDE_HFLAG_MMIO;
+
+       ret = ide_host_add(&d, hws, &host);
+       if (ret)
+               goto out;
+
+       platform_set_drvdata(pdev, host);
+
+       return 0;
+
+out:
+       return ret;
+}
+
+static int __devexit plat_ide_remove(struct platform_device *pdev)
+{
+       struct ide_host *host = pdev->dev.driver_data;
+
+       ide_host_remove(host);
+
+       return 0;
+}
+
+static struct platform_driver platform_ide_driver = {
+       .driver = {
+               .name = "pata_platform",
+               .owner = THIS_MODULE,
+       },
+       .probe = plat_ide_probe,
+       .remove = __devexit_p(plat_ide_remove),
+};
+
+static int __init platform_ide_init(void)
+{
+       return platform_driver_register(&platform_ide_driver);
+}
+
+static void __exit platform_ide_exit(void)
+{
+       platform_driver_unregister(&platform_ide_driver);
+}
+
+MODULE_DESCRIPTION("Platform IDE driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pata_platform");
+
+module_init(platform_ide_init);
+module_exit(platform_ide_exit);
diff --git a/drivers/ide/it8213.c b/drivers/ide/it8213.c
new file mode 100644 (file)
index 0000000..7c2feeb
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * ITE 8213 IDE driver
+ *
+ * Copyright (C) 2006 Jack Lee
+ * Copyright (C) 2006 Alan Cox
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "it8213"
+
+/**
+ *     it8213_set_pio_mode     -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Set the interface PIO mode.
+ */
+
+static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       int is_slave            = drive->dn & 1;
+       int master_port         = 0x40;
+       int slave_port          = 0x44;
+       unsigned long flags;
+       u16 master_data;
+       u8 slave_data;
+       static DEFINE_SPINLOCK(tune_lock);
+       int control = 0;
+
+       static const u8 timings[][2] = {
+                                       { 0, 0 },
+                                       { 0, 0 },
+                                       { 1, 0 },
+                                       { 2, 1 },
+                                       { 2, 3 }, };
+
+       spin_lock_irqsave(&tune_lock, flags);
+       pci_read_config_word(dev, master_port, &master_data);
+
+       if (pio > 1)
+               control |= 1;   /* Programmable timing on */
+       if (drive->media != ide_disk)
+               control |= 4;   /* ATAPI */
+       if (pio > 2)
+               control |= 2;   /* IORDY */
+       if (is_slave) {
+               master_data |=  0x4000;
+               master_data &= ~0x0070;
+               if (pio > 1)
+                       master_data = master_data | (control << 4);
+               pci_read_config_byte(dev, slave_port, &slave_data);
+               slave_data = slave_data & 0xf0;
+               slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1];
+       } else {
+               master_data &= ~0x3307;
+               if (pio > 1)
+                       master_data = master_data | control;
+               master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
+       }
+       pci_write_config_word(dev, master_port, master_data);
+       if (is_slave)
+               pci_write_config_byte(dev, slave_port, slave_data);
+       spin_unlock_irqrestore(&tune_lock, flags);
+}
+
+/**
+ *     it8213_set_dma_mode     -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Tune the ITE chipset for the DMA mode.
+ */
+
+static void it8213_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 maslave              = 0x40;
+       int a_speed             = 3 << (drive->dn * 4);
+       int u_flag              = 1 << drive->dn;
+       int v_flag              = 0x01 << drive->dn;
+       int w_flag              = 0x10 << drive->dn;
+       int u_speed             = 0;
+       u16                     reg4042, reg4a;
+       u8                      reg48, reg54, reg55;
+
+       pci_read_config_word(dev, maslave, &reg4042);
+       pci_read_config_byte(dev, 0x48, &reg48);
+       pci_read_config_word(dev, 0x4a, &reg4a);
+       pci_read_config_byte(dev, 0x54, &reg54);
+       pci_read_config_byte(dev, 0x55, &reg55);
+
+       if (speed >= XFER_UDMA_0) {
+               u8 udma = speed - XFER_UDMA_0;
+
+               u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
+
+               if (!(reg48 & u_flag))
+                       pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+               if (speed >= XFER_UDMA_5)
+                       pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+               else
+                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+
+               if ((reg4a & a_speed) != u_speed)
+                       pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+               if (speed > XFER_UDMA_2) {
+                       if (!(reg54 & v_flag))
+                               pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+               } else
+                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+       } else {
+               const u8 mwdma_to_pio[] = { 0, 3, 4 };
+               u8 pio;
+
+               if (reg48 & u_flag)
+                       pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+               if (reg4a & a_speed)
+                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+               if (reg54 & v_flag)
+                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+               if (reg55 & w_flag)
+                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+
+               if (speed >= XFER_MW_DMA_0)
+                       pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+               else
+                       pio = 2; /* only SWDMA2 is allowed */
+
+               it8213_set_pio_mode(drive, pio);
+       }
+}
+
+static u8 it8213_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u8 reg42h = 0;
+
+       pci_read_config_byte(dev, 0x42, &reg42h);
+
+       return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+static const struct ide_port_ops it8213_port_ops = {
+       .set_pio_mode           = it8213_set_pio_mode,
+       .set_dma_mode           = it8213_set_dma_mode,
+       .cable_detect           = it8213_cable_detect,
+};
+
+static const struct ide_port_info it8213_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = { {0x41, 0x80, 0x80} },
+       .port_ops       = &it8213_port_ops,
+       .host_flags     = IDE_HFLAG_SINGLE,
+       .pio_mask       = ATA_PIO4,
+       .swdma_mask     = ATA_SWDMA2_ONLY,
+       .mwdma_mask     = ATA_MWDMA12_ONLY,
+       .udma_mask      = ATA_UDMA6,
+};
+
+/**
+ *     it8213_init_one -       pci layer discovery entry
+ *     @dev: PCI device
+ *     @id: ident table entry
+ *
+ *     Called by the PCI code when it finds an ITE8213 controller. As
+ *     this device follows the standard interfaces we can use the
+ *     standard helper functions to do almost all the work for us.
+ */
+
+static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &it8213_chipset, NULL);
+}
+
+static const struct pci_device_id it8213_pci_tbl[] = {
+       { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 },
+       { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
+
+static struct pci_driver it8213_pci_driver = {
+       .name           = "ITE8213_IDE",
+       .id_table       = it8213_pci_tbl,
+       .probe          = it8213_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init it8213_ide_init(void)
+{
+       return ide_pci_register_driver(&it8213_pci_driver);
+}
+
+static void __exit it8213_ide_exit(void)
+{
+       pci_unregister_driver(&it8213_pci_driver);
+}
+
+module_init(it8213_ide_init);
+module_exit(it8213_ide_exit);
+
+MODULE_AUTHOR("Jack Lee, Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
new file mode 100644 (file)
index 0000000..995e18b
--- /dev/null
@@ -0,0 +1,706 @@
+/*
+ * Copyright (C) 2004          Red Hat <alan@redhat.com>
+ * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ *  Based in part on the ITE vendor provided SCSI driver.
+ *
+ *  Documentation available from
+ *     http://www.ite.com.tw/pc/IT8212F_V04.pdf
+ *  Some other documents are NDA.
+ *
+ *  The ITE8212 isn't exactly a standard IDE controller. It has two
+ *  modes. In pass through mode then it is an IDE controller. In its smart
+ *  mode its actually quite a capable hardware raid controller disguised
+ *  as an IDE controller. Smart mode only understands DMA read/write and
+ *  identify, none of the fancier commands apply. The IT8211 is identical
+ *  in other respects but lacks the raid mode.
+ *
+ *  Errata:
+ *  o  Rev 0x10 also requires master/slave hold the same DMA timings and
+ *     cannot do ATAPI MWDMA.
+ *  o  The identify data for raid volumes lacks CHS info (technically ok)
+ *     but also fails to set the LBA28 and other bits. We fix these in
+ *     the IDE probe quirk code.
+ *  o  If you write LBA48 sized I/O's (ie > 256 sector) in smart mode
+ *     raid then the controller firmware dies
+ *  o  Smart mode without RAID doesn't clear all the necessary identify
+ *     bits to reduce the command set to the one used
+ *
+ *  This has a few impacts on the driver
+ *  - In pass through mode we do all the work you would expect
+ *  - In smart mode the clocking set up is done by the controller generally
+ *    but we must watch the other limits and filter.
+ *  - There are a few extra vendor commands that actually talk to the
+ *    controller but only work PIO with no IRQ.
+ *
+ *  Vendor areas of the identify block in smart mode are used for the
+ *  timing and policy set up. Each HDD in raid mode also has a serial
+ *  block on the disk. The hardware extra commands are get/set chip status,
+ *  rebuild, get rebuild status.
+ *
+ *  In Linux the driver supports pass through mode as if the device was
+ *  just another IDE controller. If the smart mode is running then
+ *  volumes are managed by the controller firmware and each IDE "disk"
+ *  is a raid volume. Even more cute - the controller can do automated
+ *  hotplug and rebuild.
+ *
+ *  The pass through controller itself is a little demented. It has a
+ *  flaw that it has a single set of PIO/MWDMA timings per channel so
+ *  non UDMA devices restrict each others performance. It also has a
+ *  single clock source per channel so mixed UDMA100/133 performance
+ *  isn't perfect and we have to pick a clock. Thankfully none of this
+ *  matters in smart mode. ATAPI DMA is not currently supported.
+ *
+ *  It seems the smart mode is a win for RAID1/RAID10 but otherwise not.
+ *
+ *  TODO
+ *     -       ATAPI UDMA is ok but not MWDMA it seems
+ *     -       RAID configuration ioctls
+ *     -       Move to libata once it grows up
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "it821x"
+
+struct it821x_dev
+{
+       unsigned int smart:1,           /* Are we in smart raid mode */
+               timing10:1;             /* Rev 0x10 */
+       u8      clock_mode;             /* 0, ATA_50 or ATA_66 */
+       u8      want[2][2];             /* Mode/Pri log for master slave */
+       /* We need these for switching the clock when DMA goes on/off
+          The high byte is the 66Mhz timing */
+       u16     pio[2];                 /* Cached PIO values */
+       u16     mwdma[2];               /* Cached MWDMA values */
+       u16     udma[2];                /* Cached UDMA values (per drive) */
+};
+
+#define ATA_66         0
+#define ATA_50         1
+#define ATA_ANY                2
+
+#define UDMA_OFF       0
+#define MWDMA_OFF      0
+
+/*
+ *     We allow users to force the card into non raid mode without
+ *     flashing the alternative BIOS. This is also necessary right now
+ *     for embedded platforms that cannot run a PC BIOS but are using this
+ *     device.
+ */
+
+static int it8212_noraid;
+
+/**
+ *     it821x_program  -       program the PIO/MWDMA registers
+ *     @drive: drive to tune
+ *     @timing: timing info
+ *
+ *     Program the PIO/MWDMA timing for this channel according to the
+ *     current clock.
+ */
+
+static void it821x_program(ide_drive_t *drive, u16 timing)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       int channel = hwif->channel;
+       u8 conf;
+
+       /* Program PIO/MWDMA timing bits */
+       if(itdev->clock_mode == ATA_66)
+               conf = timing >> 8;
+       else
+               conf = timing & 0xFF;
+
+       pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
+}
+
+/**
+ *     it821x_program_udma     -       program the UDMA registers
+ *     @drive: drive to tune
+ *     @timing: timing info
+ *
+ *     Program the UDMA timing for this drive according to the
+ *     current clock.
+ */
+
+static void it821x_program_udma(ide_drive_t *drive, u16 timing)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       int channel = hwif->channel;
+       u8 unit = drive->dn & 1, conf;
+
+       /* Program UDMA timing bits */
+       if(itdev->clock_mode == ATA_66)
+               conf = timing >> 8;
+       else
+               conf = timing & 0xFF;
+
+       if (itdev->timing10 == 0)
+               pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
+       else {
+               pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
+               pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
+       }
+}
+
+/**
+ *     it821x_clock_strategy
+ *     @drive: drive to set up
+ *
+ *     Select between the 50 and 66Mhz base clocks to get the best
+ *     results for this interface.
+ */
+
+static void it821x_clock_strategy(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       ide_drive_t *pair;
+       int clock, altclock, sel = 0;
+       u8 unit = drive->dn & 1, v;
+
+       pair = &hwif->drives[1 - unit];
+
+       if(itdev->want[0][0] > itdev->want[1][0]) {
+               clock = itdev->want[0][1];
+               altclock = itdev->want[1][1];
+       } else {
+               clock = itdev->want[1][1];
+               altclock = itdev->want[0][1];
+       }
+
+       /*
+        * if both clocks can be used for the mode with the higher priority
+        * use the clock needed by the mode with the lower priority
+        */
+       if (clock == ATA_ANY)
+               clock = altclock;
+
+       /* Nobody cares - keep the same clock */
+       if(clock == ATA_ANY)
+               return;
+       /* No change */
+       if(clock == itdev->clock_mode)
+               return;
+
+       /* Load this into the controller ? */
+       if(clock == ATA_66)
+               itdev->clock_mode = ATA_66;
+       else {
+               itdev->clock_mode = ATA_50;
+               sel = 1;
+       }
+
+       pci_read_config_byte(dev, 0x50, &v);
+       v &= ~(1 << (1 + hwif->channel));
+       v |= sel << (1 + hwif->channel);
+       pci_write_config_byte(dev, 0x50, v);
+
+       /*
+        *      Reprogram the UDMA/PIO of the pair drive for the switch
+        *      MWDMA will be dealt with by the dma switcher
+        */
+       if(pair && itdev->udma[1-unit] != UDMA_OFF) {
+               it821x_program_udma(pair, itdev->udma[1-unit]);
+               it821x_program(pair, itdev->pio[1-unit]);
+       }
+       /*
+        *      Reprogram the UDMA/PIO of our drive for the switch.
+        *      MWDMA will be dealt with by the dma switcher
+        */
+       if(itdev->udma[unit] != UDMA_OFF) {
+               it821x_program_udma(drive, itdev->udma[unit]);
+               it821x_program(drive, itdev->pio[unit]);
+       }
+}
+
+/**
+ *     it821x_set_pio_mode     -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Tune the host to the desired PIO mode taking into the consideration
+ *     the maximum PIO mode supported by the other device on the cable.
+ */
+
+static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       ide_drive_t *pair;
+       u8 unit = drive->dn & 1, set_pio = pio;
+
+       /* Spec says 89 ref driver uses 88 */
+       static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
+       static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
+
+       pair = &hwif->drives[1 - unit];
+
+       /*
+        * Compute the best PIO mode we can for a given device. We must
+        * pick a speed that does not cause problems with the other device
+        * on the cable.
+        */
+       if (pair) {
+               u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
+               /* trim PIO to the slowest of the master/slave */
+               if (pair_pio < set_pio)
+                       set_pio = pair_pio;
+       }
+
+       /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
+       itdev->want[unit][1] = pio_want[set_pio];
+       itdev->want[unit][0] = 1;       /* PIO is lowest priority */
+       itdev->pio[unit] = pio_timings[set_pio];
+       it821x_clock_strategy(drive);
+       it821x_program(drive, itdev->pio[unit]);
+}
+
+/**
+ *     it821x_tune_mwdma       -       tune a channel for MWDMA
+ *     @drive: drive to set up
+ *     @mode_wanted: the target operating mode
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller when doing MWDMA in pass through mode. The caller
+ *     must manage the whole lack of per device MWDMA/PIO timings and
+ *     the shared MWDMA/PIO timing register.
+ */
+
+static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
+       u8 unit = drive->dn & 1, channel = hwif->channel, conf;
+
+       static u16 dma[]        = { 0x8866, 0x3222, 0x3121 };
+       static u8 mwdma_want[]  = { ATA_ANY, ATA_66, ATA_ANY };
+
+       itdev->want[unit][1] = mwdma_want[mode_wanted];
+       itdev->want[unit][0] = 2;       /* MWDMA is low priority */
+       itdev->mwdma[unit] = dma[mode_wanted];
+       itdev->udma[unit] = UDMA_OFF;
+
+       /* UDMA bits off - Revision 0x10 do them in pairs */
+       pci_read_config_byte(dev, 0x50, &conf);
+       if (itdev->timing10)
+               conf |= channel ? 0x60: 0x18;
+       else
+               conf |= 1 << (3 + 2 * channel + unit);
+       pci_write_config_byte(dev, 0x50, conf);
+
+       it821x_clock_strategy(drive);
+       /* FIXME: do we need to program this ? */
+       /* it821x_program(drive, itdev->mwdma[unit]); */
+}
+
+/**
+ *     it821x_tune_udma        -       tune a channel for UDMA
+ *     @drive: drive to set up
+ *     @mode_wanted: the target operating mode
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller when doing UDMA modes in pass through.
+ */
+
+static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       u8 unit = drive->dn & 1, channel = hwif->channel, conf;
+
+       static u16 udma[]       = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
+       static u8 udma_want[]   = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
+
+       itdev->want[unit][1] = udma_want[mode_wanted];
+       itdev->want[unit][0] = 3;       /* UDMA is high priority */
+       itdev->mwdma[unit] = MWDMA_OFF;
+       itdev->udma[unit] = udma[mode_wanted];
+       if(mode_wanted >= 5)
+               itdev->udma[unit] |= 0x8080;    /* UDMA 5/6 select on */
+
+       /* UDMA on. Again revision 0x10 must do the pair */
+       pci_read_config_byte(dev, 0x50, &conf);
+       if (itdev->timing10)
+               conf &= channel ? 0x9F: 0xE7;
+       else
+               conf &= ~ (1 << (3 + 2 * channel + unit));
+       pci_write_config_byte(dev, 0x50, conf);
+
+       it821x_clock_strategy(drive);
+       it821x_program_udma(drive, itdev->udma[unit]);
+
+}
+
+/**
+ *     it821x_dma_read -       DMA hook
+ *     @drive: drive for DMA
+ *
+ *     The IT821x has a single timing register for MWDMA and for PIO
+ *     operations. As we flip back and forth we have to reload the
+ *     clock. In addition the rev 0x10 device only works if the same
+ *     timing value is loaded into the master and slave UDMA clock
+ *     so we must also reload that.
+ *
+ *     FIXME: we could figure out in advance if we need to do reloads
+ */
+
+static void it821x_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       u8 unit = drive->dn & 1;
+
+       if(itdev->mwdma[unit] != MWDMA_OFF)
+               it821x_program(drive, itdev->mwdma[unit]);
+       else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
+               it821x_program_udma(drive, itdev->udma[unit]);
+       ide_dma_start(drive);
+}
+
+/**
+ *     it821x_dma_write        -       DMA hook
+ *     @drive: drive for DMA stop
+ *
+ *     The IT821x has a single timing register for MWDMA and for PIO
+ *     operations. As we flip back and forth we have to reload the
+ *     clock.
+ */
+
+static int it821x_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       int ret = ide_dma_end(drive);
+       u8 unit = drive->dn & 1;
+
+       if(itdev->mwdma[unit] != MWDMA_OFF)
+               it821x_program(drive, itdev->pio[unit]);
+       return ret;
+}
+
+/**
+ *     it821x_set_dma_mode     -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Tune the ITE chipset for the desired DMA mode.
+ */
+
+static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       /*
+        * MWDMA tuning is really hard because our MWDMA and PIO
+        * timings are kept in the same place.  We can switch in the
+        * host dma on/off callbacks.
+        */
+       if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6)
+               it821x_tune_udma(drive, speed - XFER_UDMA_0);
+       else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+               it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0);
+}
+
+/**
+ *     it821x_cable_detect     -       cable detection
+ *     @hwif: interface to check
+ *
+ *     Check for the presence of an ATA66 capable cable on the
+ *     interface. Problematic as it seems some cards don't have
+ *     the needed logic onboard.
+ */
+
+static u8 it821x_cable_detect(ide_hwif_t *hwif)
+{
+       /* The reference driver also only does disk side */
+       return ATA_CBL_PATA80;
+}
+
+/**
+ *     it821x_quirkproc        -       post init callback
+ *     @drive: drive
+ *
+ *     This callback is run after the drive has been probed but
+ *     before anything gets attached. It allows drivers to do any
+ *     final tuning that is needed, or fixups to work around bugs.
+ */
+
+static void it821x_quirkproc(ide_drive_t *drive)
+{
+       struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
+       u16 *id = drive->id;
+
+       if (!itdev->smart) {
+               /*
+                *      If we are in pass through mode then not much
+                *      needs to be done, but we do bother to clear the
+                *      IRQ mask as we may well be in PIO (eg rev 0x10)
+                *      for now and we know unmasking is safe on this chipset.
+                */
+               drive->dev_flags |= IDE_DFLAG_UNMASK;
+       } else {
+       /*
+        *      Perform fixups on smart mode. We need to "lose" some
+        *      capabilities the firmware lacks but does not filter, and
+        *      also patch up some capability bits that it forgets to set
+        *      in RAID mode.
+        */
+
+               /* Check for RAID v native */
+               if (strstr((char *)&id[ATA_ID_PROD],
+                          "Integrated Technology Express")) {
+                       /* In raid mode the ident block is slightly buggy
+                          We need to set the bits so that the IDE layer knows
+                          LBA28. LBA48 and DMA ar valid */
+                       id[ATA_ID_CAPABILITY]    |= (3 << 8); /* LBA28, DMA */
+                       id[ATA_ID_COMMAND_SET_2] |= 0x0400;   /* LBA48 valid */
+                       id[ATA_ID_CFS_ENABLE_2]  |= 0x0400;   /* LBA48 on */
+                       /* Reporting logic */
+                       printk(KERN_INFO "%s: IT8212 %sRAID %d volume",
+                               drive->name, id[147] ? "Bootable " : "",
+                               id[ATA_ID_CSFO]);
+                       if (id[ATA_ID_CSFO] != 1)
+                               printk(KERN_CONT "(%dK stripe)", id[146]);
+                       printk(KERN_CONT ".\n");
+               } else {
+                       /* Non RAID volume. Fixups to stop the core code
+                          doing unsupported things */
+                       id[ATA_ID_FIELD_VALID]   &= 3;
+                       id[ATA_ID_QUEUE_DEPTH]    = 0;
+                       id[ATA_ID_COMMAND_SET_1]  = 0;
+                       id[ATA_ID_COMMAND_SET_2] &= 0xC400;
+                       id[ATA_ID_CFSSE]         &= 0xC000;
+                       id[ATA_ID_CFS_ENABLE_1]   = 0;
+                       id[ATA_ID_CFS_ENABLE_2]  &= 0xC400;
+                       id[ATA_ID_CSF_DEFAULT]   &= 0xC000;
+                       id[127]                   = 0;
+                       id[ATA_ID_DLF]            = 0;
+                       id[ATA_ID_CSFO]           = 0;
+                       id[ATA_ID_CFA_POWER]      = 0;
+                       printk(KERN_INFO "%s: Performing identify fixups.\n",
+                               drive->name);
+               }
+
+               /*
+                * Set MWDMA0 mode as enabled/support - just to tell
+                * IDE core that DMA is supported (it821x hardware
+                * takes care of DMA mode programming).
+                */
+               if (ata_id_has_dma(id)) {
+                       id[ATA_ID_MWDMA_MODES] |= 0x0101;
+                       drive->current_speed = XFER_MW_DMA_0;
+               }
+       }
+
+}
+
+static struct ide_dma_ops it821x_pass_through_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = it821x_dma_start,
+       .dma_end                = it821x_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+};
+
+/**
+ *     init_hwif_it821x        -       set up hwif structs
+ *     @hwif: interface to set up
+ *
+ *     We do the basic set up of the interface structure. The IT8212
+ *     requires several custom handlers so we override the default
+ *     ide DMA handlers appropriately
+ */
+
+static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct it821x_dev *itdevs = host->host_priv;
+       struct it821x_dev *idev = itdevs + hwif->channel;
+       u8 conf;
+
+       ide_set_hwifdata(hwif, idev);
+
+       pci_read_config_byte(dev, 0x50, &conf);
+       if (conf & 1) {
+               idev->smart = 1;
+               hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+               /* Long I/O's although allowed in LBA48 space cause the
+                  onboard firmware to enter the twighlight zone */
+               hwif->rqsize = 256;
+       }
+
+       /* Pull the current clocks from 0x50 also */
+       if (conf & (1 << (1 + hwif->channel)))
+               idev->clock_mode = ATA_50;
+       else
+               idev->clock_mode = ATA_66;
+
+       idev->want[0][1] = ATA_ANY;
+       idev->want[1][1] = ATA_ANY;
+
+       /*
+        *      Not in the docs but according to the reference driver
+        *      this is necessary.
+        */
+
+       pci_read_config_byte(dev, 0x08, &conf);
+       if (conf == 0x10) {
+               idev->timing10 = 1;
+               hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+               if (idev->smart == 0)
+                       printk(KERN_WARNING DRV_NAME " %s: revision 0x10, "
+                               "workarounds activated\n", pci_name(dev));
+       }
+
+       if (idev->smart == 0) {
+               /* MWDMA/PIO clock switching for pass through mode */
+               hwif->dma_ops = &it821x_pass_through_dma_ops;
+       } else
+               hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
+
+       if (hwif->dma_base == 0)
+               return;
+
+       hwif->ultra_mask = ATA_UDMA6;
+       hwif->mwdma_mask = ATA_MWDMA2;
+}
+
+static void it8212_disable_raid(struct pci_dev *dev)
+{
+       /* Reset local CPU, and set BIOS not ready */
+       pci_write_config_byte(dev, 0x5E, 0x01);
+
+       /* Set to bypass mode, and reset PCI bus */
+       pci_write_config_byte(dev, 0x50, 0x00);
+       pci_write_config_word(dev, PCI_COMMAND,
+                             PCI_COMMAND_PARITY | PCI_COMMAND_IO |
+                             PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+       pci_write_config_word(dev, 0x40, 0xA0F3);
+
+       pci_write_config_dword(dev,0x4C, 0x02040204);
+       pci_write_config_byte(dev, 0x42, 0x36);
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+}
+
+static unsigned int init_chipset_it821x(struct pci_dev *dev)
+{
+       u8 conf;
+       static char *mode[2] = { "pass through", "smart" };
+
+       /* Force the card into bypass mode if so requested */
+       if (it8212_noraid) {
+               printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n",
+                       pci_name(dev));
+               it8212_disable_raid(dev);
+       }
+       pci_read_config_byte(dev, 0x50, &conf);
+       printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n",
+               pci_name(dev), mode[conf & 1]);
+       return 0;
+}
+
+static const struct ide_port_ops it821x_port_ops = {
+       /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */
+       .set_pio_mode           = it821x_set_pio_mode,
+       .set_dma_mode           = it821x_set_dma_mode,
+       .quirkproc              = it821x_quirkproc,
+       .cable_detect           = it821x_cable_detect,
+};
+
+static const struct ide_port_info it821x_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_it821x,
+       .init_hwif      = init_hwif_it821x,
+       .port_ops       = &it821x_port_ops,
+       .pio_mask       = ATA_PIO4,
+};
+
+/**
+ *     it821x_init_one -       pci layer discovery entry
+ *     @dev: PCI device
+ *     @id: ident table entry
+ *
+ *     Called by the PCI code when it finds an ITE821x controller.
+ *     We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct it821x_dev *itdevs;
+       int rc;
+
+       itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL);
+       if (itdevs == NULL) {
+               printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev));
+               return -ENOMEM;
+       }
+
+       rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
+       if (rc)
+               kfree(itdevs);
+
+       return rc;
+}
+
+static void __devexit it821x_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct it821x_dev *itdevs = host->host_priv;
+
+       ide_pci_remove(dev);
+       kfree(itdevs);
+}
+
+static const struct pci_device_id it821x_pci_tbl[] = {
+       { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },
+       { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },
+       { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
+
+static struct pci_driver it821x_pci_driver = {
+       .name           = "ITE821x IDE",
+       .id_table       = it821x_pci_tbl,
+       .probe          = it821x_init_one,
+       .remove         = __devexit_p(it821x_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init it821x_ide_init(void)
+{
+       return ide_pci_register_driver(&it821x_pci_driver);
+}
+
+static void __exit it821x_ide_exit(void)
+{
+       pci_unregister_driver(&it821x_pci_driver);
+}
+
+module_init(it821x_ide_init);
+module_exit(it821x_ide_exit);
+
+module_param_named(noraid, it8212_noraid, int, S_IRUGO);
+MODULE_PARM_DESC(noraid, "Force card into bypass mode");
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for the ITE 821x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/jmicron.c b/drivers/ide/jmicron.c
new file mode 100644 (file)
index 0000000..9a68433
--- /dev/null
@@ -0,0 +1,176 @@
+
+/*
+ * Copyright (C) 2006          Red Hat <alan@redhat.com>
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "jmicron"
+
+typedef enum {
+       PORT_PATA0 = 0,
+       PORT_PATA1 = 1,
+       PORT_SATA = 2,
+} port_type;
+
+/**
+ *     jmicron_cable_detect    -       cable detection
+ *     @hwif: IDE port
+ *
+ *     Returns the cable type.
+ */
+
+static u8 jmicron_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+
+       u32 control;
+       u32 control5;
+
+       int port = hwif->channel;
+       port_type port_map[2];
+
+       pci_read_config_dword(pdev, 0x40, &control);
+
+       /* There are two basic mappings. One has the two SATA ports merged
+          as master/slave and the secondary as PATA, the other has only the
+          SATA port mapped */
+       if (control & (1 << 23)) {
+               port_map[0] = PORT_SATA;
+               port_map[1] = PORT_PATA0;
+       } else {
+               port_map[0] = PORT_SATA;
+               port_map[1] = PORT_SATA;
+       }
+
+       /* The 365/366 may have this bit set to map the second PATA port
+          as the internal primary channel */
+       pci_read_config_dword(pdev, 0x80, &control5);
+       if (control5 & (1<<24))
+               port_map[0] = PORT_PATA1;
+
+       /* The two ports may then be logically swapped by the firmware */
+       if (control & (1 << 22))
+               port = port ^ 1;
+
+       /*
+        *      Now we know which physical port we are talking about we can
+        *      actually do our cable checking etc. Thankfully we don't need
+        *      to do the plumbing for other cases.
+        */
+       switch (port_map[port]) {
+       case PORT_PATA0:
+               if (control & (1 << 3)) /* 40/80 pin primary */
+                       return ATA_CBL_PATA40;
+               return ATA_CBL_PATA80;
+       case PORT_PATA1:
+               if (control5 & (1 << 19))       /* 40/80 pin secondary */
+                       return ATA_CBL_PATA40;
+               return ATA_CBL_PATA80;
+       case PORT_SATA:
+               break;
+       }
+       /* Avoid bogus "control reaches end of non-void function" */
+       return ATA_CBL_PATA80;
+}
+
+static void jmicron_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+}
+
+/**
+ *     jmicron_set_dma_mode    -       set host controller for DMA mode
+ *     @drive: drive
+ *     @mode: DMA mode
+ *
+ *     As the JMicron snoops for timings we don't need to do anything here.
+ */
+
+static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+}
+
+static const struct ide_port_ops jmicron_port_ops = {
+       .set_pio_mode           = jmicron_set_pio_mode,
+       .set_dma_mode           = jmicron_set_dma_mode,
+       .cable_detect           = jmicron_cable_detect,
+};
+
+static const struct ide_port_info jmicron_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
+       .port_ops       = &jmicron_port_ops,
+       .pio_mask       = ATA_PIO5,
+       .mwdma_mask     = ATA_MWDMA2,
+       .udma_mask      = ATA_UDMA6,
+};
+
+/**
+ *     jmicron_init_one        -       pci layer discovery entry
+ *     @dev: PCI device
+ *     @id: ident table entry
+ *
+ *     Called by the PCI code when it finds a Jmicron controller.
+ *     We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &jmicron_chipset, NULL);
+}
+
+/* All JMB PATA controllers have and will continue to have the same
+ * interface.  Matching vendor and device class is enough for all
+ * current and future controllers if the controller is programmed
+ * properly.
+ *
+ * If libata is configured, jmicron PCI quirk programs the controller
+ * into the correct mode.  If libata isn't configured, match known
+ * device IDs too to maintain backward compatibility.
+ */
+static struct pci_device_id jmicron_pci_tbl[] = {
+#if !defined(CONFIG_ATA) && !defined(CONFIG_ATA_MODULE)
+       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361) },
+       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363) },
+       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365) },
+       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366) },
+       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368) },
+#endif
+       { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
+       { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
+
+static struct pci_driver jmicron_pci_driver = {
+       .name           = "JMicron IDE",
+       .id_table       = jmicron_pci_tbl,
+       .probe          = jmicron_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init jmicron_ide_init(void)
+{
+       return ide_pci_register_driver(&jmicron_pci_driver);
+}
+
+static void __exit jmicron_ide_exit(void)
+{
+       pci_unregister_driver(&jmicron_pci_driver);
+}
+
+module_init(jmicron_ide_init);
+module_exit(jmicron_ide_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
deleted file mode 100644 (file)
index 6939329..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-
-# link order is important here
-
-obj-$(CONFIG_BLK_DEV_ALI14XX)          += ali14xx.o
-obj-$(CONFIG_BLK_DEV_UMC8672)          += umc8672.o
-obj-$(CONFIG_BLK_DEV_DTC2278)          += dtc2278.o
-obj-$(CONFIG_BLK_DEV_HT6560B)          += ht6560b.o
-obj-$(CONFIG_BLK_DEV_QD65XX)           += qd65xx.o
-obj-$(CONFIG_BLK_DEV_4DRIVES)          += ide-4drives.o
-
-obj-$(CONFIG_BLK_DEV_GAYLE)            += gayle.o
-obj-$(CONFIG_BLK_DEV_FALCON_IDE)       += falconide.o
-obj-$(CONFIG_BLK_DEV_MAC_IDE)          += macide.o
-obj-$(CONFIG_BLK_DEV_Q40IDE)           += q40ide.o
-obj-$(CONFIG_BLK_DEV_BUDDHA)           += buddha.o
-
-ifeq ($(CONFIG_BLK_DEV_IDECS), m)
-       obj-m += ide-cs.o
-endif
-
-ifeq ($(CONFIG_BLK_DEV_PLATFORM), m)
-       obj-m += ide_platform.o
-endif
-
-EXTRA_CFLAGS   := -Idrivers/ide
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
deleted file mode 100644 (file)
index 90da1f9..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- *  Copyright (C) 1996  Linus Torvalds & author (see below)
- */
-
-/*
- * ALI M14xx chipset EIDE controller
- *
- * Works for ALI M1439/1443/1445/1487/1489 chipsets.
- *
- * Adapted from code developed by derekn@vw.ece.cmu.edu.  -ml
- * Derek's notes follow:
- *
- * I think the code should be pretty understandable,
- * but I'll be happy to (try to) answer questions.
- *
- * The critical part is in the setupDrive function.  The initRegisters
- * function doesn't seem to be necessary, but the DOS driver does it, so
- * I threw it in.
- *
- * I've only tested this on my system, which only has one disk.  I posted
- * it to comp.sys.linux.hardware, so maybe some other people will try it
- * out.
- *
- * Derek Noonburg  (derekn@ece.cmu.edu)
- * 95-sep-26
- *
- * Update 96-jul-13:
- *
- * I've since upgraded to two disks and a CD-ROM, with no trouble, and
- * I've also heard from several others who have used it successfully.
- * This driver appears to work with both the 1443/1445 and the 1487/1489
- * chipsets.  I've added support for PIO mode 4 for the 1487.  This
- * seems to work just fine on the 1443 also, although I'm not sure it's
- * advertised as supporting mode 4.  (I've been running a WDC AC21200 in
- * mode 4 for a while now with no trouble.)  -Derek
- */
-
-#include <linux/module.h>
-#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/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "ali14xx"
-
-/* port addresses for auto-detection */
-#define ALI_NUM_PORTS 4
-static const int ports[ALI_NUM_PORTS] __initdata =
-       { 0x074, 0x0f4, 0x034, 0x0e4 };
-
-/* register initialization data */
-typedef struct { u8 reg, data; } RegInitializer;
-
-static const RegInitializer initData[] __initdata = {
-       {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
-       {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
-       {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
-       {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
-       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
-       {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
-       {0x35, 0x03}, {0x00, 0x00}
-};
-
-/* timing parameter registers for each drive */
-static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
-       {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
-       {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
-       {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
-       {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
-};
-
-static int basePort;   /* base port address */
-static int regPort;    /* port for register number */
-static int dataPort;   /* port for register data */
-static u8 regOn;       /* output to base port to access registers */
-static u8 regOff;      /* output to base port to close registers */
-
-/*------------------------------------------------------------------------*/
-
-/*
- * Read a controller register.
- */
-static inline u8 inReg(u8 reg)
-{
-       outb_p(reg, regPort);
-       return inb(dataPort);
-}
-
-/*
- * Write a controller register.
- */
-static void outReg(u8 data, u8 reg)
-{
-       outb_p(reg, regPort);
-       outb_p(data, dataPort);
-}
-
-static DEFINE_SPINLOCK(ali14xx_lock);
-
-/*
- * Set PIO mode for the specified drive.
- * This function computes timing parameters
- * and sets controller registers accordingly.
- */
-static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       int driveNum;
-       int time1, time2;
-       u8 param1, param2, param3, param4;
-       unsigned long flags;
-       int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
-       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-
-       /* calculate timing, according to PIO mode */
-       time1 = ide_pio_cycle_time(drive, pio);
-       time2 = t->active;
-       param3 = param1 = (time2 * bus_speed + 999) / 1000;
-       param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
-       if (pio < 3) {
-               param3 += 8;
-               param4 += 8;
-       }
-       printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
-               drive->name, pio, time1, time2, param1, param2, param3, param4);
-
-       /* stuff timing parameters into controller registers */
-       driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
-       spin_lock_irqsave(&ali14xx_lock, flags);
-       outb_p(regOn, basePort);
-       outReg(param1, regTab[driveNum].reg1);
-       outReg(param2, regTab[driveNum].reg2);
-       outReg(param3, regTab[driveNum].reg3);
-       outReg(param4, regTab[driveNum].reg4);
-       outb_p(regOff, basePort);
-       spin_unlock_irqrestore(&ali14xx_lock, flags);
-}
-
-/*
- * Auto-detect the IDE controller port.
- */
-static int __init findPort(void)
-{
-       int i;
-       u8 t;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       for (i = 0; i < ALI_NUM_PORTS; ++i) {
-               basePort = ports[i];
-               regOff = inb(basePort);
-               for (regOn = 0x30; regOn <= 0x33; ++regOn) {
-                       outb_p(regOn, basePort);
-                       if (inb(basePort) == regOn) {
-                               regPort = basePort + 4;
-                               dataPort = basePort + 8;
-                               t = inReg(0) & 0xf0;
-                               outb_p(regOff, basePort);
-                               local_irq_restore(flags);
-                               if (t != 0x50)
-                                       return 0;
-                               return 1;  /* success */
-                       }
-               }
-               outb_p(regOff, basePort);
-       }
-       local_irq_restore(flags);
-       return 0;
-}
-
-/*
- * Initialize controller registers with default values.
- */
-static int __init initRegisters(void)
-{
-       const RegInitializer *p;
-       u8 t;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       outb_p(regOn, basePort);
-       for (p = initData; p->reg != 0; ++p)
-               outReg(p->data, p->reg);
-       outb_p(0x01, regPort);
-       t = inb(regPort) & 0x01;
-       outb_p(regOff, basePort);
-       local_irq_restore(flags);
-       return t;
-}
-
-static const struct ide_port_ops ali14xx_port_ops = {
-       .set_pio_mode           = ali14xx_set_pio_mode,
-};
-
-static const struct ide_port_info ali14xx_port_info = {
-       .name                   = DRV_NAME,
-       .chipset                = ide_ali14xx,
-       .port_ops               = &ali14xx_port_ops,
-       .host_flags             = IDE_HFLAG_NO_DMA,
-       .pio_mask               = ATA_PIO4,
-};
-
-static int __init ali14xx_probe(void)
-{
-       printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
-                         basePort, regOn);
-
-       /* initialize controller registers */
-       if (!initRegisters()) {
-               printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
-               return 1;
-       }
-
-       return ide_legacy_device_add(&ali14xx_port_info, 0);
-}
-
-static int probe_ali14xx;
-
-module_param_named(probe, probe_ali14xx, bool, 0);
-MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
-
-static int __init ali14xx_init(void)
-{
-       if (probe_ali14xx == 0)
-               goto out;
-
-       /* auto-detect IDE controller port */
-       if (findPort()) {
-               if (ali14xx_probe())
-                       return -ENODEV;
-               return 0;
-       }
-       printk(KERN_ERR "ali14xx: not found.\n");
-out:
-       return -ENODEV;
-}
-
-module_init(ali14xx_init);
-
-MODULE_AUTHOR("see local file");
-MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
deleted file mode 100644 (file)
index c5a3c9e..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  Amiga Buddha, Catweasel and X-Surf IDE Driver
- *
- *     Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
- *
- *  This driver was written based on the specifications in README.buddha and
- *  the X-Surf info from Inside_XSurf.txt available at
- *  http://www.jschoenfeld.com
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- *  TODO:
- *    - test it :-)
- *    - tune the timings using the speed-register
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/zorro.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-
-
-    /*
-     *  The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2
-     */
-
-#define BUDDHA_NUM_HWIFS       2
-#define CATWEASEL_NUM_HWIFS    3
-#define XSURF_NUM_HWIFS         2
-
-#define MAX_NUM_HWIFS          3
-
-    /*
-     *  Bases of the IDE interfaces (relative to the board address)
-     */
-
-#define BUDDHA_BASE1   0x800
-#define BUDDHA_BASE2   0xa00
-#define BUDDHA_BASE3   0xc00
-
-#define XSURF_BASE1     0xb000 /* 2.5" Interface */
-#define XSURF_BASE2     0xd000 /* 3.5" Interface */
-
-static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
-    BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
-};
-
-static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
-     XSURF_BASE1, XSURF_BASE2
-};
-
-    /*
-     *  Offsets from one of the above bases
-     */
-
-#define BUDDHA_CONTROL 0x11a
-
-    /*
-     *  Other registers
-     */
-
-#define BUDDHA_IRQ1    0xf00           /* MSB = 1, Harddisk is source of */
-#define BUDDHA_IRQ2    0xf40           /* interrupt */
-#define BUDDHA_IRQ3    0xf80
-
-#define XSURF_IRQ1      0x7e
-#define XSURF_IRQ2      0x7e
-
-static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
-    BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
-};
-
-static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = {
-    XSURF_IRQ1, XSURF_IRQ2
-};
-
-#define BUDDHA_IRQ_MR  0xfc0           /* master interrupt enable */
-
-
-    /*
-     *  Board information
-     */
-
-typedef enum BuddhaType_Enum {
-    BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
-} BuddhaType;
-
-static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" };
-
-    /*
-     *  Check and acknowledge the interrupt status
-     */
-
-static int buddha_ack_intr(ide_hwif_t *hwif)
-{
-    unsigned char ch;
-
-    ch = z_readb(hwif->io_ports.irq_addr);
-    if (!(ch & 0x80))
-           return 0;
-    return 1;
-}
-
-static int xsurf_ack_intr(ide_hwif_t *hwif)
-{
-    unsigned char ch;
-
-    ch = z_readb(hwif->io_ports.irq_addr);
-    /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
-    z_writeb(0, hwif->io_ports.irq_addr);
-    if (!(ch & 0x80))
-           return 0;
-    return 1;
-}
-
-static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
-                                     unsigned long ctl, unsigned long irq_port,
-                                     ide_ack_intr_t *ack_intr)
-{
-       int i;
-
-       memset(hw, 0, sizeof(*hw));
-
-       hw->io_ports.data_addr = base;
-
-       for (i = 1; i < 8; i++)
-               hw->io_ports_array[i] = base + 2 + i * 4;
-
-       hw->io_ports.ctl_addr = ctl;
-       hw->io_ports.irq_addr = irq_port;
-
-       hw->irq = IRQ_AMIGA_PORTS;
-       hw->ack_intr = ack_intr;
-
-       hw->chipset = ide_generic;
-}
-
-    /*
-     *  Probe for a Buddha or Catweasel IDE interface
-     */
-
-static int __init buddha_init(void)
-{
-       struct zorro_dev *z = NULL;
-       u_long buddha_board = 0;
-       BuddhaType type;
-       int buddha_num_hwifs, i;
-
-       while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-               unsigned long board;
-               hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
-
-               if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
-                       buddha_num_hwifs = BUDDHA_NUM_HWIFS;
-                       type=BOARD_BUDDHA;
-               } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) {
-                       buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
-                       type=BOARD_CATWEASEL;
-               } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) {
-                       buddha_num_hwifs = XSURF_NUM_HWIFS;
-                       type=BOARD_XSURF;
-               } else 
-                       continue;
-               
-               board = z->resource.start;
-
-/*
- * FIXME: we now have selectable mmio v/s iomio transports.
- */
-
-               if(type != BOARD_XSURF) {
-                       if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
-                               continue;
-               } else {
-                       if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE"))
-                               continue;
-                       if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE"))
-                               goto fail_base2;
-                       if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) {
-                               release_mem_region(board+XSURF_BASE2, 0x1000);
-fail_base2:
-                               release_mem_region(board+XSURF_BASE1, 0x1000);
-                               continue;
-                       }
-               }         
-               buddha_board = ZTWO_VADDR(board);
-               
-               /* write to BUDDHA_IRQ_MR to enable the board IRQ */
-               /* X-Surf doesn't have this.  IRQs are always on */
-               if (type != BOARD_XSURF)
-                       z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
-
-               printk(KERN_INFO "ide: %s IDE controller\n",
-                                buddha_board_name[type]);
-
-               for (i = 0; i < buddha_num_hwifs; i++) {
-                       unsigned long base, ctl, irq_port;
-                       ide_ack_intr_t *ack_intr;
-
-                       if (type != BOARD_XSURF) {
-                               base = buddha_board + buddha_bases[i];
-                               ctl = base + BUDDHA_CONTROL;
-                               irq_port = buddha_board + buddha_irqports[i];
-                               ack_intr = buddha_ack_intr;
-                       } else {
-                               base = buddha_board + xsurf_bases[i];
-                               /* X-Surf has no CS1* (Control/AltStat) */
-                               ctl = 0;
-                               irq_port = buddha_board + xsurf_irqports[i];
-                               ack_intr = xsurf_ack_intr;
-                       }
-
-                       buddha_setup_ports(&hw[i], base, ctl, irq_port,
-                                          ack_intr);
-
-                       hws[i] = &hw[i];
-               }
-
-               ide_host_add(NULL, hws, NULL);
-       }
-
-       return 0;
-}
-
-module_init(buddha_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
deleted file mode 100644 (file)
index 689b2e4..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  Copyright (C) 1996  Linus Torvalds & author (see below)
- */
-
-#include <linux/module.h>
-#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/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "dtc2278"
-
-/*
- * Changing this #undef to #define may solve start up problems in some systems.
- */
-#undef ALWAYS_SET_DTC2278_PIO_MODE
-
-/*
- * From: andy@cercle.cts.com (Dyan Wile)
- *
- * Below is a patch for DTC-2278 - alike software-programmable controllers
- * The code enables the secondary IDE controller and the PIO4 (3?) timings on
- * the primary (EIDE). You may probably have to enable the 32-bit support to
- * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
- * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
- * filesystem  corrupted with -u1, but under heavy disk load only :-)
- *
- * This card is now forced to use the "serialize" feature,
- * and irq-unmasking is disallowed.  If io_32bit is enabled,
- * it must be done for BOTH drives on each interface.
- *
- * This code was written for the DTC2278E, but might work with any of these:
- *
- * DTC2278S has only a single IDE interface.
- * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
- * DTC2278E also has serial ports and a printer port
- * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
- *
- * There may be a fourth controller type. The S and D versions use the
- * Winbond chip, and I think the E version does also.
- *
- */
-
-static void sub22 (char b, char c)
-{
-       int i;
-
-       for(i = 0; i < 3; ++i) {
-               inb(0x3f6);
-               outb_p(b,0xb0);
-               inb(0x3f6);
-               outb_p(c,0xb4);
-               inb(0x3f6);
-               if(inb(0xb4) == c) {
-                       outb_p(7,0xb0);
-                       inb(0x3f6);
-                       return; /* success */
-               }
-       }
-}
-
-static DEFINE_SPINLOCK(dtc2278_lock);
-
-static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       unsigned long flags;
-
-       if (pio >= 3) {
-               spin_lock_irqsave(&dtc2278_lock, flags);
-               /*
-                * This enables PIO mode4 (3?) on the first interface
-                */
-               sub22(1,0xc3);
-               sub22(0,0xa0);
-               spin_unlock_irqrestore(&dtc2278_lock, flags);
-       } else {
-               /* we don't know how to set it back again.. */
-               /* Actually we do - there is a data sheet available for the
-                  Winbond but does anyone actually care */
-       }
-}
-
-static const struct ide_port_ops dtc2278_port_ops = {
-       .set_pio_mode           = dtc2278_set_pio_mode,
-};
-
-static const struct ide_port_info dtc2278_port_info __initdata = {
-       .name                   = DRV_NAME,
-       .chipset                = ide_dtc2278,
-       .port_ops               = &dtc2278_port_ops,
-       .host_flags             = IDE_HFLAG_SERIALIZE |
-                                 IDE_HFLAG_NO_UNMASK_IRQS |
-                                 IDE_HFLAG_IO_32BIT |
-                                 /* disallow ->io_32bit changes */
-                                 IDE_HFLAG_NO_IO_32BIT |
-                                 IDE_HFLAG_NO_DMA,
-       .pio_mask               = ATA_PIO4,
-};
-
-static int __init dtc2278_probe(void)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       /*
-        * This enables the second interface
-        */
-       outb_p(4,0xb0);
-       inb(0x3f6);
-       outb_p(0x20,0xb4);
-       inb(0x3f6);
-#ifdef ALWAYS_SET_DTC2278_PIO_MODE
-       /*
-        * This enables PIO mode4 (3?) on the first interface
-        * and may solve start-up problems for some people.
-        */
-       sub22(1,0xc3);
-       sub22(0,0xa0);
-#endif
-       local_irq_restore(flags);
-
-       return ide_legacy_device_add(&dtc2278_port_info, 0);
-}
-
-static int probe_dtc2278;
-
-module_param_named(probe, probe_dtc2278, bool, 0);
-MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
-
-static int __init dtc2278_init(void)
-{
-       if (probe_dtc2278 == 0)
-               return -ENODEV;
-
-       if (dtc2278_probe()) {
-               printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
-               return -EBUSY;
-       }
-       return 0;
-}
-
-module_init(dtc2278_init);
-
-MODULE_AUTHOR("See Local File");
-MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
deleted file mode 100644 (file)
index 39d500d..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  Atari Falcon IDE Driver
- *
- *     Created 12 Jul 1997 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_stdma.h>
-
-#define DRV_NAME "falconide"
-
-    /*
-     *  Base of the IDE interface
-     */
-
-#define ATA_HD_BASE    0xfff00000
-
-    /*
-     *  Offsets from the above base
-     */
-
-#define ATA_HD_CONTROL 0x39
-
-    /*
-     *  falconide_intr_lock is used to obtain access to the IDE interrupt,
-     *  which is shared between several drivers.
-     */
-
-int falconide_intr_lock;
-EXPORT_SYMBOL(falconide_intr_lock);
-
-static void falconide_input_data(ide_drive_t *drive, struct request *rq,
-                                void *buf, unsigned int len)
-{
-       unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
-       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
-               return insw(data_addr, buf, (len + 1) / 2);
-
-       insw_swapw(data_addr, buf, (len + 1) / 2);
-}
-
-static void falconide_output_data(ide_drive_t *drive, struct request *rq,
-                                 void *buf, unsigned int len)
-{
-       unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
-       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
-               return outsw(data_addr, buf, (len + 1) / 2);
-
-       outsw_swapw(data_addr, buf, (len + 1) / 2);
-}
-
-/* Atari has a byte-swapped IDE interface */
-static const struct ide_tp_ops falconide_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = ide_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
-
-       .set_irq                = ide_set_irq,
-
-       .tf_load                = ide_tf_load,
-       .tf_read                = ide_tf_read,
-
-       .input_data             = falconide_input_data,
-       .output_data            = falconide_output_data,
-};
-
-static const struct ide_port_info falconide_port_info = {
-       .tp_ops                 = &falconide_tp_ops,
-       .host_flags             = IDE_HFLAG_NO_DMA,
-};
-
-static void __init falconide_setup_ports(hw_regs_t *hw)
-{
-       int i;
-
-       memset(hw, 0, sizeof(*hw));
-
-       hw->io_ports.data_addr = ATA_HD_BASE;
-
-       for (i = 1; i < 8; i++)
-               hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4;
-
-       hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL;
-
-       hw->irq = IRQ_MFP_IDE;
-       hw->ack_intr = NULL;
-
-       hw->chipset = ide_generic;
-}
-
-    /*
-     *  Probe for a Falcon IDE interface
-     */
-
-static int __init falconide_init(void)
-{
-       struct ide_host *host;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-       int rc;
-
-       if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
-               return -ENODEV;
-
-       printk(KERN_INFO "ide: Falcon IDE controller\n");
-
-       if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
-               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
-               return -EBUSY;
-       }
-
-       falconide_setup_ports(&hw);
-
-       host = ide_host_alloc(&falconide_port_info, hws);
-       if (host == NULL) {
-               rc = -ENOMEM;
-               goto err;
-       }
-
-       ide_get_lock(NULL, NULL);
-       rc = ide_host_register(host, &falconide_port_info, hws);
-       ide_release_lock();
-
-       if (rc)
-               goto err_free;
-
-       return 0;
-err_free:
-       ide_host_free(host);
-err:
-       release_mem_region(ATA_HD_BASE, 0x40);
-       return rc;
-}
-
-module_init(falconide_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
deleted file mode 100644 (file)
index 6915068..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- *  Amiga Gayle IDE Driver
- *
- *     Created 9 Jul 1997 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-#include <linux/zorro.h>
-#include <linux/module.h>
-
-#include <asm/setup.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/amigayle.h>
-
-
-    /*
-     *  Bases of the IDE interfaces
-     */
-
-#define GAYLE_BASE_4000        0xdd2020        /* A4000/A4000T */
-#define GAYLE_BASE_1200        0xda0000        /* A1200/A600 and E-Matrix 530 */
-
-#define GAYLE_IDEREG_SIZE      0x2000
-
-    /*
-     *  Offsets from one of the above bases
-     */
-
-#define GAYLE_CONTROL  0x101a
-
-    /*
-     *  These are at different offsets from the base
-     */
-
-#define GAYLE_IRQ_4000 0xdd3020        /* MSB = 1, Harddisk is source of */
-#define GAYLE_IRQ_1200 0xda9000        /* interrupt */
-
-
-    /*
-     *  Offset of the secondary port for IDE doublers
-     *  Note that GAYLE_CONTROL is NOT available then!
-     */
-
-#define GAYLE_NEXT_PORT        0x1000
-
-#ifndef CONFIG_BLK_DEV_IDEDOUBLER
-#define GAYLE_NUM_HWIFS                1
-#define GAYLE_NUM_PROBE_HWIFS  GAYLE_NUM_HWIFS
-#define GAYLE_HAS_CONTROL_REG  1
-#else /* CONFIG_BLK_DEV_IDEDOUBLER */
-#define GAYLE_NUM_HWIFS                2
-#define GAYLE_NUM_PROBE_HWIFS  (ide_doubler ? GAYLE_NUM_HWIFS : \
-                                              GAYLE_NUM_HWIFS-1)
-#define GAYLE_HAS_CONTROL_REG  (!ide_doubler)
-
-static int ide_doubler;
-module_param_named(doubler, ide_doubler, bool, 0);
-MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
-#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
-
-
-    /*
-     *  Check and acknowledge the interrupt status
-     */
-
-static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
-{
-    unsigned char ch;
-
-    ch = z_readb(hwif->io_ports.irq_addr);
-    if (!(ch & GAYLE_IRQ_IDE))
-       return 0;
-    return 1;
-}
-
-static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
-{
-    unsigned char ch;
-
-    ch = z_readb(hwif->io_ports.irq_addr);
-    if (!(ch & GAYLE_IRQ_IDE))
-       return 0;
-    (void)z_readb(hwif->io_ports.status_addr);
-    z_writeb(0x7c, hwif->io_ports.irq_addr);
-    return 1;
-}
-
-static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
-                                    unsigned long ctl, unsigned long irq_port,
-                                    ide_ack_intr_t *ack_intr)
-{
-       int i;
-
-       memset(hw, 0, sizeof(*hw));
-
-       hw->io_ports.data_addr = base;
-
-       for (i = 1; i < 8; i++)
-               hw->io_ports_array[i] = base + 2 + i * 4;
-
-       hw->io_ports.ctl_addr = ctl;
-       hw->io_ports.irq_addr = irq_port;
-
-       hw->irq = IRQ_AMIGA_PORTS;
-       hw->ack_intr = ack_intr;
-
-       hw->chipset = ide_generic;
-}
-
-    /*
-     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
-     */
-
-static int __init gayle_init(void)
-{
-    unsigned long phys_base, res_start, res_n;
-    unsigned long base, ctrlport, irqport;
-    ide_ack_intr_t *ack_intr;
-    int a4000, i, rc;
-    hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
-
-    if (!MACH_IS_AMIGA)
-       return -ENODEV;
-
-    if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
-       goto found;
-
-#ifdef CONFIG_ZORRO
-    if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
-                         NULL))
-       goto found;
-#endif
-    return -ENODEV;
-
-found:
-       printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
-                        a4000 ? 4000 : 1200,
-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
-                        ide_doubler ? ", IDE doubler" :
-#endif
-                        "");
-
-       if (a4000) {
-           phys_base = GAYLE_BASE_4000;
-           irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
-           ack_intr = gayle_ack_intr_a4000;
-       } else {
-           phys_base = GAYLE_BASE_1200;
-           irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
-           ack_intr = gayle_ack_intr_a1200;
-       }
-/*
- * FIXME: we now have selectable modes between mmio v/s iomio
- */
-
-       res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
-       res_n = GAYLE_IDEREG_SIZE;
-
-       if (!request_mem_region(res_start, res_n, "IDE"))
-               return -EBUSY;
-
-    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
-       base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
-       ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
-
-       gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
-
-       hws[i] = &hw[i];
-    }
-
-    rc = ide_host_add(NULL, hws, NULL);
-    if (rc)
-       release_mem_region(res_start, res_n);
-
-    return rc;
-}
-
-module_init(gayle_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
deleted file mode 100644 (file)
index c7e5c22..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
- */
-
-/*
- *  HT-6560B EIDE-controller support
- *  To activate controller support use kernel parameter "ide0=ht6560b".
- *  Use hdparm utility to enable PIO mode support.
- *
- *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
- *             Jan Evert van Grootheest   <j.e.van.grootheest@caiway.nl>
- *
- *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
- */
-
-#define DRV_NAME       "ht6560b"
-#define HT6560B_VERSION "v0.08"
-
-#include <linux/module.h>
-#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/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-/* #define DEBUG */  /* remove comments for DEBUG messages */
-
-/*
- * The special i/o-port that HT-6560B uses to configuration:
- *    bit0 (0x01): "1" selects secondary interface
- *    bit2 (0x04): "1" enables FIFO function
- *    bit5 (0x20): "1" enables prefetched data read function  (???)
- *
- * The special i/o-port that HT-6560A uses to configuration:
- *    bit0 (0x01): "1" selects secondary interface
- *    bit1 (0x02): "1" enables prefetched data read function
- *    bit2 (0x04): "0" enables multi-master system           (?)
- *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time        (?)
- */
-#define HT_CONFIG_PORT   0x3e6
-#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
-/*
- * FIFO + PREFETCH (both a/b-model)
- */
-#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
-/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
-#define HT_SECONDARY_IF          0x01
-#define HT_PREFETCH_MODE  0x20
-
-/*
- * ht6560b Timing values:
- *
- * I reviewed some assembler source listings of htide drivers and found
- * out how they setup those cycle time interfacing values, as they at Holtek
- * call them. IDESETUP.COM that is supplied with the drivers figures out
- * optimal values and fetches those values to drivers. I found out that
- * they use Select register to fetch timings to the ide board right after
- * interface switching. After that it was quite easy to add code to
- * ht6560b.c.
- *
- * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
- * for hda and hdc. But hdb needed higher values to work, so I guess
- * that sometimes it is necessary to give higher value than IDESETUP
- * gives.   [see cmd640.c for an extreme example of this. -ml]
- *
- * Perhaps I should explain something about these timing values:
- * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
- * of the value is the Active Time  (at). Minimum value 2 is the fastest and
- * the maximum value 15 is the slowest. Default values should be 15 for both.
- * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
- * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
- * similar. If value is too small there will be all sorts of failures.
- *
- * Timing byte consists of
- *     High nibble:  Recovery Cycle Time  (rt)
- *          The valid values range from 2 to 15. The default is 15.
- *
- *     Low nibble:   Active Cycle Time    (at)
- *          The valid values range from 2 to 15. The default is 15.
- *
- * You can obtain optimized timing values by running Holtek IDESETUP.COM
- * for DOS. DOS drivers get their timing values from command line, where
- * the first value is the Recovery Time and the second value is the
- * Active Time for each drive. Smaller value gives higher speed.
- * In case of failures you should probably fall back to a higher value.
- */
-#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
-#define HT_TIMING_DEFAULT 0xff
-
-/*
- * This routine handles interface switching for the peculiar hardware design
- * on the F.G.I./Holtek HT-6560B VLB IDE interface.
- * The HT-6560B can only enable one IDE port at a time, and requires a
- * silly sequence (below) whenever we switch between primary and secondary.
- */
-
-/*
- * This routine is invoked from ide.c to prepare for access to a given drive.
- */
-static void ht6560b_selectproc (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       unsigned long flags;
-       static u8 current_select = 0;
-       static u8 current_timing = 0;
-       u8 select, timing;
-       
-       local_irq_save(flags);
-
-       select = HT_CONFIG(drive);
-       timing = HT_TIMING(drive);
-
-       /*
-        * Need to enforce prefetch sometimes because otherwise
-        * it'll hang (hard).
-        */
-       if (drive->media != ide_disk ||
-           (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-               select |= HT_PREFETCH_MODE;
-
-       if (select != current_select || timing != current_timing) {
-               current_select = select;
-               current_timing = timing;
-               (void)inb(HT_CONFIG_PORT);
-               (void)inb(HT_CONFIG_PORT);
-               (void)inb(HT_CONFIG_PORT);
-               (void)inb(HT_CONFIG_PORT);
-               outb(select, HT_CONFIG_PORT);
-               /*
-                * Set timing for this drive:
-                */
-               outb(timing, hwif->io_ports.device_addr);
-               (void)inb(hwif->io_ports.status_addr);
-#ifdef DEBUG
-               printk("ht6560b: %s: select=%#x timing=%#x\n",
-                       drive->name, select, timing);
-#endif
-       }
-       local_irq_restore(flags);
-}
-
-/*
- * Autodetection and initialization of ht6560b
- */
-static int __init try_to_init_ht6560b(void)
-{
-       u8 orig_value;
-       int i;
-       
-       /* Autodetect ht6560b */
-       if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
-               return 0;
-       
-       for (i=3;i>0;i--) {
-               outb(0x00, HT_CONFIG_PORT);
-               if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
-                       outb(orig_value, HT_CONFIG_PORT);
-                       return 0;
-               }
-       }
-       outb(0x00, HT_CONFIG_PORT);
-       if ((~inb(HT_CONFIG_PORT))& 0x3f) {
-               outb(orig_value, HT_CONFIG_PORT);
-               return 0;
-       }
-       /*
-        * Ht6560b autodetected
-        */
-       outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
-       outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */
-       (void)inb(0x1f7);               /* Status register */
-
-       printk("ht6560b " HT6560B_VERSION
-              ": chipset detected and initialized"
-#ifdef DEBUG
-              " with debug enabled"
-#endif
-              "\n"
-               );
-       return 1;
-}
-
-static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
-{
-       int active_time, recovery_time;
-       int active_cycles, recovery_cycles;
-       int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
-
-        if (pio) {
-               unsigned int cycle_time;
-               struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-
-               cycle_time = ide_pio_cycle_time(drive, pio);
-
-               /*
-                *  Just like opti621.c we try to calculate the
-                *  actual cycle time for recovery and activity
-                *  according system bus speed.
-                */
-               active_time = t->active;
-               recovery_time = cycle_time - active_time - t->setup;
-               /*
-                *  Cycle times should be Vesa bus cycles
-                */
-               active_cycles   = (active_time   * bus_speed + 999) / 1000;
-               recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
-               /*
-                *  Upper and lower limits
-                */
-               if (active_cycles   < 2)  active_cycles   = 2;
-               if (recovery_cycles < 2)  recovery_cycles = 2;
-               if (active_cycles   > 15) active_cycles   = 15;
-               if (recovery_cycles > 15) recovery_cycles = 0;  /* 0==16 */
-               
-#ifdef DEBUG
-               printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
-#endif
-               
-               return (u8)((recovery_cycles << 4) | active_cycles);
-       } else {
-               
-#ifdef DEBUG
-               printk("ht6560b: drive %s setting pio=0\n", drive->name);
-#endif
-               
-               return HT_TIMING_DEFAULT;    /* default setting */
-       }
-}
-
-static DEFINE_SPINLOCK(ht6560b_lock);
-
-/*
- *  Enable/Disable so called prefetch mode
- */
-static void ht_set_prefetch(ide_drive_t *drive, u8 state)
-{
-       unsigned long flags;
-       int t = HT_PREFETCH_MODE << 8;
-
-       spin_lock_irqsave(&ht6560b_lock, flags);
-
-       /*
-        *  Prefetch mode and unmask irq seems to conflict
-        */
-       if (state) {
-               drive->drive_data |= t;   /* enable prefetch mode */
-               drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
-               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
-       } else {
-               drive->drive_data &= ~t;  /* disable prefetch mode */
-               drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
-       }
-
-       spin_unlock_irqrestore(&ht6560b_lock, flags);
-
-#ifdef DEBUG
-       printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
-#endif
-}
-
-static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       unsigned long flags;
-       u8 timing;
-       
-       switch (pio) {
-       case 8:         /* set prefetch off */
-       case 9:         /* set prefetch on */
-               ht_set_prefetch(drive, pio & 1);
-               return;
-       }
-
-       timing = ht_pio2timings(drive, pio);
-
-       spin_lock_irqsave(&ht6560b_lock, flags);
-       drive->drive_data &= 0xff00;
-       drive->drive_data |= timing;
-       spin_unlock_irqrestore(&ht6560b_lock, flags);
-
-#ifdef DEBUG
-       printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
-#endif
-}
-
-static void __init ht6560b_init_dev(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       /* Setting default configurations for drives. */
-       int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
-
-       if (hwif->channel)
-               t |= (HT_SECONDARY_IF << 8);
-
-       drive->drive_data = t;
-}
-
-static int probe_ht6560b;
-
-module_param_named(probe, probe_ht6560b, bool, 0);
-MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
-
-static const struct ide_port_ops ht6560b_port_ops = {
-       .init_dev               = ht6560b_init_dev,
-       .set_pio_mode           = ht6560b_set_pio_mode,
-       .selectproc             = ht6560b_selectproc,
-};
-
-static const struct ide_port_info ht6560b_port_info __initdata = {
-       .name                   = DRV_NAME,
-       .chipset                = ide_ht6560b,
-       .port_ops               = &ht6560b_port_ops,
-       .host_flags             = IDE_HFLAG_SERIALIZE | /* is this needed? */
-                                 IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAG_ABUSE_PREFETCH,
-       .pio_mask               = ATA_PIO4,
-};
-
-static int __init ht6560b_init(void)
-{
-       if (probe_ht6560b == 0)
-               return -ENODEV;
-
-       if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
-               printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
-                       __func__);
-               return -ENODEV;
-       }
-
-       if (!try_to_init_ht6560b()) {
-               printk(KERN_NOTICE "%s: HBA not found\n", __func__);
-               goto release_region;
-       }
-
-       return ide_legacy_device_add(&ht6560b_port_info, 0);
-
-release_region:
-       release_region(HT_CONFIG_PORT, 1);
-       return -ENODEV;
-}
-
-module_init(ht6560b_init);
-
-MODULE_AUTHOR("See Local File");
-MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
deleted file mode 100644 (file)
index 9e85b1e..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/ide.h>
-
-#define DRV_NAME "ide-4drives"
-
-static int probe_4drives;
-
-module_param_named(probe, probe_4drives, bool, 0);
-MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
-
-static void ide_4drives_init_dev(ide_drive_t *drive)
-{
-       if (drive->hwif->channel)
-               drive->select ^= 0x20;
-}
-
-static const struct ide_port_ops ide_4drives_port_ops = {
-       .init_dev               = ide_4drives_init_dev,
-};
-
-static const struct ide_port_info ide_4drives_port_info = {
-       .port_ops               = &ide_4drives_port_ops,
-       .host_flags             = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
-};
-
-static int __init ide_4drives_init(void)
-{
-       unsigned long base = 0x1f0, ctl = 0x3f6;
-       hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
-
-       if (probe_4drives == 0)
-               return -ENODEV;
-
-       if (!request_region(base, 8, DRV_NAME)) {
-               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
-                               DRV_NAME, base, base + 7);
-               return -EBUSY;
-       }
-
-       if (!request_region(ctl, 1, DRV_NAME)) {
-               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
-                               DRV_NAME, ctl);
-               release_region(base, 8);
-               return -EBUSY;
-       }
-
-       memset(&hw, 0, sizeof(hw));
-
-       ide_std_init_ports(&hw, base, ctl);
-       hw.irq = 14;
-       hw.chipset = ide_4drives;
-
-       return ide_host_add(&ide_4drives_port_info, hws, NULL);
-}
-
-module_init(ide_4drives_init);
-
-MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
-MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
deleted file mode 100644 (file)
index cb199c8..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/*======================================================================
-
-    A driver for PCMCIA IDE/ATA disk cards
-
-    The contents of this file are subject to the Mozilla Public
-    License Version 1.1 (the "License"); you may not use this file
-    except in compliance with the License. You may obtain a copy of
-    the License at http://www.mozilla.org/MPL/
-
-    Software distributed under the License is distributed on an "AS
-    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-    implied. See the License for the specific language governing
-    rights and limitations under the License.
-
-    The initial developer of the original code is David A. Hinds
-    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
-    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
-
-    Alternatively, the contents of this file may be used under the
-    terms of the GNU General Public License version 2 (the "GPL"), in
-    which case the provisions of the GPL are applicable instead of the
-    above.  If you wish to allow the use of your version of this file
-    only under the terms of the GPL and not to allow others to use
-    your version of this file under the MPL, indicate your decision
-    by deleting the provisions above and replace them with the notice
-    and other provisions required by the GPL.  If you do not delete
-    the provisions above, a recipient may use your version of this
-    file under either the MPL or the GPL.
-
-======================================================================*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/ide.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-#include <pcmcia/ciscode.h>
-
-#define DRV_NAME "ide-cs"
-
-/*====================================================================*/
-
-/* Module parameters */
-
-MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
-MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
-MODULE_LICENSE("Dual MPL/GPL");
-
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
-
-#ifdef CONFIG_PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, 0);
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
-
-/*====================================================================*/
-
-typedef struct ide_info_t {
-       struct pcmcia_device    *p_dev;
-       struct ide_host         *host;
-    int                ndev;
-    dev_node_t node;
-} ide_info_t;
-
-static void ide_release(struct pcmcia_device *);
-static int ide_config(struct pcmcia_device *);
-
-static void ide_detach(struct pcmcia_device *p_dev);
-
-
-
-
-/*======================================================================
-
-    ide_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
-static int ide_probe(struct pcmcia_device *link)
-{
-    ide_info_t *info;
-
-    DEBUG(0, "ide_attach()\n");
-
-    /* Create new ide device */
-    info = kzalloc(sizeof(*info), GFP_KERNEL);
-    if (!info)
-       return -ENOMEM;
-
-    info->p_dev = link;
-    link->priv = info;
-
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-    link->io.IOAddrLines = 3;
-    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
-    return ide_config(link);
-} /* ide_attach */
-
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
-static void ide_detach(struct pcmcia_device *link)
-{
-    ide_info_t *info = link->priv;
-    ide_hwif_t *hwif = info->host->ports[0];
-    unsigned long data_addr, ctl_addr;
-
-    DEBUG(0, "ide_detach(0x%p)\n", link);
-
-    data_addr = hwif->io_ports.data_addr;
-    ctl_addr  = hwif->io_ports.ctl_addr;
-
-    ide_release(link);
-
-    release_region(ctl_addr, 1);
-    release_region(data_addr, 8);
-
-    kfree(info);
-} /* ide_detach */
-
-static const struct ide_port_ops idecs_port_ops = {
-       .quirkproc              = ide_undecoded_slave,
-};
-
-static const struct ide_port_info idecs_port_info = {
-       .port_ops               = &idecs_port_ops,
-       .host_flags             = IDE_HFLAG_NO_DMA,
-};
-
-static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
-                               unsigned long irq, struct pcmcia_device *handle)
-{
-    struct ide_host *host;
-    ide_hwif_t *hwif;
-    int i, rc;
-    hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-    if (!request_region(io, 8, DRV_NAME)) {
-       printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
-                       DRV_NAME, io, io + 7);
-       return NULL;
-    }
-
-    if (!request_region(ctl, 1, DRV_NAME)) {
-       printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
-                       DRV_NAME, ctl);
-       release_region(io, 8);
-       return NULL;
-    }
-
-    memset(&hw, 0, sizeof(hw));
-    ide_std_init_ports(&hw, io, ctl);
-    hw.irq = irq;
-    hw.chipset = ide_pci;
-    hw.dev = &handle->dev;
-
-    rc = ide_host_add(&idecs_port_info, hws, &host);
-    if (rc)
-       goto out_release;
-
-    hwif = host->ports[0];
-
-    if (hwif->present)
-       return host;
-
-    /* retry registration in case device is still spinning up */
-    for (i = 0; i < 10; i++) {
-       msleep(100);
-       ide_port_scan(hwif);
-       if (hwif->present)
-           return host;
-    }
-
-    return host;
-
-out_release:
-    release_region(ctl, 1);
-    release_region(io, 8);
-    return NULL;
-}
-
-/*======================================================================
-
-    ide_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ide device available to the system.
-
-======================================================================*/
-
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-
-struct pcmcia_config_check {
-       unsigned long ctl_base;
-       int skip_vcc;
-       int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-                                  cistpl_cftable_entry_t *cfg,
-                                  cistpl_cftable_entry_t *dflt,
-                                  unsigned int vcc,
-                                  void *priv_data)
-{
-       struct pcmcia_config_check *stk = priv_data;
-
-       /* Check for matching Vcc, unless we're desperate */
-       if (!stk->skip_vcc) {
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                               return -ENODEV;
-               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                               return -ENODEV;
-               }
-       }
-
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-               pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-               pdev->conf.ConfigIndex = cfg->index;
-               pdev->io.BasePort1 = io->win[0].base;
-               pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-               if (!(io->flags & CISTPL_IO_16BIT))
-                       pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-               if (io->nwin == 2) {
-                       pdev->io.NumPorts1 = 8;
-                       pdev->io.BasePort2 = io->win[1].base;
-                       pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
-                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
-                               return -ENODEV;
-                       stk->ctl_base = pdev->io.BasePort2;
-               } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-                       pdev->io.NumPorts1 = io->win[0].len;
-                       pdev->io.NumPorts2 = 0;
-                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
-                               return -ENODEV;
-                       stk->ctl_base = pdev->io.BasePort1 + 0x0e;
-               } else
-                       return -ENODEV;
-               /* If we've got this far, we're done */
-               return 0;
-       }
-       return -ENODEV;
-}
-
-static int ide_config(struct pcmcia_device *link)
-{
-    ide_info_t *info = link->priv;
-    struct pcmcia_config_check *stk = NULL;
-    int last_ret = 0, last_fn = 0, is_kme = 0;
-    unsigned long io_base, ctl_base;
-    struct ide_host *host;
-
-    DEBUG(0, "ide_config(0x%p)\n", link);
-
-    is_kme = ((link->manf_id == MANFID_KME) &&
-             ((link->card_id == PRODID_KME_KXLC005_A) ||
-              (link->card_id == PRODID_KME_KXLC005_B)));
-
-    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-    if (!stk)
-           goto err_mem;
-    stk->is_kme = is_kme;
-    stk->skip_vcc = io_base = ctl_base = 0;
-
-    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
-           stk->skip_vcc = 1;
-           if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
-                   goto failed; /* No suitable config found */
-    }
-    io_base = link->io.BasePort1;
-    ctl_base = stk->ctl_base;
-
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
-
-    /* disable drive interrupts during IDE probe */
-    outb(0x02, ctl_base);
-
-    /* special setup for KXLC005 card */
-    if (is_kme)
-       outb(0x81, ctl_base+1);
-
-     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
-     if (host == NULL && link->io.NumPorts1 == 0x20) {
-           outb(0x02, ctl_base + 0x10);
-           host = idecs_register(io_base + 0x10, ctl_base + 0x10,
-                                 link->irq.AssignedIRQ, link);
-    }
-
-    if (host == NULL)
-       goto failed;
-
-    info->ndev = 1;
-    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
-    info->node.major = host->ports[0]->major;
-    info->node.minor = 0;
-    info->host = host;
-    link->dev_node = &info->node;
-    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
-          info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
-
-    kfree(stk);
-    return 0;
-
-err_mem:
-    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
-    goto failed;
-
-cs_failed:
-    cs_error(link, last_fn, last_ret);
-failed:
-    kfree(stk);
-    ide_release(link);
-    return -ENODEV;
-} /* ide_config */
-
-/*======================================================================
-
-    After a card is removed, ide_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
-static void ide_release(struct pcmcia_device *link)
-{
-    ide_info_t *info = link->priv;
-    struct ide_host *host = info->host;
-
-    DEBUG(0, "ide_release(0x%p)\n", link);
-
-    if (info->ndev)
-       /* FIXME: if this fails we need to queue the cleanup somehow
-          -- need to investigate the required PCMCIA magic */
-       ide_host_remove(host);
-
-    info->ndev = 0;
-
-    pcmcia_disable_device(link);
-} /* ide_release */
-
-
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the ide drivers from
-    talking to the ports.
-
-======================================================================*/
-
-static struct pcmcia_device_id ide_ids[] = {
-       PCMCIA_DEVICE_FUNC_ID(4),
-       PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),        /* Corsair */
-       PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),        /* Hitachi */
-       PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
-       PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
-       PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
-       PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
-       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
-       PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
-       PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
-       PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
-       PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
-       PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
-       PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),        /* Hitachi */
-       PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
-       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100),        /* Viking CFA */
-       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar, Viking CFA */
-       PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
-       PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
-       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
-       PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
-       PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
-       PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
-       PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
-       PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
-       PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
-       PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
-       PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
-       PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
-       PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
-       PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
-       PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
-       PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
-       PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
-       PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
-       PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
-       PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
-       PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
-       PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
-       PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
-       PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
-       PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
-       PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
-       PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
-       PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
-       PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
-       PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
-       PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
-       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
-       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
-       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
-       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
-       PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
-       PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
-       PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
-       PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
-       PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
-       PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, ide_ids);
-
-static struct pcmcia_driver ide_cs_driver = {
-       .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "ide-cs",
-       },
-       .probe          = ide_probe,
-       .remove         = ide_detach,
-       .id_table       = ide_ids,
-};
-
-static int __init init_ide_cs(void)
-{
-       return pcmcia_register_driver(&ide_cs_driver);
-}
-
-static void __exit exit_ide_cs(void)
-{
-       pcmcia_unregister_driver(&ide_cs_driver);
-}
-
-late_initcall(init_ide_cs);
-module_exit(exit_ide_cs);
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
deleted file mode 100644 (file)
index 051b4ab..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Platform IDE driver
- *
- * Copyright (C) 2007 MontaVista Software
- *
- * Maintainer: Kumar Gala <galak@kernel.crashing.org>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/ata_platform.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
-                                          void __iomem *base,
-                                          void __iomem *ctrl,
-                                          struct pata_platform_info *pdata,
-                                          int irq)
-{
-       unsigned long port = (unsigned long)base;
-       int i;
-
-       hw->io_ports.data_addr = port;
-
-       port += (1 << pdata->ioport_shift);
-       for (i = 1; i <= 7;
-            i++, port += (1 << pdata->ioport_shift))
-               hw->io_ports_array[i] = port;
-
-       hw->io_ports.ctl_addr = (unsigned long)ctrl;
-
-       hw->irq = irq;
-
-       hw->chipset = ide_generic;
-}
-
-static const struct ide_port_info platform_ide_port_info = {
-       .host_flags             = IDE_HFLAG_NO_DMA,
-};
-
-static int __devinit plat_ide_probe(struct platform_device *pdev)
-{
-       struct resource *res_base, *res_alt, *res_irq;
-       void __iomem *base, *alt_base;
-       struct pata_platform_info *pdata;
-       struct ide_host *host;
-       int ret = 0, mmio = 0;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-       struct ide_port_info d = platform_ide_port_info;
-
-       pdata = pdev->dev.platform_data;
-
-       /* get a pointer to the register memory */
-       res_base = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       res_alt = platform_get_resource(pdev, IORESOURCE_IO, 1);
-
-       if (!res_base || !res_alt) {
-               res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               if (!res_base || !res_alt) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               mmio = 1;
-       }
-
-       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res_irq) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (mmio) {
-               base = devm_ioremap(&pdev->dev,
-                       res_base->start, res_base->end - res_base->start + 1);
-               alt_base = devm_ioremap(&pdev->dev,
-                       res_alt->start, res_alt->end - res_alt->start + 1);
-       } else {
-               base = devm_ioport_map(&pdev->dev,
-                       res_base->start, res_base->end - res_base->start + 1);
-               alt_base = devm_ioport_map(&pdev->dev,
-                       res_alt->start, res_alt->end - res_alt->start + 1);
-       }
-
-       memset(&hw, 0, sizeof(hw));
-       plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
-       hw.dev = &pdev->dev;
-
-       if (mmio)
-               d.host_flags |= IDE_HFLAG_MMIO;
-
-       ret = ide_host_add(&d, hws, &host);
-       if (ret)
-               goto out;
-
-       platform_set_drvdata(pdev, host);
-
-       return 0;
-
-out:
-       return ret;
-}
-
-static int __devexit plat_ide_remove(struct platform_device *pdev)
-{
-       struct ide_host *host = pdev->dev.driver_data;
-
-       ide_host_remove(host);
-
-       return 0;
-}
-
-static struct platform_driver platform_ide_driver = {
-       .driver = {
-               .name = "pata_platform",
-               .owner = THIS_MODULE,
-       },
-       .probe = plat_ide_probe,
-       .remove = __devexit_p(plat_ide_remove),
-};
-
-static int __init platform_ide_init(void)
-{
-       return platform_driver_register(&platform_ide_driver);
-}
-
-static void __exit platform_ide_exit(void)
-{
-       platform_driver_unregister(&platform_ide_driver);
-}
-
-MODULE_DESCRIPTION("Platform IDE driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pata_platform");
-
-module_init(platform_ide_init);
-module_exit(platform_ide_exit);
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
deleted file mode 100644 (file)
index 43f97cc..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  Macintosh IDE Driver
- *
- *     Copyright (C) 1998 by Michael Schmitz
- *
- *  This driver was written based on information obtained from the MacOS IDE
- *  driver binary by Mikael Forselius
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-
-#include <asm/machw.h>
-#include <asm/macintosh.h>
-#include <asm/macints.h>
-#include <asm/mac_baboon.h>
-
-#define IDE_BASE 0x50F1A000    /* Base address of IDE controller */
-
-/*
- * Generic IDE registers as offsets from the base
- * These match MkLinux so they should be correct.
- */
-
-#define IDE_CONTROL    0x38    /* control/altstatus */
-
-/*
- * Mac-specific registers
- */
-
-/*
- * this register is odd; it doesn't seem to do much and it's
- * not word-aligned like virtually every other hardware register
- * on the Mac...
- */
-
-#define IDE_IFR                0x101   /* (0x101) IDE interrupt flags on Quadra:
-                                *
-                                * Bit 0+1: some interrupt flags
-                                * Bit 2+3: some interrupt enable
-                                * Bit 4:   ??
-                                * Bit 5:   IDE interrupt flag (any hwif)
-                                * Bit 6:   maybe IDE interrupt enable (any hwif) ??
-                                * Bit 7:   Any interrupt condition
-                                */
-
-volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR);
-
-int macide_ack_intr(ide_hwif_t* hwif)
-{
-       if (*ide_ifr & 0x20) {
-               *ide_ifr &= ~0x20;
-               return 1;
-       }
-       return 0;
-}
-
-static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
-                                     int irq, ide_ack_intr_t *ack_intr)
-{
-       int i;
-
-       memset(hw, 0, sizeof(*hw));
-
-       for (i = 0; i < 8; i++)
-               hw->io_ports_array[i] = base + i * 4;
-
-       hw->io_ports.ctl_addr = base + IDE_CONTROL;
-
-       hw->irq = irq;
-       hw->ack_intr = ack_intr;
-
-       hw->chipset = ide_generic;
-}
-
-static const char *mac_ide_name[] =
-       { "Quadra", "Powerbook", "Powerbook Baboon" };
-
-/*
- * Probe for a Macintosh IDE interface
- */
-
-static int __init macide_init(void)
-{
-       ide_ack_intr_t *ack_intr;
-       unsigned long base;
-       int irq;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-       if (!MACH_IS_MAC)
-               return -ENODEV;
-
-       switch (macintosh_config->ide_type) {
-       case MAC_IDE_QUADRA:
-               base = IDE_BASE;
-               ack_intr = macide_ack_intr;
-               irq = IRQ_NUBUS_F;
-               break;
-       case MAC_IDE_PB:
-               base = IDE_BASE;
-               ack_intr = macide_ack_intr;
-               irq = IRQ_NUBUS_C;
-               break;
-       case MAC_IDE_BABOON:
-               base = BABOON_BASE;
-               ack_intr = NULL;
-               irq = IRQ_BABOON_1;
-               break;
-       default:
-               return -ENODEV;
-       }
-
-       printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
-                        mac_ide_name[macintosh_config->ide_type - 1]);
-
-       macide_setup_ports(&hw, base, irq, ack_intr);
-
-       return ide_host_add(NULL, hws, NULL);
-}
-
-module_init(macide_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
deleted file mode 100644 (file)
index 4af4a8c..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *  Q40 I/O port IDE Driver
- *
- *     (c) Richard Zidlicky
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- *
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/ide.h>
-
-    /*
-     *  Bases of the IDE interfaces
-     */
-
-#define Q40IDE_NUM_HWIFS       2
-
-#define PCIDE_BASE1    0x1f0
-#define PCIDE_BASE2    0x170
-#define PCIDE_BASE3    0x1e8
-#define PCIDE_BASE4    0x168
-#define PCIDE_BASE5    0x1e0
-#define PCIDE_BASE6    0x160
-
-static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
-    PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
-    PCIDE_BASE6 */
-};
-
-static int q40ide_default_irq(unsigned long base)
-{
-           switch (base) {
-                   case 0x1f0: return 14;
-                   case 0x170: return 15;
-                   case 0x1e8: return 11;
-                   default:
-                       return 0;
-          }
-}
-
-
-/*
- * Addresses are pretranslated for Q40 ISA access.
- */
-static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base,
-                       ide_ack_intr_t *ack_intr,
-                       int irq)
-{
-       memset(hw, 0, sizeof(hw_regs_t));
-       /* BIG FAT WARNING: 
-          assumption: only DATA port is ever used in 16 bit mode */
-       hw->io_ports.data_addr = Q40_ISA_IO_W(base);
-       hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1);
-       hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2);
-       hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3);
-       hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4);
-       hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5);
-       hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6);
-       hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7);
-       hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
-
-       hw->irq = irq;
-       hw->ack_intr = ack_intr;
-
-       hw->chipset = ide_generic;
-}
-
-static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
-                             void *buf, unsigned int len)
-{
-       unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
-       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
-               return insw(data_addr, buf, (len + 1) / 2);
-
-       insw_swapw(data_addr, buf, (len + 1) / 2);
-}
-
-static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
-                              void *buf, unsigned int len)
-{
-       unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
-       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
-               return outsw(data_addr, buf, (len + 1) / 2);
-
-       outsw_swapw(data_addr, buf, (len + 1) / 2);
-}
-
-/* Q40 has a byte-swapped IDE interface */
-static const struct ide_tp_ops q40ide_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = ide_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
-
-       .set_irq                = ide_set_irq,
-
-       .tf_load                = ide_tf_load,
-       .tf_read                = ide_tf_read,
-
-       .input_data             = q40ide_input_data,
-       .output_data            = q40ide_output_data,
-};
-
-static const struct ide_port_info q40ide_port_info = {
-       .tp_ops                 = &q40ide_tp_ops,
-       .host_flags             = IDE_HFLAG_NO_DMA,
-};
-
-/* 
- * the static array is needed to have the name reported in /proc/ioports,
- * hwif->name unfortunately isn't available yet
- */
-static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
-       "ide0", "ide1"
-};
-
-/*
- *  Probe for Q40 IDE interfaces
- */
-
-static int __init q40ide_init(void)
-{
-    int i;
-    hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
-
-    if (!MACH_IS_Q40)
-      return -ENODEV;
-
-    printk(KERN_INFO "ide: Q40 IDE controller\n");
-
-    for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
-       const char *name = q40_ide_names[i];
-
-       if (!request_region(pcide_bases[i], 8, name)) {
-               printk("could not reserve ports %lx-%lx for %s\n",
-                      pcide_bases[i],pcide_bases[i]+8,name);
-               continue;
-       }
-       if (!request_region(pcide_bases[i]+0x206, 1, name)) {
-               printk("could not reserve port %lx for %s\n",
-                      pcide_bases[i]+0x206,name);
-               release_region(pcide_bases[i], 8);
-               continue;
-       }
-       q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
-                       q40ide_default_irq(pcide_bases[i]));
-
-       hws[i] = &hw[i];
-    }
-
-    return ide_host_add(&q40ide_port_info, hws, NULL);
-}
-
-module_init(q40ide_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
deleted file mode 100644 (file)
index bc27c7a..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
- */
-
-/*
- *  Version 0.03       Cleaned auto-tune, added probe
- *  Version 0.04       Added second channel tuning
- *  Version 0.05       Enhanced tuning ; added qd6500 support
- *  Version 0.06       Added dos driver's list
- *  Version 0.07       Second channel bug fix 
- *
- * QDI QD6500/QD6580 EIDE controller fast support
- *
- * To activate controller support, use "ide0=qd65xx"
- */
-
-/*
- * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@fnac.net>
- */
-
-#include <linux/module.h>
-#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/ide.h>
-#include <linux/init.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#define DRV_NAME "qd65xx"
-
-#include "qd65xx.h"
-
-/*
- * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580)
- *            or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580)
- *     -- qd6500 is a single IDE interface
- *     -- qd6580 is a dual IDE interface
- *
- * More research on qd6580 being done by willmore@cig.mot.com (David)
- * More Information given by Petr Soucek (petr@ryston.cz)
- * http://www.ryston.cz/petr/vlb
- */
-
-/*
- * base: Timer1
- *
- *
- * base+0x01: Config (R/O)
- *
- * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500)
- * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30
- * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz
- * bit 3: qd6500: 1 = disabled, 0 = enabled
- *        qd6580: 1
- * upper nibble:
- *        qd6500: 1100
- *        qd6580: either 1010 or 0101
- *
- *
- * base+0x02: Timer2 (qd6580 only)
- *
- *
- * base+0x03: Control (qd6580 only)
- *
- * bits 0-3 must always be set 1
- * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock
- * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb
- *         0 = Primary and Secondary ports enabled : channel 0 for hda & hdb
- *                                                   channel 1 for hdc & hdd
- * bit 1 : 1 = only disks on primary port
- *         0 = disks & ATAPI devices on primary port
- * bit 2-4 : always 0
- * bit 5 : status, but of what ?
- * bit 6 : always set 1 by dos driver
- * bit 7 : set 1 for non-ATAPI devices on primary port
- *     (maybe read-ahead and post-write buffer ?)
- */
-
-static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
-
-/*
- * qd65xx_select:
- *
- * This routine is invoked to prepare for access to a given drive.
- */
-
-static void qd65xx_select(ide_drive_t *drive)
-{
-       u8 index = ((   (QD_TIMREG(drive)) & 0x80 ) >> 7) |
-                       (QD_TIMREG(drive) & 0x02);
-
-       if (timings[index] != QD_TIMING(drive))
-               outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
-}
-
-/*
- * qd6500_compute_timing
- *
- * computes the timing value where
- *     lower nibble represents active time,   in count of VLB clocks
- *     upper nibble represents recovery time, in count of VLB clocks
- */
-
-static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
-{
-       int clk = ide_vlb_clk ? ide_vlb_clk : 50;
-       u8 act_cyc, rec_cyc;
-
-       if (clk <= 33) {
-               act_cyc =  9 - IDE_IN(active_time   * clk / 1000 + 1, 2,  9);
-               rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15);
-       } else {
-               act_cyc =  8 - IDE_IN(active_time   * clk / 1000 + 1, 1,  8);
-               rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18);
-       }
-
-       return (rec_cyc << 4) | 0x08 | act_cyc;
-}
-
-/*
- * qd6580_compute_timing
- *
- * idem for qd6580
- */
-
-static u8 qd6580_compute_timing (int active_time, int recovery_time)
-{
-       int clk = ide_vlb_clk ? ide_vlb_clk : 50;
-       u8 act_cyc, rec_cyc;
-
-       act_cyc = 17 - IDE_IN(active_time   * clk / 1000 + 1, 2, 17);
-       rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15);
-
-       return (rec_cyc << 4) | act_cyc;
-}
-
-/*
- * qd_find_disk_type
- *
- * tries to find timing from dos driver's table
- */
-
-static int qd_find_disk_type (ide_drive_t *drive,
-               int *active_time, int *recovery_time)
-{
-       struct qd65xx_timing_s *p;
-       char *m = (char *)&drive->id[ATA_ID_PROD];
-       char model[ATA_ID_PROD_LEN];
-
-       if (*m == 0)
-               return 0;
-
-       strncpy(model, m, ATA_ID_PROD_LEN);
-       ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */
-
-       for (p = qd65xx_timing ; p->offset != -1 ; p++) {
-               if (!strncmp(p->model, model+p->offset, 4)) {
-                       printk(KERN_DEBUG "%s: listed !\n", drive->name);
-                       *active_time = p->active;
-                       *recovery_time = p->recovery;
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * qd_set_timing:
- *
- * records the timing
- */
-
-static void qd_set_timing (ide_drive_t *drive, u8 timing)
-{
-       drive->drive_data &= 0xff00;
-       drive->drive_data |= timing;
-
-       printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
-}
-
-static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       u16 *id = drive->id;
-       int active_time   = 175;
-       int recovery_time = 415; /* worst case values from the dos driver */
-
-       /*
-        * FIXME: use "pio" value
-        */
-       if (!qd_find_disk_type(drive, &active_time, &recovery_time) &&
-           (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) &&
-           id[ATA_ID_EIDE_PIO] >= 240) {
-               printk(KERN_INFO "%s: PIO mode%d\n", drive->name,
-                       id[ATA_ID_OLD_PIO_MODES] & 0xff);
-               active_time = 110;
-               recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120;
-       }
-
-       qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
-}
-
-static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-       unsigned int cycle_time;
-       int active_time   = 175;
-       int recovery_time = 415; /* worst case values from the dos driver */
-       u8 base = (hwif->config_data & 0xff00) >> 8;
-
-       if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
-               cycle_time = ide_pio_cycle_time(drive, pio);
-
-               switch (pio) {
-                       case 0: break;
-                       case 3:
-                               if (cycle_time >= 110) {
-                                       active_time = 86;
-                                       recovery_time = cycle_time - 102;
-                               } else
-                                       printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
-                               break;
-                       case 4:
-                               if (cycle_time >= 69) {
-                                       active_time = 70;
-                                       recovery_time = cycle_time - 61;
-                               } else
-                                       printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
-                               break;
-                       default:
-                               if (cycle_time >= 180) {
-                                       active_time = 110;
-                                       recovery_time = cycle_time - 120;
-                               } else {
-                                       active_time = t->active;
-                                       recovery_time = cycle_time - active_time;
-                               }
-               }
-               printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio);
-       }
-
-       if (!HWIF(drive)->channel && drive->media != ide_disk) {
-               outb(0x5f, QD_CONTROL_PORT);
-               printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
-                       "and post-write buffer on %s.\n",
-                       drive->name, HWIF(drive)->name);
-       }
-
-       qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
-}
-
-/*
- * qd_testreg
- *
- * tests if the given port is a register
- */
-
-static int __init qd_testreg(int port)
-{
-       unsigned long flags;
-       u8 savereg, readreg;
-
-       local_irq_save(flags);
-       savereg = inb_p(port);
-       outb_p(QD_TESTVAL, port);       /* safe value */
-       readreg = inb_p(port);
-       outb(savereg, port);
-       local_irq_restore(flags);
-
-       if (savereg == QD_TESTVAL) {
-               printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n");
-               printk(KERN_ERR "Please contact maintainers to tell about your hardware\n");
-               printk(KERN_ERR "Assuming qd65xx is not present.\n");
-               return 1;
-       }
-
-       return (readreg != QD_TESTVAL);
-}
-
-static void __init qd6500_init_dev(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 base = (hwif->config_data & 0xff00) >> 8;
-       u8 config = QD_CONFIG(hwif);
-
-       drive->drive_data = QD6500_DEF_DATA;
-}
-
-static void __init qd6580_init_dev(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u16 t1, t2;
-       u8 base = (hwif->config_data & 0xff00) >> 8;
-       u8 config = QD_CONFIG(hwif);
-
-       if (hwif->host_flags & IDE_HFLAG_SINGLE) {
-               t1 = QD6580_DEF_DATA;
-               t2 = QD6580_DEF_DATA2;
-       } else
-               t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
-
-       drive->drive_data = (drive->dn & 1) ? t2 : t1;
-}
-
-static const struct ide_port_ops qd6500_port_ops = {
-       .init_dev               = qd6500_init_dev,
-       .set_pio_mode           = qd6500_set_pio_mode,
-       .selectproc             = qd65xx_select,
-};
-
-static const struct ide_port_ops qd6580_port_ops = {
-       .init_dev               = qd6580_init_dev,
-       .set_pio_mode           = qd6580_set_pio_mode,
-       .selectproc             = qd65xx_select,
-};
-
-static const struct ide_port_info qd65xx_port_info __initdata = {
-       .name                   = DRV_NAME,
-       .chipset                = ide_qd65xx,
-       .host_flags             = IDE_HFLAG_IO_32BIT |
-                                 IDE_HFLAG_NO_DMA,
-       .pio_mask               = ATA_PIO4,
-};
-
-/*
- * qd_probe:
- *
- * looks at the specified baseport, and if qd found, registers & initialises it
- * return 1 if another qd may be probed
- */
-
-static int __init qd_probe(int base)
-{
-       int rc;
-       u8 config, unit, control;
-       struct ide_port_info d = qd65xx_port_info;
-
-       config = inb(QD_CONFIG_PORT);
-
-       if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
-               return -ENODEV;
-
-       unit = ! (config & QD_CONFIG_IDE_BASEPORT);
-
-       if (unit)
-               d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
-
-       switch (config & 0xf0) {
-       case QD_CONFIG_QD6500:
-               if (qd_testreg(base))
-                        return -ENODEV;        /* bad register */
-
-               if (config & QD_CONFIG_DISABLED) {
-                       printk(KERN_WARNING "qd6500 is disabled !\n");
-                       return -ENODEV;
-               }
-
-               printk(KERN_NOTICE "qd6500 at %#x\n", base);
-               printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
-                       config, QD_ID3);
-
-               d.port_ops = &qd6500_port_ops;
-               d.host_flags |= IDE_HFLAG_SINGLE;
-               break;
-       case QD_CONFIG_QD6580_A:
-       case QD_CONFIG_QD6580_B:
-               if (qd_testreg(base) || qd_testreg(base + 0x02))
-                       return -ENODEV; /* bad registers */
-
-               control = inb(QD_CONTROL_PORT);
-
-               printk(KERN_NOTICE "qd6580 at %#x\n", base);
-               printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n",
-                       config, control, QD_ID3);
-
-               outb(QD_DEF_CONTR, QD_CONTROL_PORT);
-
-               d.port_ops = &qd6580_port_ops;
-               if (control & QD_CONTR_SEC_DISABLED)
-                       d.host_flags |= IDE_HFLAG_SINGLE;
-
-               printk(KERN_INFO "qd6580: %s IDE board\n",
-                       (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual");
-               break;
-       default:
-               return -ENODEV;
-       }
-
-       rc = ide_legacy_device_add(&d, (base << 8) | config);
-
-       if (d.host_flags & IDE_HFLAG_SINGLE)
-               return (rc == 0) ? 1 : rc;
-
-       return rc;
-}
-
-static int probe_qd65xx;
-
-module_param_named(probe, probe_qd65xx, bool, 0);
-MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
-
-static int __init qd65xx_init(void)
-{
-       int rc1, rc2 = -ENODEV;
-
-       if (probe_qd65xx == 0)
-               return -ENODEV;
-
-       rc1 = qd_probe(0x30);
-       if (rc1)
-               rc2 = qd_probe(0xb0);
-
-       if (rc1 < 0 && rc2 < 0)
-               return -ENODEV;
-
-       return 0;
-}
-
-module_init(qd65xx_init);
-
-MODULE_AUTHOR("Samuel Thibault");
-MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
deleted file mode 100644 (file)
index c83dea8..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2000  Linus Torvalds & authors
- */
-
-/*
- * Authors:    Petr Soucek <petr@ryston.cz>
- *             Samuel Thibault <samuel.thibault@fnac.net>
- */
-
-/* truncates a in [b,c] */
-#define IDE_IN(a,b,c)   ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) )
-
-#define IDE_IMPLY(a,b) ((!(a)) || (b))
-
-#define QD_TIM1_PORT           (base)
-#define QD_CONFIG_PORT         (base+0x01)
-#define QD_TIM2_PORT           (base+0x02)
-#define QD_CONTROL_PORT                (base+0x03)
-
-#define QD_CONFIG_IDE_BASEPORT 0x01
-#define QD_CONFIG_BASEPORT     0x02
-#define QD_CONFIG_ID3          0x04
-#define QD_CONFIG_DISABLED     0x08
-#define QD_CONFIG_QD6500       0xc0
-#define QD_CONFIG_QD6580_A     0xa0
-#define QD_CONFIG_QD6580_B     0x50
-
-#define QD_CONTR_SEC_DISABLED  0x01
-
-#define QD_ID3                 ((config & QD_CONFIG_ID3)!=0)
-
-#define QD_CONFIG(hwif)                ((hwif)->config_data & 0x00ff)
-
-#define QD_TIMING(drive)       (byte)(((drive)->drive_data) & 0x00ff)
-#define QD_TIMREG(drive)       (byte)((((drive)->drive_data) & 0xff00) >> 8)
-
-#define QD6500_DEF_DATA                ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08))
-#define QD6580_DEF_DATA                ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
-#define QD6580_DEF_DATA2       ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
-#define QD_DEF_CONTR           (0x40 | ((control & 0x02) ? 0x9f : 0x1f))
-
-#define QD_TESTVAL             0x19    /* safe value */
-
-/* Drive specific timing taken from DOS driver v3.7 */
-
-static struct qd65xx_timing_s {
-       s8      offset;   /* ofset from the beginning of Model Number" */
-       char    model[4];    /* 4 chars from Model number, no conversion */
-       s16     active;   /* active time */
-       s16     recovery; /* recovery time */
-} qd65xx_timing [] = {
-       { 30, "2040", 110, 225 },  /* Conner CP30204                    */
-       { 30, "2045", 135, 225 },  /* Conner CP30254                    */
-       { 30, "1040", 155, 325 },  /* Conner CP30104                    */
-       { 30, "1047", 135, 265 },  /* Conner CP30174                    */
-       { 30, "5344", 135, 225 },  /* Conner CP3544                     */
-       { 30, "01 4", 175, 405 },  /* Conner CP-3104                    */
-       { 27, "C030", 175, 375 },  /* Conner CP3000                     */
-       {  8, "PL42", 110, 295 },  /* Quantum LP240                     */
-       {  8, "PL21", 110, 315 },  /* Quantum LP120                     */
-       {  8, "PL25", 175, 385 },  /* Quantum LP52                      */
-       {  4, "PA24", 110, 285 },  /* WD Piranha SP4200                 */
-       {  6, "2200", 110, 260 },  /* WD Caviar AC2200                  */
-       {  6, "3204", 110, 235 },  /* WD Caviar AC2340                  */
-       {  6, "1202", 110, 265 },  /* WD Caviar AC2120                  */
-       {  0, "DS3-", 135, 315 },  /* Teac SD340                        */
-       {  8, "KM32", 175, 355 },  /* Toshiba MK234                     */
-       {  2, "53A1", 175, 355 },  /* Seagate ST351A                    */
-       {  2, "4108", 175, 295 },  /* Seagate ST1480A                   */
-       {  2, "1344", 175, 335 },  /* Seagate ST3144A                   */
-       {  6, "7 12", 110, 225 },  /* Maxtor 7213A                      */
-       { 30, "02F4", 145, 295 },  /* Conner 3204F                      */
-       {  2, "1302", 175, 335 },  /* Seagate ST3120A                   */
-       {  2, "2334", 145, 265 },  /* Seagate ST3243A                   */
-       {  2, "2338", 145, 275 },  /* Seagate ST3283A                   */
-       {  2, "3309", 145, 275 },  /* Seagate ST3390A                   */
-       {  2, "5305", 145, 275 },  /* Seagate ST3550A                   */
-       {  2, "4100", 175, 295 },  /* Seagate ST1400A                   */
-       {  2, "4110", 175, 295 },  /* Seagate ST1401A                   */
-       {  2, "6300", 135, 265 },  /* Seagate ST3600A                   */
-       {  2, "5300", 135, 265 },  /* Seagate ST3500A                   */
-       {  6, "7 31", 135, 225 },  /* Maxtor 7131 AT                    */
-       {  6, "7 43", 115, 265 },  /* Maxtor 7345 AT                    */
-       {  6, "7 42", 110, 255 },  /* Maxtor 7245 AT                    */
-       {  6, "3 04", 135, 265 },  /* Maxtor 340 AT                     */
-       {  6, "61 0", 135, 285 },  /* WD AC160                          */
-       {  6, "1107", 135, 235 },  /* WD AC1170                         */
-       {  6, "2101", 110, 220 },  /* WD AC1210                         */
-       {  6, "4202", 135, 245 },  /* WD AC2420                         */
-       {  6, "41 0", 175, 355 },  /* WD Caviar 140                     */
-       {  6, "82 0", 175, 355 },  /* WD Caviar 280                     */
-       {  8, "PL01", 175, 375 },  /* Quantum LP105                     */
-       {  8, "PL25", 110, 295 },  /* Quantum LP525                     */
-       { 10, "4S 2", 175, 385 },  /* Quantum ELS42                     */
-       { 10, "8S 5", 175, 385 },  /* Quantum ELS85                     */
-       { 10, "1S72", 175, 385 },  /* Quantum ELS127                    */
-       { 10, "1S07", 175, 385 },  /* Quantum ELS170                    */
-       {  8, "ZE42", 135, 295 },  /* Quantum EZ240                     */
-       {  8, "ZE21", 175, 385 },  /* Quantum EZ127                     */
-       {  8, "ZE58", 175, 385 },  /* Quantum EZ85                      */
-       {  8, "ZE24", 175, 385 },  /* Quantum EZ42                      */
-       { 27, "C036", 155, 325 },  /* Conner CP30064                    */
-       { 27, "C038", 155, 325 },  /* Conner CP30084                    */
-       {  6, "2205", 110, 255 },  /* WDC AC2250                        */
-       {  2, " CHA", 140, 415 },  /* WDC AH series; WDC AH260, WDC     */
-       {  2, " CLA", 140, 415 },  /* WDC AL series: WDC AL2120, 2170,  */
-       {  4, "UC41", 140, 415 },  /* WDC CU140                         */
-       {  6, "1207", 130, 275 },  /* WDC AC2170                        */
-       {  6, "2107", 130, 275 },  /* WDC AC1270                        */
-       {  6, "5204", 130, 275 },  /* WDC AC2540                        */
-       { 30, "3004", 110, 235 },  /* Conner CP30340                    */
-       { 30, "0345", 135, 255 },  /* Conner CP30544                    */
-       { 12, "12A3", 175, 320 },  /* MAXTOR LXT-213A                   */
-       { 12, "43A0", 145, 240 },  /* MAXTOR LXT-340A                   */
-       {  6, "7 21", 180, 290 },  /* Maxtor 7120 AT                    */
-       {  6, "7 71", 135, 240 },  /* Maxtor 7170 AT                    */
-       { 12, "45\0000", 110, 205 },   /* MAXTOR MXT-540                */
-       {  8, "PL11", 180, 290 },  /* QUANTUM LP110A                    */
-       {  8, "OG21", 150, 275 },  /* QUANTUM GO120                     */
-       { 12, "42A5", 175, 320 },  /* MAXTOR LXT-245A                   */
-       {  2, "2309", 175, 295 },  /* ST3290A                           */
-       {  2, "3358", 180, 310 },  /* ST3385A                           */
-       {  2, "6355", 180, 310 },  /* ST3655A                           */
-       {  2, "1900", 175, 270 },  /* ST9100A                           */
-       {  2, "1954", 175, 270 },  /* ST9145A                           */
-       {  2, "1909", 175, 270 },  /* ST9190AG                          */
-       {  2, "2953", 175, 270 },  /* ST9235A                           */
-       {  2, "1359", 175, 270 },  /* ST3195A                           */
-       { 24, "3R11", 175, 290 },  /* ALPS ELECTRIC Co.,LTD, DR311C     */
-       {  0, "2M26", 175, 215 },  /* M262XT-0Ah                        */
-       {  4, "2253", 175, 300 },  /* HP C2235A                         */
-       {  4, "-32A", 145, 245 },  /* H3133-A2                          */
-       { 30, "0326", 150, 270 },  /* Samsung Electronics 120MB         */
-       { 30, "3044", 110, 195 },  /* Conner CFA340A                    */
-       { 30, "43A0", 110, 195 },  /* Conner CFA340A                    */
-       { -1, "    ", 175, 415 }   /* unknown disk name                 */
-};
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
deleted file mode 100644 (file)
index 1da076e..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
- */
-
-/*
- *  Principal Author/Maintainer:  PODIEN@hml2.atlas.de (Wolfram Podien)
- *
- *  This file provides support for the advanced features
- *  of the UMC 8672 IDE interface.
- *
- *  Version 0.01       Initial version, hacked out of ide.c,
- *                     and #include'd rather than compiled separately.
- *                     This will get cleaned up in a subsequent release.
- *
- *  Version 0.02       now configs/compiles separate from ide.c  -ml
- *  Version 0.03       enhanced auto-tune, fix display bug
- *  Version 0.05       replace sti() with restore_flags()  -ml
- *                     add detection of possible race condition  -ml
- */
-
-/*
- * VLB Controller Support from
- * Wolfram Podien
- * Rohoefe 3
- * D28832 Achim
- * Germany
- *
- * To enable UMC8672 support there must a lilo line like
- * append="ide0=umc8672"...
- * To set the speed according to the abilities of the hardware there must be a
- * line like
- * #define UMC_DRIVE0 11
- * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
- * are some lines present). 0 - 11 are allowed speed values. These values are
- * the results from the DOS speed test program supplied from UMC. 11 is the
- * highest speed (about PIO mode 3)
- */
-#define REALLY_SLOW_IO         /* some systems can safely undef this */
-
-#include <linux/module.h>
-#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/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "umc8672"
-
-/*
- * Default speeds.  These can be changed with "auto-tune" and/or hdparm.
- */
-#define UMC_DRIVE0      1              /* DOS measured drive speeds */
-#define UMC_DRIVE1      1              /* 0 to 11 allowed */
-#define UMC_DRIVE2      1              /* 11 = Fastest Speed */
-#define UMC_DRIVE3      1              /* In case of crash reduce speed */
-
-static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
-static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11};    /* rough guesses */
-
-/*       0    1    2    3    4    5    6    7    8    9    10   11      */
-static const u8 speedtab [3][12] = {
-       {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
-       {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
-       {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0}
-};
-
-static void out_umc(char port, char wert)
-{
-       outb_p(port, 0x108);
-       outb_p(wert, 0x109);
-}
-
-static inline u8 in_umc(char port)
-{
-       outb_p(port, 0x108);
-       return inb_p(0x109);
-}
-
-static void umc_set_speeds(u8 speeds[])
-{
-       int i, tmp;
-
-       outb_p(0x5A, 0x108); /* enable umc */
-
-       out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
-       out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
-       tmp = 0;
-       for (i = 3; i >= 0; i--)
-               tmp = (tmp << 2) | speedtab[1][speeds[i]];
-       out_umc(0xdc, tmp);
-       for (i = 0; i < 4; i++) {
-               out_umc(0xd0 + i, speedtab[2][speeds[i]]);
-               out_umc(0xd8 + i, speedtab[2][speeds[i]]);
-       }
-       outb_p(0xa5, 0x108); /* disable umc */
-
-       printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
-               speeds[0], speeds[1], speeds[2], speeds[3]);
-}
-
-static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       unsigned long flags;
-
-       printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
-               drive->name, pio, pio_to_umc[pio]);
-       spin_lock_irqsave(&ide_lock, flags);
-       if (hwif->mate && hwif->mate->hwgroup->handler) {
-               printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
-       } else {
-               current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
-               umc_set_speeds(current_speeds);
-       }
-       spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-static const struct ide_port_ops umc8672_port_ops = {
-       .set_pio_mode           = umc_set_pio_mode,
-};
-
-static const struct ide_port_info umc8672_port_info __initdata = {
-       .name                   = DRV_NAME,
-       .chipset                = ide_umc8672,
-       .port_ops               = &umc8672_port_ops,
-       .host_flags             = IDE_HFLAG_NO_DMA,
-       .pio_mask               = ATA_PIO4,
-};
-
-static int __init umc8672_probe(void)
-{
-       unsigned long flags;
-
-       if (!request_region(0x108, 2, "umc8672")) {
-               printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
-               return 1;
-       }
-       local_irq_save(flags);
-       outb_p(0x5A, 0x108); /* enable umc */
-       if (in_umc (0xd5) != 0xa0) {
-               local_irq_restore(flags);
-               printk(KERN_ERR "umc8672: not found\n");
-               release_region(0x108, 2);
-               return 1;
-       }
-       outb_p(0xa5, 0x108); /* disable umc */
-
-       umc_set_speeds(current_speeds);
-       local_irq_restore(flags);
-
-       return ide_legacy_device_add(&umc8672_port_info, 0);
-}
-
-static int probe_umc8672;
-
-module_param_named(probe, probe_umc8672, bool, 0);
-MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
-
-static int __init umc8672_init(void)
-{
-       if (probe_umc8672 == 0)
-               goto out;
-
-       if (umc8672_probe() == 0)
-               return 0;;
-out:
-       return -ENODEV;;
-}
-
-module_init(umc8672_init);
-
-MODULE_AUTHOR("Wolfram Podien");
-MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/macide.c b/drivers/ide/macide.c
new file mode 100644 (file)
index 0000000..43f97cc
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *  Macintosh IDE Driver
+ *
+ *     Copyright (C) 1998 by Michael Schmitz
+ *
+ *  This driver was written based on information obtained from the MacOS IDE
+ *  driver binary by Mikael Forselius
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/machw.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_baboon.h>
+
+#define IDE_BASE 0x50F1A000    /* Base address of IDE controller */
+
+/*
+ * Generic IDE registers as offsets from the base
+ * These match MkLinux so they should be correct.
+ */
+
+#define IDE_CONTROL    0x38    /* control/altstatus */
+
+/*
+ * Mac-specific registers
+ */
+
+/*
+ * this register is odd; it doesn't seem to do much and it's
+ * not word-aligned like virtually every other hardware register
+ * on the Mac...
+ */
+
+#define IDE_IFR                0x101   /* (0x101) IDE interrupt flags on Quadra:
+                                *
+                                * Bit 0+1: some interrupt flags
+                                * Bit 2+3: some interrupt enable
+                                * Bit 4:   ??
+                                * Bit 5:   IDE interrupt flag (any hwif)
+                                * Bit 6:   maybe IDE interrupt enable (any hwif) ??
+                                * Bit 7:   Any interrupt condition
+                                */
+
+volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR);
+
+int macide_ack_intr(ide_hwif_t* hwif)
+{
+       if (*ide_ifr & 0x20) {
+               *ide_ifr &= ~0x20;
+               return 1;
+       }
+       return 0;
+}
+
+static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
+                                     int irq, ide_ack_intr_t *ack_intr)
+{
+       int i;
+
+       memset(hw, 0, sizeof(*hw));
+
+       for (i = 0; i < 8; i++)
+               hw->io_ports_array[i] = base + i * 4;
+
+       hw->io_ports.ctl_addr = base + IDE_CONTROL;
+
+       hw->irq = irq;
+       hw->ack_intr = ack_intr;
+
+       hw->chipset = ide_generic;
+}
+
+static const char *mac_ide_name[] =
+       { "Quadra", "Powerbook", "Powerbook Baboon" };
+
+/*
+ * Probe for a Macintosh IDE interface
+ */
+
+static int __init macide_init(void)
+{
+       ide_ack_intr_t *ack_intr;
+       unsigned long base;
+       int irq;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+       if (!MACH_IS_MAC)
+               return -ENODEV;
+
+       switch (macintosh_config->ide_type) {
+       case MAC_IDE_QUADRA:
+               base = IDE_BASE;
+               ack_intr = macide_ack_intr;
+               irq = IRQ_NUBUS_F;
+               break;
+       case MAC_IDE_PB:
+               base = IDE_BASE;
+               ack_intr = macide_ack_intr;
+               irq = IRQ_NUBUS_C;
+               break;
+       case MAC_IDE_BABOON:
+               base = BABOON_BASE;
+               ack_intr = NULL;
+               irq = IRQ_BABOON_1;
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
+                        mac_ide_name[macintosh_config->ide_type - 1]);
+
+       macide_setup_ports(&hw, base, irq, ack_intr);
+
+       return ide_host_add(NULL, hws, NULL);
+}
+
+module_init(macide_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile
deleted file mode 100644 (file)
index 5873fa0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)       += au1xxx-ide.o
-
-EXTRA_CFLAGS    := -Idrivers/ide
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
deleted file mode 100644 (file)
index 0ec8fd1..0000000
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
- *
- * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
- *       Interface and Linux Device Driver" Application Note.
- */
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/scatterlist.h>
-
-#include <asm/mach-au1x00/au1xxx.h>
-#include <asm/mach-au1x00/au1xxx_dbdma.h>
-#include <asm/mach-au1x00/au1xxx_ide.h>
-
-#define DRV_NAME       "au1200-ide"
-#define DRV_AUTHOR     "Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>"
-
-/* enable the burstmode in the dbdma */
-#define IDE_AU1XXX_BURSTMODE   1
-
-static _auide_hwif auide_hwif;
-
-#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
-
-void auide_insw(unsigned long port, void *addr, u32 count)
-{
-       _auide_hwif *ahwif = &auide_hwif;
-       chan_tab_t *ctp;
-       au1x_ddma_desc_t *dp;
-
-       if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, 
-                          DDMA_FLAGS_NOIE)) {
-               printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
-               return;
-       }
-       ctp = *((chan_tab_t **)ahwif->rx_chan);
-       dp = ctp->cur_ptr;
-       while (dp->dscr_cmd0 & DSCR_CMD0_V)
-               ;
-       ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
-}
-
-void auide_outsw(unsigned long port, void *addr, u32 count)
-{
-       _auide_hwif *ahwif = &auide_hwif;
-       chan_tab_t *ctp;
-       au1x_ddma_desc_t *dp;
-
-       if(!put_source_flags(ahwif->tx_chan, (void*)addr,
-                            count << 1, DDMA_FLAGS_NOIE)) {
-               printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
-               return;
-       }
-       ctp = *((chan_tab_t **)ahwif->tx_chan);
-       dp = ctp->cur_ptr;
-       while (dp->dscr_cmd0 & DSCR_CMD0_V)
-               ;
-       ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
-}
-
-static void au1xxx_input_data(ide_drive_t *drive, struct request *rq,
-                             void *buf, unsigned int len)
-{
-       auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static void au1xxx_output_data(ide_drive_t *drive, struct request *rq,
-                              void *buf, unsigned int len)
-{
-       auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-#endif
-
-static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
-
-       /* set pio mode! */
-       switch(pio) {
-       case 0:
-               mem_sttime = SBC_IDE_TIMING(PIO0);
-
-               /* set configuration for RCS2# */
-               mem_stcfg |= TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS;
-               break;
-
-       case 1:
-               mem_sttime = SBC_IDE_TIMING(PIO1);
-
-               /* set configuration for RCS2# */
-               mem_stcfg |= TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS;
-               break;
-
-       case 2:
-               mem_sttime = SBC_IDE_TIMING(PIO2);
-
-               /* set configuration for RCS2# */
-               mem_stcfg &= ~TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS;
-               break;
-
-       case 3:
-               mem_sttime = SBC_IDE_TIMING(PIO3);
-
-               /* set configuration for RCS2# */
-               mem_stcfg &= ~TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS;
-
-               break;
-
-       case 4:
-               mem_sttime = SBC_IDE_TIMING(PIO4);
-
-               /* set configuration for RCS2# */
-               mem_stcfg &= ~TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS;
-               break;
-       }
-
-       au_writel(mem_sttime,MEM_STTIME2);
-       au_writel(mem_stcfg,MEM_STCFG2);
-}
-
-static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
-
-       switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-       case XFER_MW_DMA_2:
-               mem_sttime = SBC_IDE_TIMING(MDMA2);
-
-               /* set configuration for RCS2# */
-               mem_stcfg &= ~TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
-
-               break;
-       case XFER_MW_DMA_1:
-               mem_sttime = SBC_IDE_TIMING(MDMA1);
-
-               /* set configuration for RCS2# */
-               mem_stcfg &= ~TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
-
-               break;
-       case XFER_MW_DMA_0:
-               mem_sttime = SBC_IDE_TIMING(MDMA0);
-
-               /* set configuration for RCS2# */
-               mem_stcfg |= TS_MASK;
-               mem_stcfg &= ~TCSOE_MASK;
-               mem_stcfg &= ~TOECS_MASK;
-               mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
-
-               break;
-#endif
-       }
-
-       au_writel(mem_sttime,MEM_STTIME2);
-       au_writel(mem_stcfg,MEM_STCFG2);
-}
-
-/*
- * Multi-Word DMA + DbDMA functions
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-static int auide_build_dmatable(ide_drive_t *drive)
-{
-       int i, iswrite, count = 0;
-       ide_hwif_t *hwif = HWIF(drive);
-       struct request *rq = HWGROUP(drive)->rq;
-       _auide_hwif *ahwif = &auide_hwif;
-       struct scatterlist *sg;
-
-       iswrite = (rq_data_dir(rq) == WRITE);
-       /* Save for interrupt context */
-       ahwif->drive = drive;
-
-       hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-       if (!i)
-               return 0;
-
-       /* fill the descriptors */
-       sg = hwif->sg_table;
-       while (i && sg_dma_len(sg)) {
-               u32 cur_addr;
-               u32 cur_len;
-
-               cur_addr = sg_dma_address(sg);
-               cur_len = sg_dma_len(sg);
-
-               while (cur_len) {
-                       u32 flags = DDMA_FLAGS_NOIE;
-                       unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
-
-                       if (++count >= PRD_ENTRIES) {
-                               printk(KERN_WARNING "%s: DMA table too small\n",
-                                      drive->name);
-                               goto use_pio_instead;
-                       }
-
-                       /* Lets enable intr for the last descriptor only */
-                       if (1==i)
-                               flags = DDMA_FLAGS_IE;
-                       else
-                               flags = DDMA_FLAGS_NOIE;
-
-                       if (iswrite) {
-                               if(!put_source_flags(ahwif->tx_chan, 
-                                                    (void*) sg_virt(sg),
-                                                    tc, flags)) { 
-                                       printk(KERN_ERR "%s failed %d\n", 
-                                              __func__, __LINE__);
-                               }
-                       } else 
-                       {
-                               if(!put_dest_flags(ahwif->rx_chan, 
-                                                  (void*) sg_virt(sg),
-                                                  tc, flags)) { 
-                                       printk(KERN_ERR "%s failed %d\n", 
-                                              __func__, __LINE__);
-                               }
-                       }
-
-                       cur_addr += tc;
-                       cur_len -= tc;
-               }
-               sg = sg_next(sg);
-               i--;
-       }
-
-       if (count)
-               return 1;
-
- use_pio_instead:
-       ide_destroy_dmatable(drive);
-
-       return 0; /* revert to PIO for this request */
-}
-
-static int auide_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-
-       if (hwif->sg_nents) {
-               ide_destroy_dmatable(drive);
-               hwif->sg_nents = 0;
-       }
-
-       return 0;
-}
-
-static void auide_dma_start(ide_drive_t *drive )
-{
-}
-
-
-static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-       /* issue cmd to drive */
-       ide_execute_command(drive, command, &ide_dma_intr,
-                           (2*WAIT_CMD), NULL);
-}
-
-static int auide_dma_setup(ide_drive_t *drive)
-{              
-       struct request *rq = HWGROUP(drive)->rq;
-
-       if (!auide_build_dmatable(drive)) {
-               ide_map_sg(drive, rq);
-               return 1;
-       }
-
-       drive->waiting_for_dma = 1;
-       return 0;
-}
-
-static int auide_dma_test_irq(ide_drive_t *drive)
-{
-       /* If dbdma didn't execute the STOP command yet, the
-        * active bit is still set
-        */
-       drive->waiting_for_dma++;
-       if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
-               printk(KERN_WARNING "%s: timeout waiting for ddma to \
-                                     complete\n", drive->name);
-               return 1;
-       }
-       udelay(10);
-       return 0;
-}
-
-static void auide_dma_host_set(ide_drive_t *drive, int on)
-{
-}
-
-static void auide_ddma_tx_callback(int irq, void *param)
-{
-       _auide_hwif *ahwif = (_auide_hwif*)param;
-       ahwif->drive->waiting_for_dma = 0;
-}
-
-static void auide_ddma_rx_callback(int irq, void *param)
-{
-       _auide_hwif *ahwif = (_auide_hwif*)param;
-       ahwif->drive->waiting_for_dma = 0;
-}
-
-#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
-
-static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags)
-{
-       dev->dev_id          = dev_id;
-       dev->dev_physaddr    = (u32)IDE_PHYS_ADDR;
-       dev->dev_intlevel    = 0;
-       dev->dev_intpolarity = 0;
-       dev->dev_tsize       = tsize;
-       dev->dev_devwidth    = devwidth;
-       dev->dev_flags       = flags;
-}
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-static const struct ide_dma_ops au1xxx_dma_ops = {
-       .dma_host_set           = auide_dma_host_set,
-       .dma_setup              = auide_dma_setup,
-       .dma_exec_cmd           = auide_dma_exec_cmd,
-       .dma_start              = auide_dma_start,
-       .dma_end                = auide_dma_end,
-       .dma_test_irq           = auide_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
-       _auide_hwif *auide = &auide_hwif;
-       dbdev_tab_t source_dev_tab, target_dev_tab;
-       u32 dev_id, tsize, devwidth, flags;
-
-       dev_id   = IDE_DDMA_REQ;
-
-       tsize    =  8; /*  1 */
-       devwidth = 32; /* 16 */
-
-#ifdef IDE_AU1XXX_BURSTMODE 
-       flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE;
-#else
-       flags = DEV_FLAGS_SYNC;
-#endif
-
-       /* setup dev_tab for tx channel */
-       auide_init_dbdma_dev( &source_dev_tab,
-                             dev_id,
-                             tsize, devwidth, DEV_FLAGS_OUT | flags);
-       auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
-
-       auide_init_dbdma_dev( &source_dev_tab,
-                             dev_id,
-                             tsize, devwidth, DEV_FLAGS_IN | flags);
-       auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
-       
-       /* We also need to add a target device for the DMA */
-       auide_init_dbdma_dev( &target_dev_tab,
-                             (u32)DSCR_CMD0_ALWAYS,
-                             tsize, devwidth, DEV_FLAGS_ANYUSE);
-       auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); 
-       /* Get a channel for TX */
-       auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id,
-                                                auide->tx_dev_id,
-                                                auide_ddma_tx_callback,
-                                                (void*)auide);
-       /* Get a channel for RX */
-       auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
-                                                auide->target_dev_id,
-                                                auide_ddma_rx_callback,
-                                                (void*)auide);
-
-       auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan,
-                                                            NUM_DESCRIPTORS);
-       auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
-                                                            NUM_DESCRIPTORS);
-
-       /* FIXME: check return value */
-       (void)ide_allocate_dma_engine(hwif);
-       
-       au1xxx_dbdma_start( auide->tx_chan );
-       au1xxx_dbdma_start( auide->rx_chan );
-       return 0;
-} 
-#else
-static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
-       _auide_hwif *auide = &auide_hwif;
-       dbdev_tab_t source_dev_tab;
-       int flags;
-
-#ifdef IDE_AU1XXX_BURSTMODE 
-       flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE;
-#else
-       flags = DEV_FLAGS_SYNC;
-#endif
-
-       /* setup dev_tab for tx channel */
-       auide_init_dbdma_dev( &source_dev_tab,
-                             (u32)DSCR_CMD0_ALWAYS,
-                             8, 32, DEV_FLAGS_OUT | flags);
-       auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
-
-       auide_init_dbdma_dev( &source_dev_tab,
-                             (u32)DSCR_CMD0_ALWAYS,
-                             8, 32, DEV_FLAGS_IN | flags);
-       auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
-       
-       /* Get a channel for TX */
-       auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
-                                                auide->tx_dev_id,
-                                                NULL,
-                                                (void*)auide);
-       /* Get a channel for RX */
-       auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
-                                                DSCR_CMD0_ALWAYS,
-                                                NULL,
-                                                (void*)auide);
-       auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan,
-                                                            NUM_DESCRIPTORS);
-       auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
-                                                            NUM_DESCRIPTORS);
-       au1xxx_dbdma_start( auide->tx_chan );
-       au1xxx_dbdma_start( auide->rx_chan );
-       
-       return 0;
-}
-#endif
-
-static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
-{
-       int i;
-       unsigned long *ata_regs = hw->io_ports_array;
-
-       /* FIXME? */
-       for (i = 0; i < 8; i++)
-               *ata_regs++ = ahwif->regbase + (i << IDE_REG_SHIFT);
-
-       /* set the Alternative Status register */
-       *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
-}
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
-static const struct ide_tp_ops au1xxx_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = ide_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
-
-       .set_irq                = ide_set_irq,
-
-       .tf_load                = ide_tf_load,
-       .tf_read                = ide_tf_read,
-
-       .input_data             = au1xxx_input_data,
-       .output_data            = au1xxx_output_data,
-};
-#endif
-
-static const struct ide_port_ops au1xxx_port_ops = {
-       .set_pio_mode           = au1xxx_set_pio_mode,
-       .set_dma_mode           = auide_set_dma_mode,
-};
-
-static const struct ide_port_info au1xxx_port_info = {
-       .init_dma               = auide_ddma_init,
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
-       .tp_ops                 = &au1xxx_tp_ops,
-#endif
-       .port_ops               = &au1xxx_port_ops,
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-       .dma_ops                = &au1xxx_dma_ops,
-#endif
-       .host_flags             = IDE_HFLAG_POST_SET_MODE |
-                                 IDE_HFLAG_NO_IO_32BIT |
-                                 IDE_HFLAG_UNMASK_IRQS,
-       .pio_mask               = ATA_PIO4,
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-       .mwdma_mask             = ATA_MWDMA2,
-#endif
-};
-
-static int au_ide_probe(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       _auide_hwif *ahwif = &auide_hwif;
-       struct resource *res;
-       struct ide_host *host;
-       int ret = 0;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
-       char *mode = "MWDMA2";
-#elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
-       char *mode = "PIO+DDMA(offload)";
-#endif
-
-       memset(&auide_hwif, 0, sizeof(_auide_hwif));
-       ahwif->irq = platform_get_irq(pdev, 0);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       if (res == NULL) {
-               pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id);
-               ret = -ENODEV;
-               goto out;
-       }
-       if (ahwif->irq < 0) {
-               pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id);
-               ret = -ENODEV;
-               goto out;
-       }
-
-       if (!request_mem_region(res->start, res->end - res->start + 1,
-                               pdev->name)) {
-               pr_debug("%s: request_mem_region failed\n", DRV_NAME);
-               ret =  -EBUSY;
-               goto out;
-       }
-
-       ahwif->regbase = (u32)ioremap(res->start, res->end - res->start + 1);
-       if (ahwif->regbase == 0) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memset(&hw, 0, sizeof(hw));
-       auide_setup_ports(&hw, ahwif);
-       hw.irq = ahwif->irq;
-       hw.dev = dev;
-       hw.chipset = ide_au1xxx;
-
-       ret = ide_host_add(&au1xxx_port_info, hws, &host);
-       if (ret)
-               goto out;
-
-       auide_hwif.hwif = host->ports[0];
-
-       dev_set_drvdata(dev, host);
-
-       printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
-
- out:
-       return ret;
-}
-
-static int au_ide_remove(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct resource *res;
-       struct ide_host *host = dev_get_drvdata(dev);
-       _auide_hwif *ahwif = &auide_hwif;
-
-       ide_host_remove(host);
-
-       iounmap((void *)ahwif->regbase);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, res->end - res->start + 1);
-
-       return 0;
-}
-
-static struct device_driver au1200_ide_driver = {
-       .name           = "au1200-ide",
-       .bus            = &platform_bus_type,
-       .probe          = au_ide_probe,
-       .remove         = au_ide_remove,
-};
-
-static int __init au_ide_init(void)
-{
-       return driver_register(&au1200_ide_driver);
-}
-
-static void __exit au_ide_exit(void)
-{
-       driver_unregister(&au1200_ide_driver);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("AU1200 IDE driver");
-
-module_init(au_ide_init);
-module_exit(au_ide_exit);
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
new file mode 100644 (file)
index 0000000..1378906
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 1997-1998     Mark Lord <mlord@pobox.com>
+ * Copyright (C) 1998          Eddie C. Dost <ecd@skynet.be>
+ * Copyright (C) 1999-2000     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2004          Grant Grundler <grundler at parisc-linux.org>
+ *
+ * Inspired by an earlier effort from David S. Miller <davem@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "ns87415"
+
+#ifdef CONFIG_SUPERIO
+/* SUPERIO 87560 is a PoS chip that NatSem denies exists.
+ * Unfortunately, it's built-in on all Astro-based PA-RISC workstations
+ * which use the integrated NS87514 cell for CD-ROM support.
+ * i.e we have to support for CD-ROM installs.
+ * See drivers/parisc/superio.c for more gory details.
+ */
+#include <asm/superio.h>
+
+#define SUPERIO_IDE_MAX_RETRIES 25
+
+/* Because of a defect in Super I/O, all reads of the PCI DMA status 
+ * registers, IDE status register and the IDE select register need to be 
+ * retried
+ */
+static u8 superio_ide_inb (unsigned long port)
+{
+       u8 tmp;
+       int retries = SUPERIO_IDE_MAX_RETRIES;
+
+       /* printk(" [ reading port 0x%x with retry ] ", port); */
+
+       do {
+               tmp = inb(port);
+               if (tmp == 0)
+                       udelay(50);
+       } while (tmp == 0 && retries-- > 0);
+
+       return tmp;
+}
+
+static u8 superio_read_status(ide_hwif_t *hwif)
+{
+       return superio_ide_inb(hwif->io_ports.status_addr);
+}
+
+static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
+{
+       return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
+}
+
+static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+
+       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+               u16 data = inw(io_ports->data_addr);
+
+               tf->data = data & 0xff;
+               tf->hob_data = (data >> 8) & 0xff;
+       }
+
+       /* be sure we're looking at the low order bits */
+       outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+               tf->feature = inb(io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+               tf->nsect  = inb(io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+               tf->lbal   = inb(io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+               tf->lbam   = inb(io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+               tf->lbah   = inb(io_ports->lbah_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+               tf->device = superio_ide_inb(io_ports->device_addr);
+
+       if (task->tf_flags & IDE_TFLAG_LBA48) {
+               outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+                       tf->hob_feature = inb(io_ports->feature_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+                       tf->hob_nsect   = inb(io_ports->nsect_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+                       tf->hob_lbal    = inb(io_ports->lbal_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+                       tf->hob_lbam    = inb(io_ports->lbam_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+                       tf->hob_lbah    = inb(io_ports->lbah_addr);
+       }
+}
+
+static const struct ide_tp_ops superio_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = superio_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = superio_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = superio_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
+static void __devinit superio_init_iops(struct hwif_s *hwif)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       u32 dma_stat;
+       u8 port = hwif->channel, tmp;
+
+       dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
+
+       /* Clear error/interrupt, enable dma */
+       tmp = superio_ide_inb(dma_stat);
+       outb(tmp | 0x66, dma_stat);
+}
+#endif
+
+static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
+
+/*
+ * This routine either enables/disables (according to IDE_DFLAG_PRESENT)
+ * the IRQ associated with the port (HWIF(drive)),
+ * and selects either PIO or DMA handshaking for the next I/O operation.
+ */
+static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       new = *old;
+
+       /* Adjust IRQ enable bit */
+       bit = 1 << (8 + hwif->channel);
+
+       if (drive->dev_flags & IDE_DFLAG_PRESENT)
+               new &= ~bit;
+       else
+               new |= bit;
+
+       /* Select PIO or DMA, DMA may only be selected for one drive/channel. */
+       bit   = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1));
+       other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1));
+       new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
+
+       if (new != *old) {
+               unsigned char stat;
+
+               /*
+                * Don't change DMA engine settings while Write Buffers
+                * are busy.
+                */
+               (void) pci_read_config_byte(dev, 0x43, &stat);
+               while (stat & 0x03) {
+                       udelay(1);
+                       (void) pci_read_config_byte(dev, 0x43, &stat);
+               }
+
+               *old = new;
+               (void) pci_write_config_dword(dev, 0x40, new);
+
+               /*
+                * And let things settle...
+                */
+               udelay(10);
+       }
+
+       local_irq_restore(flags);
+}
+
+static void ns87415_selectproc (ide_drive_t *drive)
+{
+       ns87415_prepare_drive(drive,
+                             !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
+}
+
+static int ns87415_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t      *hwif = HWIF(drive);
+       u8 dma_stat = 0, dma_cmd = 0;
+
+       drive->waiting_for_dma = 0;
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+       /* get DMA command mode */
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+       /* stop DMA */
+       outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+       /* from ERRATA: clear the INTR & ERROR bits */
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+       outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
+       /* and free any DMA resources */
+       ide_destroy_dmatable(drive);
+       /* verify good DMA status */
+       return (dma_stat & 7) != 4;
+}
+
+static int ns87415_dma_setup(ide_drive_t *drive)
+{
+       /* select DMA xfer */
+       ns87415_prepare_drive(drive, 1);
+       if (!ide_dma_setup(drive))
+               return 0;
+       /* DMA failed: select PIO xfer */
+       ns87415_prepare_drive(drive, 0);
+       return 1;
+}
+
+static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned int ctrl, using_inta;
+       u8 progif;
+#ifdef __sparc_v9__
+       int timeout;
+       u8 stat;
+#endif
+
+       /*
+        * We cannot probe for IRQ: both ports share common IRQ on INTA.
+        * Also, leave IRQ masked during drive probing, to prevent infinite
+        * interrupts from a potentially floating INTA..
+        *
+        * IRQs get unmasked in selectproc when drive is first used.
+        */
+       (void) pci_read_config_dword(dev, 0x40, &ctrl);
+       (void) pci_read_config_byte(dev, 0x09, &progif);
+       /* is irq in "native" mode? */
+       using_inta = progif & (1 << (hwif->channel << 1));
+       if (!using_inta)
+               using_inta = ctrl & (1 << (4 + hwif->channel));
+       if (hwif->mate) {
+               hwif->select_data = hwif->mate->select_data;
+       } else {
+               hwif->select_data = (unsigned long)
+                                       &ns87415_control[ns87415_count++];
+               ctrl |= (1 << 8) | (1 << 9);    /* mask both IRQs */
+               if (using_inta)
+                       ctrl &= ~(1 << 6);      /* unmask INTA */
+               *((unsigned int *)hwif->select_data) = ctrl;
+               (void) pci_write_config_dword(dev, 0x40, ctrl);
+
+               /*
+                * Set prefetch size to 512 bytes for both ports,
+                * but don't turn on/off prefetching here.
+                */
+               pci_write_config_byte(dev, 0x55, 0xee);
+
+#ifdef __sparc_v9__
+               /*
+                * XXX: Reset the device, if we don't it will not respond to
+                *      SELECT_DRIVE() properly during first ide_probe_port().
+                */
+               timeout = 10000;
+               outb(12, hwif->io_ports.ctl_addr);
+               udelay(10);
+               outb(8, hwif->io_ports.ctl_addr);
+               do {
+                       udelay(50);
+                       stat = hwif->tp_ops->read_status(hwif);
+                       if (stat == 0xff)
+                               break;
+               } while ((stat & ATA_BUSY) && --timeout);
+#endif
+       }
+
+       if (!using_inta)
+               hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
+       else if (!hwif->irq && hwif->mate && hwif->mate->irq)
+               hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
+
+       if (!hwif->dma_base)
+               return;
+
+       outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
+}
+
+static const struct ide_port_ops ns87415_port_ops = {
+       .selectproc             = ns87415_selectproc,
+};
+
+static const struct ide_dma_ops ns87415_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ns87415_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = ns87415_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info ns87415_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_hwif      = init_hwif_ns87415,
+       .port_ops       = &ns87415_port_ops,
+       .dma_ops        = &ns87415_dma_ops,
+       .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+                         IDE_HFLAG_NO_ATAPI_DMA,
+};
+
+static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+       if (PCI_SLOT(dev->devfn) == 0xE) {
+               /* Built-in - assume it's under superio. */
+               d.init_iops = superio_init_iops;
+               d.tp_ops = &superio_tp_ops;
+       }
+#endif
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static const struct pci_device_id ns87415_pci_tbl[] = {
+       { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
+
+static struct pci_driver ns87415_pci_driver = {
+       .name           = "NS87415_IDE",
+       .id_table       = ns87415_pci_tbl,
+       .probe          = ns87415_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init ns87415_ide_init(void)
+{
+       return ide_pci_register_driver(&ns87415_pci_driver);
+}
+
+static void __exit ns87415_ide_exit(void)
+{
+       pci_unregister_driver(&ns87415_pci_driver);
+}
+
+module_init(ns87415_ide_init);
+module_exit(ns87415_ide_exit);
+
+MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for NS87415 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
new file mode 100644 (file)
index 0000000..6048eda
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ *  Copyright (C) 1996-1998  Linus Torvalds & authors (see below)
+ */
+
+/*
+ * Authors:
+ * Jaromir Koutek <miri@punknet.cz>,
+ * Jan Harkes <jaharkes@cwi.nl>,
+ * Mark Lord <mlord@pobox.com>
+ * Some parts of code are from ali14xx.c and from rz1000.c.
+ *
+ * OPTi is trademark of OPTi, Octek is trademark of Octek.
+ *
+ * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps
+ * and disassembled/traced setupvic.exe (DOS program).
+ * It increases kernel code about 2 kB.
+ * I don't have this card no more, but I hope I can get some in case
+ * of needed development.
+ * My card is Octek PIDE 1.01 (on card) or OPTiViC (program).
+ * It has a place for a secondary connector in circuit, but nothing
+ * is there. Also BIOS says no address for
+ * secondary controller (see bellow in ide_init_opti621).
+ * I've only tested this on my system, which only has one disk.
+ * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus
+ * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random
+ * lockups). I tried the OCTEK double speed CD-ROM and
+ * it does not work! But I can't boot DOS also, so it's probably
+ * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no
+ * problems) and Seagate 1GB (as slave, WD as master). My experiences
+ * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes
+ * it slows to about 100kB/s! I don't know why and I have
+ * not this drive now, so I can't try it again.
+ * I write this driver because I lost the paper ("manual") with
+ * settings of jumpers on the card and I have to boot Linux with
+ * Loadlin except LILO, cause I have to run the setupvic.exe program
+ * already or I get disk errors (my test: rpm -Vf
+ * /usr/X11R6/bin/XF86_SVGA - or any big file).
+ * Some numbers from hdparm -t /dev/hda:
+ * Timing buffer-cache reads:   32 MB in  3.02 seconds =10.60 MB/sec
+ * Timing buffered disk reads:  16 MB in  5.52 seconds = 2.90 MB/sec
+ * I have 4 Megs/s before, but I don't know why (maybe changes
+ * in hdparm test).
+ * After release of 0.1, I got some successful reports, so it might work.
+ *
+ * The main problem with OPTi is that some timings for master
+ * and slave must be the same. For example, if you have master
+ * PIO 3 and slave PIO 0, driver have to set some timings of
+ * master for PIO 0. Second problem is that opti621_set_pio_mode
+ * got only one drive to set, but have to set both drives.
+ * This is solved in compute_pios. If you don't set
+ * the second drive, compute_pios use ide_get_best_pio_mode
+ * for autoselect mode (you can change it to PIO 0, if you want).
+ * If you then set the second drive to another PIO, the old value
+ * (automatically selected) will be overrided by yours.
+ * There is a 25/33MHz switch in configuration
+ * register, but driver is written for use at any frequency.
+ *
+ * Version 0.1, Nov 8, 1996
+ * by Jaromir Koutek, for 2.1.8.
+ * Initial version of driver.
+ *
+ * Version 0.2
+ * Number 0.2 skipped.
+ *
+ * Version 0.3, Nov 29, 1997
+ * by Mark Lord (probably), for 2.1.68
+ * Updates for use with new IDE block driver.
+ *
+ * Version 0.4, Dec 14, 1997
+ * by Jan Harkes
+ * Fixed some errors and cleaned the code.
+ *
+ * Version 0.5, Jan 2, 1998
+ * by Jaromir Koutek
+ * Updates for use with (again) new IDE block driver.
+ * Update of documentation.
+ *
+ * Version 0.6, Jan 2, 1999
+ * by Jaromir Koutek
+ * Reversed to version 0.3 of the driver, because
+ * 0.5 doesn't work.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "opti621"
+
+#define READ_REG 0     /* index of Read cycle timing register */
+#define WRITE_REG 1    /* index of Write cycle timing register */
+#define CNTRL_REG 3    /* index of Control register */
+#define STRAP_REG 5    /* index of Strap register */
+#define MISC_REG 6     /* index of Miscellaneous register */
+
+static int reg_base;
+
+static DEFINE_SPINLOCK(opti621_lock);
+
+/* Write value to register reg, base of register
+ * is at reg_base (0x1f0 primary, 0x170 secondary,
+ * if not changed by PCI configuration).
+ * This is from setupvic.exe program.
+ */
+static void write_reg(u8 value, int reg)
+{
+       inw(reg_base + 1);
+       inw(reg_base + 1);
+       outb(3, reg_base + 2);
+       outb(value, reg_base + reg);
+       outb(0x83, reg_base + 2);
+}
+
+/* Read value from register reg, base of register
+ * is at reg_base (0x1f0 primary, 0x170 secondary,
+ * if not changed by PCI configuration).
+ * This is from setupvic.exe program.
+ */
+static u8 read_reg(int reg)
+{
+       u8 ret = 0;
+
+       inw(reg_base + 1);
+       inw(reg_base + 1);
+       outb(3, reg_base + 2);
+       ret = inb(reg_base + reg);
+       outb(0x83, reg_base + 2);
+
+       return ret;
+}
+
+static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       ide_drive_t *pair = ide_get_pair_dev(drive);
+       unsigned long flags;
+       u8 tim, misc, addr_pio = pio, clk;
+
+       /* DRDY is default 2 (by OPTi Databook) */
+       static const u8 addr_timings[2][5] = {
+               { 0x20, 0x10, 0x00, 0x00, 0x00 },       /* 33 MHz */
+               { 0x10, 0x10, 0x00, 0x00, 0x00 },       /* 25 MHz */
+       };
+       static const u8 data_rec_timings[2][5] = {
+               { 0x5b, 0x45, 0x32, 0x21, 0x20 },       /* 33 MHz */
+               { 0x48, 0x34, 0x21, 0x10, 0x10 }        /* 25 MHz */
+       };
+
+       drive->drive_data = XFER_PIO_0 + pio;
+
+       if (pair) {
+               if (pair->drive_data && pair->drive_data < drive->drive_data)
+                       addr_pio = pair->drive_data - XFER_PIO_0;
+       }
+
+       spin_lock_irqsave(&opti621_lock, flags);
+
+       reg_base = hwif->io_ports.data_addr;
+
+       /* allow Register-B */
+       outb(0xc0, reg_base + CNTRL_REG);
+       /* hmm, setupvic.exe does this ;-) */
+       outb(0xff, reg_base + 5);
+       /* if reads 0xff, adapter not exist? */
+       (void)inb(reg_base + CNTRL_REG);
+       /* if reads 0xc0, no interface exist? */
+       read_reg(CNTRL_REG);
+
+       /* check CLK speed */
+       clk = read_reg(STRAP_REG) & 1;
+
+       printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);
+
+       tim  = data_rec_timings[clk][pio];
+       misc = addr_timings[clk][addr_pio];
+
+       /* select Index-0/1 for Register-A/B */
+       write_reg(drive->dn & 1, MISC_REG);
+       /* set read cycle timings */
+       write_reg(tim, READ_REG);
+       /* set write cycle timings */
+       write_reg(tim, WRITE_REG);
+
+       /* use Register-A for drive 0 */
+       /* use Register-B for drive 1 */
+       write_reg(0x85, CNTRL_REG);
+
+       /* set address setup, DRDY timings,   */
+       /*  and read prefetch for both drives */
+       write_reg(misc, MISC_REG);
+
+       spin_unlock_irqrestore(&opti621_lock, flags);
+}
+
+static const struct ide_port_ops opti621_port_ops = {
+       .set_pio_mode           = opti621_set_pio_mode,
+};
+
+static const struct ide_port_info opti621_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
+       .port_ops       = &opti621_port_ops,
+       .host_flags     = IDE_HFLAG_NO_DMA,
+       .pio_mask       = ATA_PIO4,
+};
+
+static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &opti621_chipset, NULL);
+}
+
+static const struct pci_device_id opti621_pci_tbl[] = {
+       { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 },
+       { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
+
+static struct pci_driver opti621_pci_driver = {
+       .name           = "Opti621_IDE",
+       .id_table       = opti621_pci_tbl,
+       .probe          = opti621_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init opti621_ide_init(void)
+{
+       return ide_pci_register_driver(&opti621_pci_driver);
+}
+
+static void __exit opti621_ide_exit(void)
+{
+       pci_unregister_driver(&opti621_pci_driver);
+}
+
+module_init(opti621_ide_init);
+module_exit(opti621_ide_exit);
+
+MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
+MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
new file mode 100644 (file)
index 0000000..122ed3c
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * Palmchip bk3710 IDE controller
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Offset of the primary interface registers */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
+
+/* Primary Control Offset */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
+
+/*
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+struct palm_bk3710_udmatiming {
+       unsigned int rptime;    /* Ready to pause time  */
+       unsigned int cycletime; /* Cycle Time           */
+};
+
+#define BK3710_BMICP           0x00
+#define BK3710_BMISP           0x02
+#define BK3710_BMIDTP          0x04
+#define BK3710_BMICS           0x08
+#define BK3710_BMISS           0x0A
+#define BK3710_BMIDTS          0x0C
+#define BK3710_IDETIMP         0x40
+#define BK3710_IDETIMS         0x42
+#define BK3710_SIDETIM         0x44
+#define BK3710_SLEWCTL         0x45
+#define BK3710_IDESTATUS       0x47
+#define BK3710_UDMACTL         0x48
+#define BK3710_UDMATIM         0x4A
+#define BK3710_MISCCTL         0x50
+#define BK3710_REGSTB          0x54
+#define BK3710_REGRCVR         0x58
+#define BK3710_DATSTB          0x5C
+#define BK3710_DATRCVR         0x60
+#define BK3710_DMASTB          0x64
+#define BK3710_DMARCVR         0x68
+#define BK3710_UDMASTB         0x6C
+#define BK3710_UDMATRP         0x70
+#define BK3710_UDMAENV         0x74
+#define BK3710_IORDYTMP                0x78
+#define BK3710_IORDYTMS                0x7C
+
+static unsigned ideclk_period; /* in nanoseconds */
+
+static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
+       {160, 240},             /* UDMA Mode 0 */
+       {125, 160},             /* UDMA Mode 1 */
+       {100, 120},             /* UDMA Mode 2 */
+       {100, 90},              /* UDMA Mode 3 */
+       {100, 60},              /* UDMA Mode 4 */
+       {85,  40},              /* UDMA Mode 5 */
+};
+
+static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+                                   unsigned int mode)
+{
+       u8 tenv, trp, t0;
+       u32 val32;
+       u16 val16;
+
+       /* DMA Data Setup */
+       t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
+                         ideclk_period) - 1;
+       tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
+       trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
+                          ideclk_period) - 1;
+
+       /* udmatim Register */
+       val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
+       val16 |= (mode << (dev ? 4 : 0));
+       writew(val16, base + BK3710_UDMATIM);
+
+       /* udmastb Ultra DMA Access Strobe Width */
+       val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= (t0 << (dev ? 8 : 0));
+       writel(val32, base + BK3710_UDMASTB);
+
+       /* udmatrp Ultra DMA Ready to Pause Time */
+       val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+       val32 |= (trp << (dev ? 8 : 0));
+       writel(val32, base + BK3710_UDMATRP);
+
+       /* udmaenv Ultra DMA envelop Time */
+       val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+       val32 |= (tenv << (dev ? 8 : 0));
+       writel(val32, base + BK3710_UDMAENV);
+
+       /* Enable UDMA for Device */
+       val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
+       writew(val16, base + BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
+                                  unsigned short min_cycle,
+                                  unsigned int mode)
+{
+       u8 td, tkw, t0;
+       u32 val32;
+       u16 val16;
+       struct ide_timing *t;
+       int cycletime;
+
+       t = ide_timing_find_mode(mode);
+       cycletime = max_t(int, t->cycle, min_cycle);
+
+       /* DMA Data Setup */
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       td = DIV_ROUND_UP(t->active, ideclk_period);
+       tkw = t0 - td - 1;
+       td -= 1;
+
+       val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= (td << (dev ? 8 : 0));
+       writel(val32, base + BK3710_DMASTB);
+
+       val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= (tkw << (dev ? 8 : 0));
+       writel(val32, base + BK3710_DMARCVR);
+
+       /* Disable UDMA for Device */
+       val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
+       writew(val16, base + BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+                                  unsigned int dev, unsigned int cycletime,
+                                  unsigned int mode)
+{
+       u8 t2, t2i, t0;
+       u32 val32;
+       struct ide_timing *t;
+
+       /* PIO Data Setup */
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
+                         ideclk_period);
+
+       t2i = t0 - t2 - 1;
+       t2 -= 1;
+
+       val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= (t2 << (dev ? 8 : 0));
+       writel(val32, base + BK3710_DATSTB);
+
+       val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= (t2i << (dev ? 8 : 0));
+       writel(val32, base + BK3710_DATRCVR);
+
+       if (mate) {
+               u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+
+               if (mode2 < mode)
+                       mode = mode2;
+       }
+
+       /* TASKFILE Setup */
+       t = ide_timing_find_mode(XFER_PIO_0 + mode);
+       t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
+       t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
+
+       t2i = t0 - t2 - 1;
+       t2 -= 1;
+
+       val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= (t2 << (dev ? 8 : 0));
+       writel(val32, base + BK3710_REGSTB);
+
+       val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= (t2i << (dev ? 8 : 0));
+       writel(val32, base + BK3710_REGRCVR);
+}
+
+static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+{
+       int is_slave = drive->dn & 1;
+       void __iomem *base = (void *)drive->hwif->dma_base;
+
+       if (xferspeed >= XFER_UDMA_0) {
+               palm_bk3710_setudmamode(base, is_slave,
+                                       xferspeed - XFER_UDMA_0);
+       } else {
+               palm_bk3710_setdmamode(base, is_slave,
+                                      drive->id[ATA_ID_EIDE_DMA_MIN],
+                                      xferspeed);
+       }
+}
+
+static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+       unsigned int cycle_time;
+       int is_slave = drive->dn & 1;
+       ide_drive_t *mate;
+       void __iomem *base = (void *)drive->hwif->dma_base;
+
+       /*
+        * Obtain the drive PIO data for tuning the Palm Chip registers
+        */
+       cycle_time = ide_pio_cycle_time(drive, pio);
+       mate = ide_get_pair_dev(drive);
+       palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
+}
+
+static void __devinit palm_bk3710_chipinit(void __iomem *base)
+{
+       /*
+        * enable the reset_en of ATA controller so that when ata signals
+        * are brought out, by writing into device config. at that
+        * time por_n signal should not be 'Z' and have a stable value.
+        */
+       writel(0x0300, base + BK3710_MISCCTL);
+
+       /* wait for some time and deassert the reset of ATA Device. */
+       mdelay(100);
+
+       /* Deassert the Reset */
+       writel(0x0200, base + BK3710_MISCCTL);
+
+       /*
+        * Program the IDETIMP Register Value based on the following assumptions
+        *
+        * (ATA_IDETIMP_IDEEN           , ENABLE ) |
+        * (ATA_IDETIMP_SLVTIMEN        , DISABLE) |
+        * (ATA_IDETIMP_RDYSMPL         , 70NS)    |
+        * (ATA_IDETIMP_RDYRCVRY        , 50NS)    |
+        * (ATA_IDETIMP_DMAFTIM1        , PIOCOMP) |
+        * (ATA_IDETIMP_PREPOST1        , DISABLE) |
+        * (ATA_IDETIMP_RDYSEN1         , DISABLE) |
+        * (ATA_IDETIMP_PIOFTIM1        , DISABLE) |
+        * (ATA_IDETIMP_DMAFTIM0        , PIOCOMP) |
+        * (ATA_IDETIMP_PREPOST0        , DISABLE) |
+        * (ATA_IDETIMP_RDYSEN0         , DISABLE) |
+        * (ATA_IDETIMP_PIOFTIM0        , DISABLE)
+        */
+       writew(0xB388, base + BK3710_IDETIMP);
+
+       /*
+        * Configure  SIDETIM  Register
+        * (ATA_SIDETIM_RDYSMPS1        ,120NS ) |
+        * (ATA_SIDETIM_RDYRCYS1        ,120NS )
+        */
+       writeb(0, base + BK3710_SIDETIM);
+
+       /*
+        * UDMACTL Ultra-ATA DMA Control
+        * (ATA_UDMACTL_UDMAP1  , 0 ) |
+        * (ATA_UDMACTL_UDMAP0  , 0 )
+        *
+        */
+       writew(0, base + BK3710_UDMACTL);
+
+       /*
+        * MISCCTL Miscellaneous Conrol Register
+        * (ATA_MISCCTL_RSTMODEP        , 1) |
+        * (ATA_MISCCTL_RESETP          , 0) |
+        * (ATA_MISCCTL_TIMORIDE        , 1)
+        */
+       writel(0x201, base + BK3710_MISCCTL);
+
+       /*
+        * IORDYTMP IORDY Timer for Primary Register
+        * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+        */
+       writel(0xFFFF, base + BK3710_IORDYTMP);
+
+       /*
+        * Configure BMISP Register
+        * (ATA_BMISP_DMAEN1    , DISABLE )     |
+        * (ATA_BMISP_DMAEN0    , DISABLE )     |
+        * (ATA_BMISP_IORDYINT  , CLEAR)        |
+        * (ATA_BMISP_INTRSTAT  , CLEAR)        |
+        * (ATA_BMISP_DMAERROR  , CLEAR)
+        */
+       writew(0, base + BK3710_BMISP);
+
+       palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
+       palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+
+static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif)
+{
+       return ATA_CBL_PATA80;
+}
+
+static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
+                                         const struct ide_port_info *d)
+{
+       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
+
+       hwif->dma_ops = &sff_dma_ops;
+
+       return 0;
+}
+
+static const struct ide_port_ops palm_bk3710_ports_ops = {
+       .set_pio_mode           = palm_bk3710_set_pio_mode,
+       .set_dma_mode           = palm_bk3710_set_dma_mode,
+       .cable_detect           = palm_bk3710_cable_detect,
+};
+
+static struct ide_port_info __devinitdata palm_bk3710_port_info = {
+       .init_dma               = palm_bk3710_init_dma,
+       .port_ops               = &palm_bk3710_ports_ops,
+       .host_flags             = IDE_HFLAG_MMIO,
+       .pio_mask               = ATA_PIO4,
+       .mwdma_mask             = ATA_MWDMA2,
+};
+
+static int __init palm_bk3710_probe(struct platform_device *pdev)
+{
+       struct clk *clk;
+       struct resource *mem, *irq;
+       unsigned long base, rate;
+       int i, rc;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+       clk = clk_get(&pdev->dev, "IDECLK");
+       if (IS_ERR(clk))
+               return -ENODEV;
+
+       clk_enable(clk);
+       rate = clk_get_rate(clk);
+       ideclk_period = 1000000000UL / rate;
+
+       /* Register the IDE interface with Linux ATA Interface */
+       memset(&hw, 0, sizeof(hw));
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (mem == NULL) {
+               printk(KERN_ERR "failed to get memory region resource\n");
+               return -ENODEV;
+       }
+
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (irq == NULL) {
+               printk(KERN_ERR "failed to get IRQ resource\n");
+               return -ENODEV;
+       }
+
+       if (request_mem_region(mem->start, mem->end - mem->start + 1,
+                              "palm_bk3710") == NULL) {
+               printk(KERN_ERR "failed to request memory region\n");
+               return -EBUSY;
+       }
+
+       base = IO_ADDRESS(mem->start);
+
+       /* Configure the Palm Chip controller */
+       palm_bk3710_chipinit((void __iomem *)base);
+
+       for (i = 0; i < IDE_NR_PORTS - 2; i++)
+               hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
+       hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
+       hw.irq = irq->start;
+       hw.dev = &pdev->dev;
+       hw.chipset = ide_palm3710;
+
+       palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
+                                                            ATA_UDMA5;
+
+       rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
+       if (rc)
+               goto out;
+
+       return 0;
+out:
+       printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
+       return rc;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:palm_bk3710");
+
+static struct platform_driver platform_bk_driver = {
+       .driver = {
+               .name = "palm_bk3710",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init palm_bk3710_init(void)
+{
+       return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe);
+}
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
deleted file mode 100644 (file)
index ab44a1f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-
-obj-$(CONFIG_BLK_DEV_AEC62XX)          += aec62xx.o
-obj-$(CONFIG_BLK_DEV_ALI15X3)          += alim15x3.o
-obj-$(CONFIG_BLK_DEV_AMD74XX)          += amd74xx.o
-obj-$(CONFIG_BLK_DEV_ATIIXP)           += atiixp.o
-obj-$(CONFIG_BLK_DEV_CELLEB)           += scc_pata.o
-obj-$(CONFIG_BLK_DEV_CMD64X)           += cmd64x.o
-obj-$(CONFIG_BLK_DEV_CS5520)           += cs5520.o
-obj-$(CONFIG_BLK_DEV_CS5530)           += cs5530.o
-obj-$(CONFIG_BLK_DEV_CS5535)           += cs5535.o
-obj-$(CONFIG_BLK_DEV_SC1200)           += sc1200.o
-obj-$(CONFIG_BLK_DEV_CY82C693)         += cy82c693.o
-obj-$(CONFIG_BLK_DEV_DELKIN)           += delkin_cb.o
-obj-$(CONFIG_BLK_DEV_HPT366)           += hpt366.o
-obj-$(CONFIG_BLK_DEV_IT8213)           += it8213.o
-obj-$(CONFIG_BLK_DEV_IT821X)           += it821x.o
-obj-$(CONFIG_BLK_DEV_JMICRON)          += jmicron.o
-obj-$(CONFIG_BLK_DEV_NS87415)          += ns87415.o
-obj-$(CONFIG_BLK_DEV_OPTI621)          += opti621.o
-obj-$(CONFIG_BLK_DEV_PDC202XX_OLD)     += pdc202xx_old.o
-obj-$(CONFIG_BLK_DEV_PDC202XX_NEW)     += pdc202xx_new.o
-obj-$(CONFIG_BLK_DEV_PIIX)             += piix.o
-obj-$(CONFIG_BLK_DEV_RZ1000)           += rz1000.o
-obj-$(CONFIG_BLK_DEV_SVWKS)            += serverworks.o
-obj-$(CONFIG_BLK_DEV_SGIIOC4)          += sgiioc4.o
-obj-$(CONFIG_BLK_DEV_SIIMAGE)          += siimage.o
-obj-$(CONFIG_BLK_DEV_SIS5513)          += sis5513.o
-obj-$(CONFIG_BLK_DEV_SL82C105)         += sl82c105.o
-obj-$(CONFIG_BLK_DEV_SLC90E66)         += slc90e66.o
-obj-$(CONFIG_BLK_DEV_TC86C001)         += tc86c001.o
-obj-$(CONFIG_BLK_DEV_TRIFLEX)          += triflex.o
-obj-$(CONFIG_BLK_DEV_TRM290)           += trm290.o
-obj-$(CONFIG_BLK_DEV_VIA82CXXX)                += via82cxxx.o
-
-# Must appear at the end of the block
-obj-$(CONFIG_BLK_DEV_GENERIC)          += ide-pci-generic.o
-ide-pci-generic-y                      += generic.o
-
-ifeq ($(CONFIG_BLK_DEV_CMD640), m)
-       obj-m += cmd640.o
-endif
-
-EXTRA_CFLAGS   := -Idrivers/ide
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
deleted file mode 100644 (file)
index 4142c69..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "aec62xx"
-
-struct chipset_bus_clock_list_entry {
-       u8 xfer_speed;
-       u8 chipset_settings;
-       u8 ultra_settings;
-};
-
-static const struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
-       {       XFER_UDMA_6,    0x31,   0x07    },
-       {       XFER_UDMA_5,    0x31,   0x06    },
-       {       XFER_UDMA_4,    0x31,   0x05    },
-       {       XFER_UDMA_3,    0x31,   0x04    },
-       {       XFER_UDMA_2,    0x31,   0x03    },
-       {       XFER_UDMA_1,    0x31,   0x02    },
-       {       XFER_UDMA_0,    0x31,   0x01    },
-
-       {       XFER_MW_DMA_2,  0x31,   0x00    },
-       {       XFER_MW_DMA_1,  0x31,   0x00    },
-       {       XFER_MW_DMA_0,  0x0a,   0x00    },
-       {       XFER_PIO_4,     0x31,   0x00    },
-       {       XFER_PIO_3,     0x33,   0x00    },
-       {       XFER_PIO_2,     0x08,   0x00    },
-       {       XFER_PIO_1,     0x0a,   0x00    },
-       {       XFER_PIO_0,     0x00,   0x00    },
-       {       0,              0x00,   0x00    }
-};
-
-static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
-       {       XFER_UDMA_6,    0x41,   0x06    },
-       {       XFER_UDMA_5,    0x41,   0x05    },
-       {       XFER_UDMA_4,    0x41,   0x04    },
-       {       XFER_UDMA_3,    0x41,   0x03    },
-       {       XFER_UDMA_2,    0x41,   0x02    },
-       {       XFER_UDMA_1,    0x41,   0x01    },
-       {       XFER_UDMA_0,    0x41,   0x01    },
-
-       {       XFER_MW_DMA_2,  0x41,   0x00    },
-       {       XFER_MW_DMA_1,  0x42,   0x00    },
-       {       XFER_MW_DMA_0,  0x7a,   0x00    },
-       {       XFER_PIO_4,     0x41,   0x00    },
-       {       XFER_PIO_3,     0x43,   0x00    },
-       {       XFER_PIO_2,     0x78,   0x00    },
-       {       XFER_PIO_1,     0x7a,   0x00    },
-       {       XFER_PIO_0,     0x70,   0x00    },
-       {       0,              0x00,   0x00    }
-};
-
-/*
- * TO DO: active tuning and correction of cards without a bios.
- */
-static u8 pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
-{
-       for ( ; chipset_table->xfer_speed ; chipset_table++)
-               if (chipset_table->xfer_speed == speed) {
-                       return chipset_table->chipset_settings;
-               }
-       return chipset_table->chipset_settings;
-}
-
-static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
-{
-       for ( ; chipset_table->xfer_speed ; chipset_table++)
-               if (chipset_table->xfer_speed == speed) {
-                       return chipset_table->ultra_settings;
-               }
-       return chipset_table->ultra_settings;
-}
-
-static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct ide_host *host   = pci_get_drvdata(dev);
-       struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
-       u16 d_conf              = 0;
-       u8 ultra = 0, ultra_conf = 0;
-       u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       /* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
-       pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
-       tmp0 = pci_bus_clock_list(speed, bus_clock);
-       d_conf = ((tmp0 & 0xf0) << 4) | (tmp0 & 0xf);
-       pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
-
-       tmp1 = 0x00;
-       tmp2 = 0x00;
-       pci_read_config_byte(dev, 0x54, &ultra);
-       tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
-       ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
-       tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
-       pci_write_config_byte(dev, 0x54, tmp2);
-       local_irq_restore(flags);
-}
-
-static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct ide_host *host   = pci_get_drvdata(dev);
-       struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
-       u8 unit                 = drive->dn & 1;
-       u8 tmp1 = 0, tmp2 = 0;
-       u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       /* high 4-bits: Active, low 4-bits: Recovery */
-       pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
-       drive_conf = pci_bus_clock_list(speed, bus_clock);
-       pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
-
-       pci_read_config_byte(dev, (0x44|hwif->channel), &ultra);
-       tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
-       ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
-       tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
-       pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
-       local_irq_restore(flags);
-}
-
-static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
-}
-
-static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
-{
-       /* These are necessary to get AEC6280 Macintosh cards to work */
-       if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
-           (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
-               u8 reg49h = 0, reg4ah = 0;
-               /* Clear reset and test bits.  */
-               pci_read_config_byte(dev, 0x49, &reg49h);
-               pci_write_config_byte(dev, 0x49, reg49h & ~0x30);
-               /* Enable chip interrupt output.  */
-               pci_read_config_byte(dev, 0x4a, &reg4ah);
-               pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01);
-               /* Enable burst mode. */
-               pci_read_config_byte(dev, 0x4a, &reg4ah);
-               pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
-       }
-
-       return dev->irq;
-}
-
-static u8 atp86x_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
-
-       pci_read_config_byte(dev, 0x49, &ata66);
-
-       return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-}
-
-static const struct ide_port_ops atp850_port_ops = {
-       .set_pio_mode           = aec_set_pio_mode,
-       .set_dma_mode           = aec6210_set_mode,
-};
-
-static const struct ide_port_ops atp86x_port_ops = {
-       .set_pio_mode           = aec_set_pio_mode,
-       .set_dma_mode           = aec6260_set_mode,
-       .cable_detect           = atp86x_cable_detect,
-};
-
-static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
-       {       /* 0: AEC6210 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_aec62xx,
-               .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-               .port_ops       = &atp850_port_ops,
-               .host_flags     = IDE_HFLAG_SERIALIZE |
-                                 IDE_HFLAG_NO_ATAPI_DMA |
-                                 IDE_HFLAG_NO_DSC |
-                                 IDE_HFLAG_OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA2,
-       },
-       {       /* 1: AEC6260 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_aec62xx,
-               .port_ops       = &atp86x_port_ops,
-               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
-                                 IDE_HFLAG_OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA4,
-       },
-       {       /* 2: AEC6260R */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_aec62xx,
-               .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-               .port_ops       = &atp86x_port_ops,
-               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
-                                 IDE_HFLAG_NON_BOOTABLE,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA4,
-       },
-       {       /* 3: AEC6280 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_aec62xx,
-               .port_ops       = &atp86x_port_ops,
-               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
-                                 IDE_HFLAG_OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       },
-       {       /* 4: AEC6280R */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_aec62xx,
-               .enablebits     = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
-               .port_ops       = &atp86x_port_ops,
-               .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
-                                 IDE_HFLAG_OFF_BOARD,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       }
-};
-
-/**
- *     aec62xx_init_one        -       called when a AEC is found
- *     @dev: the aec62xx device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- *
- *     NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
- *     chips, pass a local copy of 'struct ide_port_info' down the call chain.
- */
-
-static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       const struct chipset_bus_clock_list_entry *bus_clock;
-       struct ide_port_info d;
-       u8 idx = id->driver_data;
-       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-       int err;
-
-       if (bus_speed <= 33)
-               bus_clock = aec6xxx_33_base;
-       else
-               bus_clock = aec6xxx_34_base;
-
-       err = pci_enable_device(dev);
-       if (err)
-               return err;
-
-       d = aec62xx_chipsets[idx];
-
-       if (idx == 3 || idx == 4) {
-               unsigned long dma_base = pci_resource_start(dev, 4);
-
-               if (inb(dma_base + 2) & 0x10) {
-                       printk(KERN_INFO DRV_NAME " %s: AEC6880%s card detected"
-                               "\n", pci_name(dev), (idx == 4) ? "R" : "");
-                       d.udma_mask = ATA_UDMA6;
-               }
-       }
-
-       err = ide_pci_init_one(dev, &d, (void *)bus_clock);
-       if (err)
-               pci_disable_device(dev);
-
-       return err;
-}
-
-static void __devexit aec62xx_remove(struct pci_dev *dev)
-{
-       ide_pci_remove(dev);
-       pci_disable_device(dev);
-}
-
-static const struct pci_device_id aec62xx_pci_tbl[] = {
-       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
-       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860),   1 },
-       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R),  2 },
-       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865),   3 },
-       { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R),  4 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
-
-static struct pci_driver aec62xx_pci_driver = {
-       .name           = "AEC62xx_IDE",
-       .id_table       = aec62xx_pci_tbl,
-       .probe          = aec62xx_init_one,
-       .remove         = __devexit_p(aec62xx_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init aec62xx_ide_init(void)
-{
-       return ide_pci_register_driver(&aec62xx_pci_driver);
-}
-
-static void __exit aec62xx_ide_exit(void)
-{
-       pci_unregister_driver(&aec62xx_pci_driver);
-}
-
-module_init(aec62xx_ide_init);
-module_exit(aec62xx_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
deleted file mode 100644 (file)
index daf9dce..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
- *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
- *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
- *
- *  Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org)
- *  May be copied or modified under the terms of the GNU General Public License
- *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
- *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
- *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
- *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
- *
- *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
- *
- **********************************************************************
- *  9/7/99 --Parts from the above author are included and need to be
- *  converted into standard interface, once I finish the thought.
- *
- *  Recent changes
- *     Don't use LBA48 mode on ALi <= 0xC4
- *     Don't poke 0x79 with a non ALi northbridge
- *     Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang)
- *     Allow UDMA6 on revisions > 0xC4
- *
- *  Documentation
- *     Chipset documentation available under NDA only
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "alim15x3"
-
-/*
- * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking
- * (this is DANGEROUS and could result in data corruption).
- */
-static int wdc_udma;
-
-module_param(wdc_udma, bool, 0);
-MODULE_PARM_DESC(wdc_udma,
-                "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)");
-
-/*
- *     ALi devices are not plug in. Otherwise these static values would
- *     need to go. They ought to go away anyway
- */
-static u8 m5229_revision;
-static u8 chip_is_1543c_e;
-static struct pci_dev *isa_dev;
-
-/**
- *     ali_set_pio_mode        -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Program the controller for the given PIO mode.
- */
-
-static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-       int s_time = t->setup, a_time = t->active, c_time = t->cycle;
-       u8 s_clc, a_clc, r_clc;
-       unsigned long flags;
-       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-       int port = hwif->channel ? 0x5c : 0x58;
-       int portFIFO = hwif->channel ? 0x55 : 0x54;
-       u8 cd_dma_fifo = 0, unit = drive->dn & 1;
-
-       if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
-               s_clc = 0;
-       if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
-               a_clc = 0;
-
-       if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
-               r_clc = 1;
-       } else {
-               if (r_clc >= 16)
-                       r_clc = 0;
-       }
-       local_irq_save(flags);
-       
-       /* 
-        * PIO mode => ATA FIFO on, ATAPI FIFO off
-        */
-       pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);
-       if (drive->media==ide_disk) {
-               if (unit) {
-                       pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);
-               } else {
-                       pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);
-               }
-       } else {
-               if (unit) {
-                       pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);
-               } else {
-                       pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);
-               }
-       }
-       
-       pci_write_config_byte(dev, port, s_clc);
-       pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
-       local_irq_restore(flags);
-}
-
-/**
- *     ali_udma_filter         -       compute UDMA mask
- *     @drive: IDE device
- *
- *     Return available UDMA modes.
- *
- *     The actual rules for the ALi are:
- *             No UDMA on revisions <= 0x20
- *             Disk only for revisions < 0xC2
- *             Not WDC drives on M1543C-E (?)
- */
-
-static u8 ali_udma_filter(ide_drive_t *drive)
-{
-       if (m5229_revision > 0x20 && m5229_revision < 0xC2) {
-               if (drive->media != ide_disk)
-                       return 0;
-               if (wdc_udma == 0 && chip_is_1543c_e &&
-                   strstr((char *)&drive->id[ATA_ID_PROD], "WDC "))
-                       return 0;
-       }
-
-       return drive->hwif->ultra_mask;
-}
-
-/**
- *     ali_set_dma_mode        -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Configure the hardware for the desired IDE transfer mode.
- */
-
-static void ali_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 speed1               = speed;
-       u8 unit                 = drive->dn & 1;
-       u8 tmpbyte              = 0x00;
-       int m5229_udma          = (hwif->channel) ? 0x57 : 0x56;
-
-       if (speed == XFER_UDMA_6)
-               speed1 = 0x47;
-
-       if (speed < XFER_UDMA_0) {
-               u8 ultra_enable = (unit) ? 0x7f : 0xf7;
-               /*
-                * clear "ultra enable" bit
-                */
-               pci_read_config_byte(dev, m5229_udma, &tmpbyte);
-               tmpbyte &= ultra_enable;
-               pci_write_config_byte(dev, m5229_udma, tmpbyte);
-
-               /*
-                * FIXME: Oh, my... DMA timings are never set.
-                */
-       } else {
-               pci_read_config_byte(dev, m5229_udma, &tmpbyte);
-               tmpbyte &= (0x0f << ((1-unit) << 2));
-               /*
-                * enable ultra dma and set timing
-                */
-               tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2));
-               pci_write_config_byte(dev, m5229_udma, tmpbyte);
-               if (speed >= XFER_UDMA_3) {
-                       pci_read_config_byte(dev, 0x4b, &tmpbyte);
-                       tmpbyte |= 1;
-                       pci_write_config_byte(dev, 0x4b, tmpbyte);
-               }
-       }
-}
-
-/**
- *     ali15x3_dma_setup       -       begin a DMA phase
- *     @drive: target device
- *
- *     Returns 1 if the DMA cannot be performed, zero on success.
- */
-
-static int ali15x3_dma_setup(ide_drive_t *drive)
-{
-       if (m5229_revision < 0xC2 && drive->media != ide_disk) {
-               if (rq_data_dir(drive->hwif->hwgroup->rq))
-                       return 1;       /* try PIO instead of DMA */
-       }
-       return ide_dma_setup(drive);
-}
-
-/**
- *     init_chipset_ali15x3    -       Initialise an ALi IDE controller
- *     @dev: PCI device
- *
- *     This function initializes the ALI IDE controller and where 
- *     appropriate also sets up the 1533 southbridge.
- */
-
-static unsigned int init_chipset_ali15x3(struct pci_dev *dev)
-{
-       unsigned long flags;
-       u8 tmpbyte;
-       struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
-
-       m5229_revision = dev->revision;
-
-       isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-
-       local_irq_save(flags);
-
-       if (m5229_revision < 0xC2) {
-               /*
-                * revision 0x20 (1543-E, 1543-F)
-                * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E)
-                * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7
-                */
-               pci_read_config_byte(dev, 0x4b, &tmpbyte);
-               /*
-                * clear bit 7
-                */
-               pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
-               /*
-                * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
-                */
-               if (m5229_revision >= 0x20 && isa_dev) {
-                       pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
-                       chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
-               }
-               goto out;
-       }
-
-       /*
-        * 1543C-B?, 1535, 1535D, 1553
-        * Note 1: not all "motherboard" support this detection
-        * Note 2: if no udma 66 device, the detection may "error".
-        *         but in this case, we will not set the device to
-        *         ultra 66, the detection result is not important
-        */
-
-       /*
-        * enable "Cable Detection", m5229, 0x4b, bit3
-        */
-       pci_read_config_byte(dev, 0x4b, &tmpbyte);
-       pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08);
-
-       /*
-        * We should only tune the 1533 enable if we are using an ALi
-        * North bridge. We might have no north found on some zany
-        * box without a device at 0:0.0. The ALi bridge will be at
-        * 0:0.0 so if we didn't find one we know what is cooking.
-        */
-       if (north && north->vendor != PCI_VENDOR_ID_AL)
-               goto out;
-
-       if (m5229_revision < 0xC5 && isa_dev)
-       {       
-               /*
-                * set south-bridge's enable bit, m1533, 0x79
-                */
-
-               pci_read_config_byte(isa_dev, 0x79, &tmpbyte);
-               if (m5229_revision == 0xC2) {
-                       /*
-                        * 1543C-B0 (m1533, 0x79, bit 2)
-                        */
-                       pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04);
-               } else if (m5229_revision >= 0xC3) {
-                       /*
-                        * 1553/1535 (m1533, 0x79, bit 1)
-                        */
-                       pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
-               }
-       }
-
-out:
-       /*
-        * CD_ROM DMA on (m5229, 0x53, bit0)
-        *      Enable this bit even if we want to use PIO.
-        * PIO FIFO off (m5229, 0x53, bit1)
-        *      The hardware will use 0x54h and 0x55h to control PIO FIFO.
-        *      (Not on later devices it seems)
-        *
-        *      0x53 changes meaning on later revs - we must no touch
-        *      bit 1 on them.  Need to check if 0x20 is the right break.
-        */
-       if (m5229_revision >= 0x20) {
-               pci_read_config_byte(dev, 0x53, &tmpbyte);
-
-               if (m5229_revision <= 0x20)
-                       tmpbyte = (tmpbyte & (~0x02)) | 0x01;
-               else if (m5229_revision == 0xc7 || m5229_revision == 0xc8)
-                       tmpbyte |= 0x03;
-               else
-                       tmpbyte |= 0x01;
-
-               pci_write_config_byte(dev, 0x53, tmpbyte);
-       }
-       pci_dev_put(north);
-       pci_dev_put(isa_dev);
-       local_irq_restore(flags);
-       return 0;
-}
-
-/*
- *     Cable special cases
- */
-
-static const struct dmi_system_id cable_dmi_table[] = {
-       {
-               .ident = "HP Pavilion N5430",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
-               },
-       },
-       {
-               .ident = "Toshiba Satellite S1800-814",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
-               },
-       },
-       { }
-};
-
-static int ali_cable_override(struct pci_dev *pdev)
-{
-       /* Fujitsu P2000 */
-       if (pdev->subsystem_vendor == 0x10CF &&
-           pdev->subsystem_device == 0x10AF)
-               return 1;
-
-       /* Mitac 8317 (Winbook-A) and relatives */
-       if (pdev->subsystem_vendor == 0x1071 &&
-           pdev->subsystem_device == 0x8317)
-               return 1;
-
-       /* Systems by DMI */
-       if (dmi_check_system(cable_dmi_table))
-               return 1;
-
-       return 0;
-}
-
-/**
- *     ali_cable_detect        -       cable detection
- *     @hwif: IDE interface
- *
- *     This checks if the controller and the cable are capable
- *     of UDMA66 transfers. It doesn't check the drives.
- *     But see note 2 below!
- *
- *     FIXME: frobs bits that are not defined on newer ALi devicea
- */
-
-static u8 ali_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned long flags;
-       u8 cbl = ATA_CBL_PATA40, tmpbyte;
-
-       local_irq_save(flags);
-
-       if (m5229_revision >= 0xC2) {
-               /*
-                * m5229 80-pin cable detection (from Host View)
-                *
-                * 0x4a bit0 is 0 => primary channel has 80-pin
-                * 0x4a bit1 is 0 => secondary channel has 80-pin
-                *
-                * Certain laptops use short but suitable cables
-                * and don't implement the detect logic.
-                */
-               if (ali_cable_override(dev))
-                       cbl = ATA_CBL_PATA40_SHORT;
-               else {
-                       pci_read_config_byte(dev, 0x4a, &tmpbyte);
-                       if ((tmpbyte & (1 << hwif->channel)) == 0)
-                               cbl = ATA_CBL_PATA80;
-               }
-       }
-
-       local_irq_restore(flags);
-
-       return cbl;
-}
-
-#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
-/**
- *     init_hwif_ali15x3       -       Initialize the ALI IDE x86 stuff
- *     @hwif: interface to configure
- *
- *     Obtain the IRQ tables for an ALi based IDE solution on the PC
- *     class platforms. This part of the code isn't applicable to the
- *     Sparc and PowerPC systems.
- */
-
-static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 ideic, inmir;
-       s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
-                                     1, 11, 0, 12, 0, 14, 0, 15 };
-       int irq = -1;
-
-       if (dev->device == PCI_DEVICE_ID_AL_M5229)
-               hwif->irq = hwif->channel ? 15 : 14;
-
-       if (isa_dev) {
-               /*
-                * read IDE interface control
-                */
-               pci_read_config_byte(isa_dev, 0x58, &ideic);
-
-               /* bit0, bit1 */
-               ideic = ideic & 0x03;
-
-               /* get IRQ for IDE Controller */
-               if ((hwif->channel && ideic == 0x03) ||
-                   (!hwif->channel && !ideic)) {
-                       /*
-                        * get SIRQ1 routing table
-                        */
-                       pci_read_config_byte(isa_dev, 0x44, &inmir);
-                       inmir = inmir & 0x0f;
-                       irq = irq_routing_table[inmir];
-               } else if (hwif->channel && !(ideic & 0x01)) {
-                       /*
-                        * get SIRQ2 routing table
-                        */
-                       pci_read_config_byte(isa_dev, 0x75, &inmir);
-                       inmir = inmir & 0x0f;
-                       irq = irq_routing_table[inmir];
-               }
-               if(irq >= 0)
-                       hwif->irq = irq;
-       }
-}
-#else
-#define init_hwif_ali15x3 NULL
-#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
-
-/**
- *     init_dma_ali15x3        -       set up DMA on ALi15x3
- *     @hwif: IDE interface
- *     @d: IDE port info
- *
- *     Set up the DMA functionality on the ALi 15x3.
- */
-
-static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
-                                     const struct ide_port_info *d)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned long base = ide_pci_dma_base(hwif, d);
-
-       if (base == 0)
-               return -1;
-
-       hwif->dma_base = base;
-
-       if (ide_pci_check_simplex(hwif, d) < 0)
-               return -1;
-
-       if (ide_pci_set_master(dev, d->name) < 0)
-               return -1;
-
-       if (!hwif->channel)
-               outb(inb(base + 2) & 0x60, base + 2);
-
-       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
-                        hwif->name, base, base + 7);
-
-       if (ide_allocate_dma_engine(hwif))
-               return -1;
-
-       hwif->dma_ops = &sff_dma_ops;
-
-       return 0;
-}
-
-static const struct ide_port_ops ali_port_ops = {
-       .set_pio_mode           = ali_set_pio_mode,
-       .set_dma_mode           = ali_set_dma_mode,
-       .udma_filter            = ali_udma_filter,
-       .cable_detect           = ali_cable_detect,
-};
-
-static const struct ide_dma_ops ali_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ali15x3_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_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info ali15x3_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_chipset   = init_chipset_ali15x3,
-       .init_hwif      = init_hwif_ali15x3,
-       .init_dma       = init_dma_ali15x3,
-       .port_ops       = &ali_port_ops,
-       .pio_mask       = ATA_PIO5,
-       .swdma_mask     = ATA_SWDMA2,
-       .mwdma_mask     = ATA_MWDMA2,
-};
-
-/**
- *     alim15x3_init_one       -       set up an ALi15x3 IDE controller
- *     @dev: PCI device to set up
- *
- *     Perform the actual set up for an ALi15x3 that has been found by the
- *     hot plug layer.
- */
-static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d = ali15x3_chipset;
-       u8 rev = dev->revision, idx = id->driver_data;
-
-       /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
-       if (rev <= 0xC4)
-               d.host_flags |= IDE_HFLAG_NO_LBA48_DMA;
-
-       if (rev >= 0x20) {
-               if (rev == 0x20)
-                       d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
-
-               if (rev < 0xC2)
-                       d.udma_mask = ATA_UDMA2;
-               else if (rev == 0xC2 || rev == 0xC3)
-                       d.udma_mask = ATA_UDMA4;
-               else if (rev == 0xC4)
-                       d.udma_mask = ATA_UDMA5;
-               else
-                       d.udma_mask = ATA_UDMA6;
-
-               d.dma_ops = &ali_dma_ops;
-       } else {
-               d.host_flags |= IDE_HFLAG_NO_DMA;
-
-               d.mwdma_mask = d.swdma_mask = 0;
-       }
-
-       if (idx == 0)
-               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-
-static const struct pci_device_id alim15x3_pci_tbl[] = {
-       { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
-       { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
-
-static struct pci_driver alim15x3_pci_driver = {
-       .name           = "ALI15x3_IDE",
-       .id_table       = alim15x3_pci_tbl,
-       .probe          = alim15x3_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init ali15x3_ide_init(void)
-{
-       return ide_pci_register_driver(&alim15x3_pci_driver);
-}
-
-static void __exit ali15x3_ide_exit(void)
-{
-       return pci_unregister_driver(&alim15x3_pci_driver);
-}
-
-module_init(ali15x3_ide_init);
-module_exit(ali15x3_ide_exit);
-
-MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
deleted file mode 100644 (file)
index 81ec731..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
- * IDE driver for Linux.
- *
- * Copyright (c) 2000-2002 Vojtech Pavlik
- * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
- *
- * Based on the work of:
- *      Andre Hedrick
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#define DRV_NAME "amd74xx"
-
-enum {
-       AMD_IDE_CONFIG          = 0x41,
-       AMD_CABLE_DETECT        = 0x42,
-       AMD_DRIVE_TIMING        = 0x48,
-       AMD_8BIT_TIMING         = 0x4e,
-       AMD_ADDRESS_SETUP       = 0x4c,
-       AMD_UDMA_TIMING         = 0x50,
-};
-
-static unsigned int amd_80w;
-static unsigned int amd_clock;
-
-static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
-static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
-
-static inline u8 amd_offset(struct pci_dev *dev)
-{
-       return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
-}
-
-/*
- * amd_set_speed() writes timing values to the chipset registers
- */
-
-static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
-                         struct ide_timing *timing)
-{
-       u8 t = 0, offset = amd_offset(dev);
-
-       pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
-       t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
-       pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
-
-       pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
-               ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
-
-       pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
-               ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
-
-       switch (udma_mask) {
-       case ATA_UDMA2: t = timing->udma ? (0xc0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
-       case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 2, 10)]) : 0x03; break;
-       case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 10)]) : 0x03; break;
-       case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[clamp_val(timing->udma, 1, 15)]) : 0x03; break;
-       default: return;
-       }
-
-       pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
-}
-
-/*
- * amd_set_drive() computes timing values and configures the chipset
- * to a desired transfer mode.  It also can be called by upper layers.
- */
-
-static void amd_set_drive(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
-       struct ide_timing t, p;
-       int T, UT;
-       u8 udma_mask = hwif->ultra_mask;
-
-       T = 1000000000 / amd_clock;
-       UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
-
-       ide_timing_compute(drive, speed, &t, T, UT);
-
-       if (peer->dev_flags & IDE_DFLAG_PRESENT) {
-               ide_timing_compute(peer, peer->current_speed, &p, T, UT);
-               ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
-       }
-
-       if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
-       if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
-
-       amd_set_speed(dev, drive->dn, udma_mask, &t);
-}
-
-/*
- * amd_set_pio_mode() is a callback from upper layers for PIO-only tuning.
- */
-
-static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       amd_set_drive(drive, XFER_PIO_0 + pio);
-}
-
-static void amd7409_cable_detect(struct pci_dev *dev)
-{
-       /* no host side cable detection */
-       amd_80w = 0x03;
-}
-
-static void amd7411_cable_detect(struct pci_dev *dev)
-{
-       int i;
-       u32 u = 0;
-       u8 t = 0, offset = amd_offset(dev);
-
-       pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
-       pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
-       amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
-       for (i = 24; i >= 0; i -= 8)
-               if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
-                       printk(KERN_WARNING DRV_NAME " %s: BIOS didn't set "
-                               "cable bits correctly. Enabling workaround.\n",
-                               pci_name(dev));
-                       amd_80w |= (1 << (1 - (i >> 4)));
-               }
-}
-
-/*
- * The initialization callback.  Initialize drive independent registers.
- */
-
-static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
-{
-       u8 t = 0, offset = amd_offset(dev);
-
-/*
- * Check 80-wire cable presence.
- */
-
-       if (dev->vendor == PCI_VENDOR_ID_AMD &&
-           dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
-               ; /* no UDMA > 2 */
-       else if (dev->vendor == PCI_VENDOR_ID_AMD &&
-                dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
-               amd7409_cable_detect(dev);
-       else
-               amd7411_cable_detect(dev);
-
-/*
- * Take care of prefetch & postwrite.
- */
-
-       pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
-       /*
-        * Check for broken FIFO support.
-        */
-       if (dev->vendor == PCI_VENDOR_ID_AMD &&
-           dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
-               t &= 0x0f;
-       else
-               t |= 0xf0;
-       pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
-
-       return dev->irq;
-}
-
-static u8 amd_cable_detect(ide_hwif_t *hwif)
-{
-       if ((amd_80w >> hwif->channel) & 1)
-               return ATA_CBL_PATA80;
-       else
-               return ATA_CBL_PATA40;
-}
-
-static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       if (hwif->irq == 0) /* 0 is bogus but will do for now */
-               hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
-}
-
-static const struct ide_port_ops amd_port_ops = {
-       .set_pio_mode           = amd_set_pio_mode,
-       .set_dma_mode           = amd_set_drive,
-       .cable_detect           = amd_cable_detect,
-};
-
-#define IDE_HFLAGS_AMD \
-       (IDE_HFLAG_PIO_NO_BLACKLIST | \
-        IDE_HFLAG_POST_SET_MODE | \
-        IDE_HFLAG_IO_32BIT | \
-        IDE_HFLAG_UNMASK_IRQS)
-
-#define DECLARE_AMD_DEV(swdma, udma)                           \
-       {                                                               \
-               .name           = DRV_NAME,                             \
-               .init_chipset   = init_chipset_amd74xx,                 \
-               .init_hwif      = init_hwif_amd74xx,                    \
-               .enablebits     = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
-               .port_ops       = &amd_port_ops,                        \
-               .host_flags     = IDE_HFLAGS_AMD,                       \
-               .pio_mask       = ATA_PIO5,                             \
-               .swdma_mask     = swdma,                                \
-               .mwdma_mask     = ATA_MWDMA2,                           \
-               .udma_mask      = udma,                                 \
-       }
-
-#define DECLARE_NV_DEV(udma)                                   \
-       {                                                               \
-               .name           = DRV_NAME,                             \
-               .init_chipset   = init_chipset_amd74xx,                 \
-               .init_hwif      = init_hwif_amd74xx,                    \
-               .enablebits     = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
-               .port_ops       = &amd_port_ops,                        \
-               .host_flags     = IDE_HFLAGS_AMD,                       \
-               .pio_mask       = ATA_PIO5,                             \
-               .swdma_mask     = ATA_SWDMA2,                           \
-               .mwdma_mask     = ATA_MWDMA2,                           \
-               .udma_mask      = udma,                                 \
-       }
-
-static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
-       /* 0: AMD7401 */        DECLARE_AMD_DEV(0x00, ATA_UDMA2),
-       /* 1: AMD7409 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
-       /* 2: AMD7411/7441 */   DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
-       /* 3: AMD8111 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6),
-
-       /* 4: NFORCE */         DECLARE_NV_DEV(ATA_UDMA5),
-       /* 5: >= NFORCE2 */     DECLARE_NV_DEV(ATA_UDMA6),
-
-       /* 6: AMD5536 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
-};
-
-static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d;
-       u8 idx = id->driver_data;
-
-       d = amd74xx_chipsets[idx];
-
-       /*
-        * Check for bad SWDMA and incorrectly wired Serenade mainboards.
-        */
-       if (idx == 1) {
-               if (dev->revision <= 7)
-                       d.swdma_mask = 0;
-               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-       } else if (idx == 3) {
-               if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
-                   dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
-                       d.udma_mask = ATA_UDMA5;
-       }
-
-       printk(KERN_INFO "%s %s: UDMA%s controller\n",
-               d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
-
-       /*
-       * Determine the system bus clock.
-       */
-       amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
-
-       switch (amd_clock) {
-       case 33000: amd_clock = 33333; break;
-       case 37000: amd_clock = 37500; break;
-       case 41000: amd_clock = 41666; break;
-       }
-
-       if (amd_clock < 20000 || amd_clock > 50000) {
-               printk(KERN_WARNING "%s: User given PCI clock speed impossible"
-                                   " (%d), using 33 MHz instead.\n",
-                                   d.name, amd_clock);
-               amd_clock = 33333;
-       }
-
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-static const struct pci_device_id amd74xx_pci_tbl[] = {
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_COBRA_7401),           0 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_VIPER_7409),           1 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_VIPER_7411),           2 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_OPUS_7441),            2 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_8111_IDE),             3 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_IDE),        4 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE),       5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE),      5 },
-#ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA),     5 },
-#endif
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE),       5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE),      5 },
-#ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA),     5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2),    5 },
-#endif
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE),  5 },
-       { PCI_VDEVICE(NVIDIA,   PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE),  5 },
-       { PCI_VDEVICE(AMD,      PCI_DEVICE_ID_AMD_CS5536_IDE),           6 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
-
-static struct pci_driver amd74xx_pci_driver = {
-       .name           = "AMD_IDE",
-       .id_table       = amd74xx_pci_tbl,
-       .probe          = amd74xx_probe,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init amd74xx_ide_init(void)
-{
-       return ide_pci_register_driver(&amd74xx_pci_driver);
-}
-
-static void __exit amd74xx_ide_exit(void)
-{
-       pci_unregister_driver(&amd74xx_pci_driver);
-}
-
-module_init(amd74xx_ide_init);
-module_exit(amd74xx_ide_exit);
-
-MODULE_AUTHOR("Vojtech Pavlik");
-MODULE_DESCRIPTION("AMD PCI IDE driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
deleted file mode 100644 (file)
index b2735d2..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- *  Copyright (C) 2003 ATI Inc. <hyu@ati.com>
- *  Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "atiixp"
-
-#define ATIIXP_IDE_PIO_TIMING          0x40
-#define ATIIXP_IDE_MDMA_TIMING         0x44
-#define ATIIXP_IDE_PIO_CONTROL         0x48
-#define ATIIXP_IDE_PIO_MODE            0x4a
-#define ATIIXP_IDE_UDMA_CONTROL                0x54
-#define ATIIXP_IDE_UDMA_MODE           0x56
-
-typedef struct {
-       u8 command_width;
-       u8 recover_width;
-} atiixp_ide_timing;
-
-static atiixp_ide_timing pio_timing[] = {
-       { 0x05, 0x0d },
-       { 0x04, 0x07 },
-       { 0x03, 0x04 },
-       { 0x02, 0x02 },
-       { 0x02, 0x00 },
-};
-
-static atiixp_ide_timing mdma_timing[] = {
-       { 0x07, 0x07 },
-       { 0x02, 0x01 },
-       { 0x02, 0x00 },
-};
-
-static DEFINE_SPINLOCK(atiixp_lock);
-
-/**
- *     atiixp_set_pio_mode     -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Set the interface PIO mode.
- */
-
-static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       unsigned long flags;
-       int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
-       u32 pio_timing_data;
-       u16 pio_mode_data;
-
-       spin_lock_irqsave(&atiixp_lock, flags);
-
-       pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
-       pio_mode_data &= ~(0x07 << (drive->dn * 4));
-       pio_mode_data |= (pio << (drive->dn * 4));
-       pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
-
-       pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
-       pio_timing_data &= ~(0xff << timing_shift);
-       pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) |
-                (pio_timing[pio].command_width << (timing_shift + 4));
-       pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
-
-       spin_unlock_irqrestore(&atiixp_lock, flags);
-}
-
-/**
- *     atiixp_set_dma_mode     -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Set a ATIIXP host controller to the desired DMA mode.  This involves
- *     programming the right timing data into the PCI configuration space.
- */
-
-static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       unsigned long flags;
-       int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
-       u32 tmp32;
-       u16 tmp16;
-       u16 udma_ctl = 0;
-
-       spin_lock_irqsave(&atiixp_lock, flags);
-
-       pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl);
-
-       if (speed >= XFER_UDMA_0) {
-               pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
-               tmp16 &= ~(0x07 << (drive->dn * 4));
-               tmp16 |= ((speed & 0x07) << (drive->dn * 4));
-               pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
-
-               udma_ctl |= (1 << drive->dn);
-       } else if (speed >= XFER_MW_DMA_0) {
-               u8 i = speed & 0x03;
-
-               pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
-               tmp32 &= ~(0xff << timing_shift);
-               tmp32 |= (mdma_timing[i].recover_width << timing_shift) |
-                        (mdma_timing[i].command_width << (timing_shift + 4));
-               pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
-
-               udma_ctl &= ~(1 << drive->dn);
-       }
-
-       pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl);
-
-       spin_unlock_irqrestore(&atiixp_lock, flags);
-}
-
-static u8 atiixp_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       u8 udma_mode = 0, ch = hwif->channel;
-
-       pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
-
-       if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
-               return ATA_CBL_PATA80;
-       else
-               return ATA_CBL_PATA40;
-}
-
-static const struct ide_port_ops atiixp_port_ops = {
-       .set_pio_mode           = atiixp_set_pio_mode,
-       .set_dma_mode           = atiixp_set_dma_mode,
-       .cable_detect           = atiixp_cable_detect,
-};
-
-static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
-       {       /* 0: IXP200/300/400/700 */
-               .name           = DRV_NAME,
-               .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
-               .port_ops       = &atiixp_port_ops,
-               .host_flags     = IDE_HFLAG_LEGACY_IRQS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       },
-       {       /* 1: IXP600 */
-               .name           = DRV_NAME,
-               .enablebits     = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
-               .port_ops       = &atiixp_port_ops,
-               .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       },
-};
-
-/**
- *     atiixp_init_one -       called when a ATIIXP is found
- *     @dev: the atiixp device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-
-static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
-}
-
-static const struct pci_device_id atiixp_pci_tbl[] = {
-       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), 0 },
-       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), 0 },
-       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 },
-       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 },
-       { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
-
-static struct pci_driver atiixp_pci_driver = {
-       .name           = "ATIIXP_IDE",
-       .id_table       = atiixp_pci_tbl,
-       .probe          = atiixp_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init atiixp_ide_init(void)
-{
-       return ide_pci_register_driver(&atiixp_pci_driver);
-}
-
-static void __exit atiixp_ide_exit(void)
-{
-       pci_unregister_driver(&atiixp_pci_driver);
-}
-
-module_init(atiixp_ide_init);
-module_exit(atiixp_ide_exit);
-
-MODULE_AUTHOR("HUI YU");
-MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
deleted file mode 100644 (file)
index e430664..0000000
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
- */
-
-/*
- *  Original authors:  abramov@cecmow.enet.dec.com (Igor Abramov)
- *                     mlord@pobox.com (Mark Lord)
- *
- *  See linux/MAINTAINERS for address of current maintainer.
- *
- *  This file provides support for the advanced features and bugs
- *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
- *
- *  These chips are basically fucked by design, and getting this driver
- *  to work on every motherboard design that uses this screwed chip seems
- *  bloody well impossible.  However, we're still trying.
- *
- *  Version 0.97 worked for everybody.
- *
- *  User feedback is essential.  Many thanks to the beta test team:
- *
- *  A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com,
- *  bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz,
- *  chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de,
- *  derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de,
- *  flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net,
- *  j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net,
- *  kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu,
- *  peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com,
- *  s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net,
- *  steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com
- *  liug@mama.indstate.edu, and others.
- *
- *  Version 0.01       Initial version, hacked out of ide.c,
- *                     and #include'd rather than compiled separately.
- *                     This will get cleaned up in a subsequent release.
- *
- *  Version 0.02       Fixes for vlb initialization code, enable prefetch
- *                     for versions 'B' and 'C' of chip by default,
- *                     some code cleanup.
- *
- *  Version 0.03       Added reset of secondary interface,
- *                     and black list for devices which are not compatible
- *                     with prefetch mode. Separate function for setting
- *                     prefetch is added, possibly it will be called some
- *                     day from ioctl processing code.
- *
- *  Version 0.04       Now configs/compiles separate from ide.c
- *
- *  Version 0.05       Major rewrite of interface timing code.
- *                     Added new function cmd640_set_mode to set PIO mode
- *                     from ioctl call. New drives added to black list.
- *
- *  Version 0.06       More code cleanup. Prefetch is enabled only for
- *                     detected hard drives, not included in prefetch
- *                     black list.
- *
- *  Version 0.07       Changed to more conservative drive tuning policy.
- *                     Unknown drives, which report PIO < 4 are set to
- *                     (reported_PIO - 1) if it is supported, or to PIO0.
- *                     List of known drives extended by info provided by
- *                     CMD at their ftp site.
- *
- *  Version 0.08       Added autotune/noautotune support.
- *
- *  Version 0.09       Try to be smarter about 2nd port enabling.
- *  Version 0.10       Be nice and don't reset 2nd port.
- *  Version 0.11       Try to handle more weird situations.
- *
- *  Version 0.12       Lots of bug fixes from Laszlo Peter
- *                     irq unmasking disabled for reliability.
- *                     try to be even smarter about the second port.
- *                     tidy up source code formatting.
- *  Version 0.13       permit irq unmasking again.
- *  Version 0.90       massive code cleanup, some bugs fixed.
- *                     defaults all drives to PIO mode0, prefetch off.
- *                     autotune is OFF by default, with compile time flag.
- *                     prefetch can be turned OFF/ON using "hdparm -p8/-p9"
- *                      (requires hdparm-3.1 or newer)
- *  Version 0.91       first release to linux-kernel list.
- *  Version 0.92       move initial reg dump to separate callable function
- *                     change "readahead" to "prefetch" to avoid confusion
- *  Version 0.95       respect original BIOS timings unless autotuning.
- *                     tons of code cleanup and rearrangement.
- *                     added CONFIG_BLK_DEV_CMD640_ENHANCED option
- *                     prevent use of unmask when prefetch is on
- *  Version 0.96       prevent use of io_32bit when prefetch is off
- *  Version 0.97       fix VLB secondary interface for sjd@slip.net
- *                     other minor tune-ups:  0.96 was very good.
- *  Version 0.98       ignore PCI version when disabled by BIOS
- *  Version 0.99       display setup/active/recovery clocks with PIO mode
- *  Version 1.00       Mmm.. cannot depend on PCMD_ENA in all systems
- *  Version 1.01       slow/fast devsel can be selected with "hdparm -p6/-p7"
- *                      ("fast" is necessary for 32bit I/O in some systems)
- *  Version 1.02       fix bug that resulted in slow "setup times"
- *                      (patch courtesy of Zoltan Hidvegi)
- */
-
-#define CMD640_PREFETCH_MASKS 1
-
-/*#define CMD640_DUMP_REGS */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "cmd640"
-
-static int cmd640_vlb;
-
-/*
- * CMD640 specific registers definition.
- */
-
-#define VID            0x00
-#define DID            0x02
-#define PCMD           0x04
-#define   PCMD_ENA     0x01
-#define PSTTS          0x06
-#define REVID          0x08
-#define PROGIF         0x09
-#define SUBCL          0x0a
-#define BASCL          0x0b
-#define BaseA0         0x10
-#define BaseA1         0x14
-#define BaseA2         0x18
-#define BaseA3         0x1c
-#define INTLINE                0x3c
-#define INPINE         0x3d
-
-#define        CFR             0x50
-#define   CFR_DEVREV           0x03
-#define   CFR_IDE01INTR                0x04
-#define          CFR_DEVID             0x18
-#define          CFR_AT_VESA_078h      0x20
-#define          CFR_DSA1              0x40
-#define          CFR_DSA0              0x80
-
-#define CNTRL          0x51
-#define          CNTRL_DIS_RA0         0x40
-#define   CNTRL_DIS_RA1                0x80
-#define          CNTRL_ENA_2ND         0x08
-
-#define        CMDTIM          0x52
-#define        ARTTIM0         0x53
-#define        DRWTIM0         0x54
-#define ARTTIM1        0x55
-#define DRWTIM1                0x56
-#define ARTTIM23       0x57
-#define   ARTTIM23_DIS_RA2     0x04
-#define   ARTTIM23_DIS_RA3     0x08
-#define DRWTIM23       0x58
-#define BRST           0x59
-
-/*
- * Registers and masks for easy access by drive index:
- */
-static u8 prefetch_regs[4]  = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
-static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3};
-
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-
-static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
-static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23};
-
-/*
- * Current cmd640 timing values for each drive.
- * The defaults for each are the slowest possible timings.
- */
-static u8 setup_counts[4]    = {4, 4, 4, 4};     /* Address setup count (in clocks) */
-static u8 active_counts[4]   = {16, 16, 16, 16}; /* Active count   (encoded) */
-static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
-
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-
-static DEFINE_SPINLOCK(cmd640_lock);
-
-/*
- * Interface to access cmd640x registers
- */
-static unsigned int cmd640_key;
-static void (*__put_cmd640_reg)(u16 reg, u8 val);
-static u8 (*__get_cmd640_reg)(u16 reg);
-
-/*
- * This is read from the CFR reg, and is used in several places.
- */
-static unsigned int cmd640_chip_version;
-
-/*
- * The CMD640x chip does not support DWORD config write cycles, but some
- * of the BIOSes use them to implement the config services.
- * Therefore, we must use direct IO instead.
- */
-
-/* PCI method 1 access */
-
-static void put_cmd640_reg_pci1(u16 reg, u8 val)
-{
-       outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
-       outb_p(val, (reg & 3) | 0xcfc);
-}
-
-static u8 get_cmd640_reg_pci1(u16 reg)
-{
-       outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
-       return inb_p((reg & 3) | 0xcfc);
-}
-
-/* PCI method 2 access (from CMD datasheet) */
-
-static void put_cmd640_reg_pci2(u16 reg, u8 val)
-{
-       outb_p(0x10, 0xcf8);
-       outb_p(val, cmd640_key + reg);
-       outb_p(0, 0xcf8);
-}
-
-static u8 get_cmd640_reg_pci2(u16 reg)
-{
-       u8 b;
-
-       outb_p(0x10, 0xcf8);
-       b = inb_p(cmd640_key + reg);
-       outb_p(0, 0xcf8);
-       return b;
-}
-
-/* VLB access */
-
-static void put_cmd640_reg_vlb(u16 reg, u8 val)
-{
-       outb_p(reg, cmd640_key);
-       outb_p(val, cmd640_key + 4);
-}
-
-static u8 get_cmd640_reg_vlb(u16 reg)
-{
-       outb_p(reg, cmd640_key);
-       return inb_p(cmd640_key + 4);
-}
-
-static u8 get_cmd640_reg(u16 reg)
-{
-       unsigned long flags;
-       u8 b;
-
-       spin_lock_irqsave(&cmd640_lock, flags);
-       b = __get_cmd640_reg(reg);
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-       return b;
-}
-
-static void put_cmd640_reg(u16 reg, u8 val)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cmd640_lock, flags);
-       __put_cmd640_reg(reg, val);
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-}
-
-static int __init match_pci_cmd640_device(void)
-{
-       const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
-       unsigned int i;
-       for (i = 0; i < 4; i++) {
-               if (get_cmd640_reg(i) != ven_dev[i])
-                       return 0;
-       }
-#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT
-       if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
-               printk("ide: cmd640 on PCI disabled by BIOS\n");
-               return 0;
-       }
-#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */
-       return 1; /* success */
-}
-
-/*
- * Probe for CMD640x -- pci method 1
- */
-static int __init probe_for_cmd640_pci1(void)
-{
-       __get_cmd640_reg = get_cmd640_reg_pci1;
-       __put_cmd640_reg = put_cmd640_reg_pci1;
-       for (cmd640_key = 0x80000000;
-            cmd640_key <= 0x8000f800;
-            cmd640_key += 0x800) {
-               if (match_pci_cmd640_device())
-                       return 1; /* success */
-       }
-       return 0;
-}
-
-/*
- * Probe for CMD640x -- pci method 2
- */
-static int __init probe_for_cmd640_pci2(void)
-{
-       __get_cmd640_reg = get_cmd640_reg_pci2;
-       __put_cmd640_reg = put_cmd640_reg_pci2;
-       for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) {
-               if (match_pci_cmd640_device())
-                       return 1; /* success */
-       }
-       return 0;
-}
-
-/*
- * Probe for CMD640x -- vlb
- */
-static int __init probe_for_cmd640_vlb(void)
-{
-       u8 b;
-
-       __get_cmd640_reg = get_cmd640_reg_vlb;
-       __put_cmd640_reg = put_cmd640_reg_vlb;
-       cmd640_key = 0x178;
-       b = get_cmd640_reg(CFR);
-       if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) {
-               cmd640_key = 0x78;
-               b = get_cmd640_reg(CFR);
-               if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h))
-                       return 0;
-       }
-       return 1; /* success */
-}
-
-/*
- *  Returns 1 if an IDE interface/drive exists at 0x170,
- *  Returns 0 otherwise.
- */
-static int __init secondary_port_responding(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cmd640_lock, flags);
-
-       outb_p(0x0a, 0x176);    /* select drive0 */
-       udelay(100);
-       if ((inb_p(0x176) & 0x1f) != 0x0a) {
-               outb_p(0x1a, 0x176); /* select drive1 */
-               udelay(100);
-               if ((inb_p(0x176) & 0x1f) != 0x1a) {
-                       spin_unlock_irqrestore(&cmd640_lock, flags);
-                       return 0; /* nothing responded */
-               }
-       }
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-       return 1; /* success */
-}
-
-#ifdef CMD640_DUMP_REGS
-/*
- * Dump out all cmd640 registers.  May be called from ide.c
- */
-static void cmd640_dump_regs(void)
-{
-       unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
-
-       /* Dump current state of chip registers */
-       printk("ide: cmd640 internal register dump:");
-       for (; reg <= 0x59; reg++) {
-               if (!(reg & 0x0f))
-                       printk("\n%04x:", reg);
-               printk(" %02x", get_cmd640_reg(reg));
-       }
-       printk("\n");
-}
-#endif
-
-static void __set_prefetch_mode(ide_drive_t *drive, int mode)
-{
-       if (mode) {     /* want prefetch on? */
-#if CMD640_PREFETCH_MASKS
-               drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
-               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
-#endif
-               drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
-       } else {
-               drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
-               drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
-               drive->io_32bit = 0;
-       }
-}
-
-#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED
-/*
- * Check whether prefetch is on for a drive,
- * and initialize the unmask flags for safe operation.
- */
-static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
-{
-       u8 b = get_cmd640_reg(prefetch_regs[index]);
-
-       __set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 1);
-}
-#else
-
-/*
- * Sets prefetch mode for a drive.
- */
-static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
-{
-       unsigned long flags;
-       int reg = prefetch_regs[index];
-       u8 b;
-
-       spin_lock_irqsave(&cmd640_lock, flags);
-       b = __get_cmd640_reg(reg);
-       __set_prefetch_mode(drive, mode);
-       if (mode)
-               b &= ~prefetch_masks[index];    /* enable prefetch */
-       else
-               b |= prefetch_masks[index];     /* disable prefetch */
-       __put_cmd640_reg(reg, b);
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-}
-
-/*
- * Dump out current drive clocks settings
- */
-static void display_clocks(unsigned int index)
-{
-       u8 active_count, recovery_count;
-
-       active_count = active_counts[index];
-       if (active_count == 1)
-               ++active_count;
-       recovery_count = recovery_counts[index];
-       if (active_count > 3 && recovery_count == 1)
-               ++recovery_count;
-       if (cmd640_chip_version > 1)
-               recovery_count += 1;  /* cmd640b uses (count + 1)*/
-       printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count);
-}
-
-/*
- * Pack active and recovery counts into single byte representation
- * used by controller
- */
-static inline u8 pack_nibbles(u8 upper, u8 lower)
-{
-       return ((upper & 0x0f) << 4) | (lower & 0x0f);
-}
-
-/*
- * This routine writes the prepared setup/active/recovery counts
- * for a drive into the cmd640 chipset registers to active them.
- */
-static void program_drive_counts(ide_drive_t *drive, unsigned int index)
-{
-       unsigned long flags;
-       u8 setup_count    = setup_counts[index];
-       u8 active_count   = active_counts[index];
-       u8 recovery_count = recovery_counts[index];
-
-       /*
-        * Set up address setup count and drive read/write timing registers.
-        * Primary interface has individual count/timing registers for
-        * each drive.  Secondary interface has one common set of registers,
-        * so we merge the timings, using the slowest value for each timing.
-        */
-       if (index > 1) {
-               ide_hwif_t *hwif = drive->hwif;
-               ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
-               unsigned int mate = index ^ 1;
-
-               if (peer->dev_flags & IDE_DFLAG_PRESENT) {
-                       if (setup_count < setup_counts[mate])
-                               setup_count = setup_counts[mate];
-                       if (active_count < active_counts[mate])
-                               active_count = active_counts[mate];
-                       if (recovery_count < recovery_counts[mate])
-                               recovery_count = recovery_counts[mate];
-               }
-       }
-
-       /*
-        * Convert setup_count to internal chipset representation
-        */
-       switch (setup_count) {
-       case 4:  setup_count = 0x00; break;
-       case 3:  setup_count = 0x80; break;
-       case 1:
-       case 2:  setup_count = 0x40; break;
-       default: setup_count = 0xc0; /* case 5 */
-       }
-
-       /*
-        * Now that everything is ready, program the new timings
-        */
-       spin_lock_irqsave(&cmd640_lock, flags);
-       /*
-        * Program the address_setup clocks into ARTTIM reg,
-        * and then the active/recovery counts into the DRWTIM reg
-        * (this converts counts of 16 into counts of zero -- okay).
-        */
-       setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
-       __put_cmd640_reg(arttim_regs[index], setup_count);
-       __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-}
-
-/*
- * Set a specific pio_mode for a drive
- */
-static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
-                           u8 pio_mode, unsigned int cycle_time)
-{
-       struct ide_timing *t;
-       int setup_time, active_time, recovery_time, clock_time;
-       u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
-       int bus_speed;
-
-       if (cmd640_vlb)
-               bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
-       else
-               bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-
-       if (pio_mode > 5)
-               pio_mode = 5;
-
-       t = ide_timing_find_mode(XFER_PIO_0 + pio_mode);
-       setup_time  = t->setup;
-       active_time = t->active;
-
-       recovery_time = cycle_time - (setup_time + active_time);
-       clock_time = 1000 / bus_speed;
-       cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
-
-       setup_count = DIV_ROUND_UP(setup_time, clock_time);
-
-       active_count = DIV_ROUND_UP(active_time, clock_time);
-       if (active_count < 2)
-               active_count = 2; /* minimum allowed by cmd640 */
-
-       recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
-       recovery_count2 = cycle_count - (setup_count + active_count);
-       if (recovery_count2 > recovery_count)
-               recovery_count = recovery_count2;
-       if (recovery_count < 2)
-               recovery_count = 2; /* minimum allowed by cmd640 */
-       if (recovery_count > 17) {
-               active_count += recovery_count - 17;
-               recovery_count = 17;
-       }
-       if (active_count > 16)
-               active_count = 16; /* maximum allowed by cmd640 */
-       if (cmd640_chip_version > 1)
-               recovery_count -= 1;  /* cmd640b uses (count + 1)*/
-       if (recovery_count > 16)
-               recovery_count = 16; /* maximum allowed by cmd640 */
-
-       setup_counts[index]    = setup_count;
-       active_counts[index]   = active_count;
-       recovery_counts[index] = recovery_count;
-
-       /*
-        * In a perfect world, we might set the drive pio mode here
-        * (using WIN_SETFEATURE) before continuing.
-        *
-        * But we do not, because:
-        *      1) this is the wrong place to do it (proper is do_special() in ide.c)
-        *      2) in practice this is rarely, if ever, necessary
-        */
-       program_drive_counts(drive, index);
-}
-
-static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       unsigned int index = 0, cycle_time;
-       u8 b;
-
-       switch (pio) {
-       case 6: /* set fast-devsel off */
-       case 7: /* set fast-devsel on */
-               b = get_cmd640_reg(CNTRL) & ~0x27;
-               if (pio & 1)
-                       b |= 0x27;
-               put_cmd640_reg(CNTRL, b);
-               printk("%s: %sabled cmd640 fast host timing (devsel)\n",
-                       drive->name, (pio & 1) ? "en" : "dis");
-               return;
-       case 8: /* set prefetch off */
-       case 9: /* set prefetch on */
-               set_prefetch_mode(drive, index, pio & 1);
-               printk("%s: %sabled cmd640 prefetch\n",
-                       drive->name, (pio & 1) ? "en" : "dis");
-               return;
-       }
-
-       cycle_time = ide_pio_cycle_time(drive, pio);
-       cmd640_set_mode(drive, index, pio, cycle_time);
-
-       printk("%s: selected cmd640 PIO mode%d (%dns)",
-               drive->name, pio, cycle_time);
-
-       display_clocks(index);
-}
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-
-static void cmd640_init_dev(ide_drive_t *drive)
-{
-       unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
-
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-       /*
-        * Reset timing to the slowest speed and turn off prefetch.
-        * This way, the drive identify code has a better chance.
-        */
-       setup_counts[i]    =  4;        /* max possible */
-       active_counts[i]   = 16;        /* max possible */
-       recovery_counts[i] = 16;        /* max possible */
-       program_drive_counts(drive, i);
-       set_prefetch_mode(drive, i, 0);
-       printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i);
-#else
-       /*
-        * Set the drive unmask flags to match the prefetch setting.
-        */
-       check_prefetch(drive, i);
-       printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
-               i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on");
-#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-}
-
-
-static const struct ide_port_ops cmd640_port_ops = {
-       .init_dev               = cmd640_init_dev,
-#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-       .set_pio_mode           = cmd640_set_pio_mode,
-#endif
-};
-
-static int pci_conf1(void)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&cmd640_lock, flags);
-       outb(0x01, 0xCFB);
-       tmp = inl(0xCF8);
-       outl(0x80000000, 0xCF8);
-       if (inl(0xCF8) == 0x80000000) {
-               outl(tmp, 0xCF8);
-               spin_unlock_irqrestore(&cmd640_lock, flags);
-               return 1;
-       }
-       outl(tmp, 0xCF8);
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-       return 0;
-}
-
-static int pci_conf2(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cmd640_lock, flags);
-       outb(0x00, 0xCFB);
-       outb(0x00, 0xCF8);
-       outb(0x00, 0xCFA);
-       if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) {
-               spin_unlock_irqrestore(&cmd640_lock, flags);
-               return 1;
-       }
-       spin_unlock_irqrestore(&cmd640_lock, flags);
-       return 0;
-}
-
-static const struct ide_port_info cmd640_port_info __initdata = {
-       .chipset                = ide_cmd640,
-       .host_flags             = IDE_HFLAG_SERIALIZE |
-                                 IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAG_ABUSE_PREFETCH |
-                                 IDE_HFLAG_ABUSE_FAST_DEVSEL,
-       .port_ops               = &cmd640_port_ops,
-       .pio_mask               = ATA_PIO5,
-};
-
-static int cmd640x_init_one(unsigned long base, unsigned long ctl)
-{
-       if (!request_region(base, 8, DRV_NAME)) {
-               printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
-                               DRV_NAME, base, base + 7);
-               return -EBUSY;
-       }
-
-       if (!request_region(ctl, 1, DRV_NAME)) {
-               printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
-                               DRV_NAME, ctl);
-               release_region(base, 8);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-/*
- * Probe for a cmd640 chipset, and initialize it if found.
- */
-static int __init cmd640x_init(void)
-{
-       int second_port_cmd640 = 0, rc;
-       const char *bus_type, *port2;
-       u8 b, cfr;
-       hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
-
-       if (cmd640_vlb && probe_for_cmd640_vlb()) {
-               bus_type = "VLB";
-       } else {
-               cmd640_vlb = 0;
-               /* Find out what kind of PCI probing is supported otherwise
-                  Justin Gibbs will sulk.. */
-               if (pci_conf1() && probe_for_cmd640_pci1())
-                       bus_type = "PCI (type1)";
-               else if (pci_conf2() && probe_for_cmd640_pci2())
-                       bus_type = "PCI (type2)";
-               else
-                       return 0;
-       }
-       /*
-        * Undocumented magic (there is no 0x5b reg in specs)
-        */
-       put_cmd640_reg(0x5b, 0xbd);
-       if (get_cmd640_reg(0x5b) != 0xbd) {
-               printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n");
-               return 0;
-       }
-       put_cmd640_reg(0x5b, 0);
-
-#ifdef CMD640_DUMP_REGS
-       cmd640_dump_regs();
-#endif
-
-       /*
-        * Documented magic begins here
-        */
-       cfr = get_cmd640_reg(CFR);
-       cmd640_chip_version = cfr & CFR_DEVREV;
-       if (cmd640_chip_version == 0) {
-               printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
-               return 0;
-       }
-
-       rc = cmd640x_init_one(0x1f0, 0x3f6);
-       if (rc)
-               return rc;
-
-       rc = cmd640x_init_one(0x170, 0x376);
-       if (rc) {
-               release_region(0x3f6, 1);
-               release_region(0x1f0, 8);
-               return rc;
-       }
-
-       memset(&hw, 0, sizeof(hw));
-
-       ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
-       hw[0].irq = 14;
-       hw[0].chipset = ide_cmd640;
-
-       ide_std_init_ports(&hw[1], 0x170, 0x376);
-       hw[1].irq = 15;
-       hw[1].chipset = ide_cmd640;
-
-       printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
-                        "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
-
-       /*
-        * Initialize data for primary port
-        */
-       hws[0] = &hw[0];
-
-       /*
-        * Ensure compatibility by always using the slowest timings
-        * for access to the drive's command register block,
-        * and reset the prefetch burstsize to default (512 bytes).
-        *
-        * Maybe we need a way to NOT do these on *some* systems?
-        */
-       put_cmd640_reg(CMDTIM, 0);
-       put_cmd640_reg(BRST, 0x40);
-
-       b = get_cmd640_reg(CNTRL);
-
-       /*
-        * Try to enable the secondary interface, if not already enabled
-        */
-       if (secondary_port_responding()) {
-               if ((b & CNTRL_ENA_2ND)) {
-                       second_port_cmd640 = 1;
-                       port2 = "okay";
-               } else if (cmd640_vlb) {
-                       second_port_cmd640 = 1;
-                       port2 = "alive";
-               } else
-                       port2 = "not cmd640";
-       } else {
-               put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
-               if (secondary_port_responding()) {
-                       second_port_cmd640 = 1;
-                       port2 = "enabled";
-               } else {
-                       put_cmd640_reg(CNTRL, b); /* restore original setting */
-                       port2 = "not responding";
-               }
-       }
-
-       /*
-        * Initialize data for secondary cmd640 port, if enabled
-        */
-       if (second_port_cmd640)
-               hws[1] = &hw[1];
-
-       printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
-                        second_port_cmd640 ? "" : "not ", port2);
-
-#ifdef CMD640_DUMP_REGS
-       cmd640_dump_regs();
-#endif
-
-       return ide_host_add(&cmd640_port_info, hws, NULL);
-}
-
-module_param_named(probe_vlb, cmd640_vlb, bool, 0);
-MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset");
-
-module_init(cmd640x_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
deleted file mode 100644 (file)
index 935385c..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
- *           Due to massive hardware bugs, UltraDMA is only supported
- *           on the 646U2 and not on the 646U.
- *
- * Copyright (C) 1998          Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 1998          David S. Miller (davem@redhat.com)
- *
- * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "cmd64x"
-
-#define CMD_DEBUG 0
-
-#if CMD_DEBUG
-#define cmdprintk(x...)        printk(x)
-#else
-#define cmdprintk(x...)
-#endif
-
-/*
- * CMD64x specific registers definition.
- */
-#define CFR            0x50
-#define   CFR_INTR_CH0         0x04
-
-#define        CMDTIM          0x52
-#define        ARTTIM0         0x53
-#define        DRWTIM0         0x54
-#define ARTTIM1        0x55
-#define DRWTIM1                0x56
-#define ARTTIM23       0x57
-#define   ARTTIM23_DIS_RA2     0x04
-#define   ARTTIM23_DIS_RA3     0x08
-#define   ARTTIM23_INTR_CH1    0x10
-#define DRWTIM2                0x58
-#define BRST           0x59
-#define DRWTIM3                0x5b
-
-#define BMIDECR0       0x70
-#define MRDMODE                0x71
-#define   MRDMODE_INTR_CH0     0x04
-#define   MRDMODE_INTR_CH1     0x08
-#define UDIDETCR0      0x73
-#define DTPR0          0x74
-#define BMIDECR1       0x78
-#define BMIDECSR       0x79
-#define UDIDETCR1      0x7B
-#define DTPR1          0x7C
-
-static u8 quantize_timing(int timing, int quant)
-{
-       return (timing + quant - 1) / quant;
-}
-
-/*
- * This routine calculates active/recovery counts and then writes them into
- * the chipset registers.
- */
-static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
-       u8  cycle_count, active_count, recovery_count, drwtim;
-       static const u8 recovery_values[] =
-               {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
-       static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
-
-       cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",
-                 cycle_time, active_time);
-
-       cycle_count     = quantize_timing( cycle_time, clock_time);
-       active_count    = quantize_timing(active_time, clock_time);
-       recovery_count  = cycle_count - active_count;
-
-       /*
-        * In case we've got too long recovery phase, try to lengthen
-        * the active phase
-        */
-       if (recovery_count > 16) {
-               active_count += recovery_count - 16;
-               recovery_count = 16;
-       }
-       if (active_count > 16)          /* shouldn't actually happen... */
-               active_count = 16;
-
-       cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
-                 cycle_count, active_count, recovery_count);
-
-       /*
-        * Convert values to internal chipset representation
-        */
-       recovery_count = recovery_values[recovery_count];
-       active_count  &= 0x0f;
-
-       /* Program the active/recovery counts into the DRWTIM register */
-       drwtim = (active_count << 4) | recovery_count;
-       (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
-       cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
-}
-
-/*
- * This routine writes into the chipset registers
- * PIO setup/active/recovery timings.
- */
-static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct ide_timing *t    = ide_timing_find_mode(XFER_PIO_0 + pio);
-       unsigned int cycle_time;
-       u8 setup_count, arttim = 0;
-
-       static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
-       static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
-
-       cycle_time = ide_pio_cycle_time(drive, pio);
-
-       program_cycle_times(drive, cycle_time, t->active);
-
-       setup_count = quantize_timing(t->setup,
-                       1000 / (ide_pci_clk ? ide_pci_clk : 33));
-
-       /*
-        * The primary channel has individual address setup timing registers
-        * for each drive and the hardware selects the slowest timing itself.
-        * The secondary channel has one common register and we have to select
-        * the slowest address setup timing ourselves.
-        */
-       if (hwif->channel) {
-               ide_drive_t *drives = hwif->drives;
-
-               drive->drive_data = setup_count;
-               setup_count = max(drives[0].drive_data, drives[1].drive_data);
-       }
-
-       if (setup_count > 5)            /* shouldn't actually happen... */
-               setup_count = 5;
-       cmdprintk("Final address setup count: %d\n", setup_count);
-
-       /*
-        * Program the address setup clocks into the ARTTIM registers.
-        * Avoid clearing the secondary channel's interrupt bit.
-        */
-       (void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);
-       if (hwif->channel)
-               arttim &= ~ARTTIM23_INTR_CH1;
-       arttim &= ~0xc0;
-       arttim |= setup_values[setup_count];
-       (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
-       cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
-}
-
-/*
- * Attempts to set drive's PIO mode.
- * Special cases are 8: prefetch off, 9: prefetch on (both never worked)
- */
-
-static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       /*
-        * Filter out the prefetch control values
-        * to prevent PIO5 from being programmed
-        */
-       if (pio == 8 || pio == 9)
-               return;
-
-       cmd64x_tune_pio(drive, pio);
-}
-
-static void cmd64x_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 unit                 = drive->dn & 0x01;
-       u8 regU = 0, pciU       = hwif->channel ? UDIDETCR1 : UDIDETCR0;
-
-       if (speed >= XFER_SW_DMA_0) {
-               (void) pci_read_config_byte(dev, pciU, &regU);
-               regU &= ~(unit ? 0xCA : 0x35);
-       }
-
-       switch(speed) {
-       case XFER_UDMA_5:
-               regU |= unit ? 0x0A : 0x05;
-               break;
-       case XFER_UDMA_4:
-               regU |= unit ? 0x4A : 0x15;
-               break;
-       case XFER_UDMA_3:
-               regU |= unit ? 0x8A : 0x25;
-               break;
-       case XFER_UDMA_2:
-               regU |= unit ? 0x42 : 0x11;
-               break;
-       case XFER_UDMA_1:
-               regU |= unit ? 0x82 : 0x21;
-               break;
-       case XFER_UDMA_0:
-               regU |= unit ? 0xC2 : 0x31;
-               break;
-       case XFER_MW_DMA_2:
-               program_cycle_times(drive, 120, 70);
-               break;
-       case XFER_MW_DMA_1:
-               program_cycle_times(drive, 150, 80);
-               break;
-       case XFER_MW_DMA_0:
-               program_cycle_times(drive, 480, 215);
-               break;
-       }
-
-       if (speed >= XFER_SW_DMA_0)
-               (void) pci_write_config_byte(dev, pciU, regU);
-}
-
-static int cmd648_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long base      = hwif->dma_base - (hwif->channel * 8);
-       int err                 = ide_dma_end(drive);
-       u8  irq_mask            = hwif->channel ? MRDMODE_INTR_CH1 :
-                                                 MRDMODE_INTR_CH0;
-       u8  mrdmode             = inb(base + 1);
-
-       /* clear the interrupt bit */
-       outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
-            base + 1);
-
-       return err;
-}
-
-static int cmd64x_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
-       u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
-                                                 CFR_INTR_CH0;
-       u8  irq_stat            = 0;
-       int err                 = ide_dma_end(drive);
-
-       (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
-       /* clear the interrupt bit */
-       (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
-
-       return err;
-}
-
-static int cmd648_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long base      = hwif->dma_base - (hwif->channel * 8);
-       u8 irq_mask             = hwif->channel ? MRDMODE_INTR_CH1 :
-                                                 MRDMODE_INTR_CH0;
-       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
-       u8 mrdmode              = inb(base + 1);
-
-#ifdef DEBUG
-       printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
-              drive->name, dma_stat, mrdmode, irq_mask);
-#endif
-       if (!(mrdmode & irq_mask))
-               return 0;
-
-       /* return 1 if INTR asserted */
-       if (dma_stat & 4)
-               return 1;
-
-       return 0;
-}
-
-static int cmd64x_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
-       u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
-                                                 CFR_INTR_CH0;
-       u8  dma_stat            = inb(hwif->dma_base + ATA_DMA_STATUS);
-       u8  irq_stat            = 0;
-
-       (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
-
-#ifdef DEBUG
-       printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
-              drive->name, dma_stat, irq_stat, irq_mask);
-#endif
-       if (!(irq_stat & irq_mask))
-               return 0;
-
-       /* return 1 if INTR asserted */
-       if (dma_stat & 4)
-               return 1;
-
-       return 0;
-}
-
-/*
- * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
- * event order for DMA transfers.
- */
-
-static int cmd646_1_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       u8 dma_stat = 0, dma_cmd = 0;
-
-       drive->waiting_for_dma = 0;
-       /* get DMA status */
-       dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
-       /* read DMA command state */
-       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-       /* stop DMA */
-       outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
-       /* clear the INTR & ERROR bits */
-       outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-       /* and free any DMA resources */
-       ide_destroy_dmatable(drive);
-       /* verify good DMA status */
-       return (dma_stat & 7) != 4;
-}
-
-static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
-{
-       u8 mrdmode = 0;
-
-       /* Set a good latency timer and cache line size value. */
-       (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-       /* FIXME: pci_set_master() to ensure a good latency timer value */
-
-       /*
-        * Enable interrupts, select MEMORY READ LINE for reads.
-        *
-        * NOTE: although not mentioned in the PCI0646U specs,
-        * bits 0-1 are write only and won't be read back as
-        * set or not -- PCI0646U2 specs clarify this point.
-        */
-       (void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
-       mrdmode &= ~0x30;
-       (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
-
-       return 0;
-}
-
-static u8 cmd64x_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev  *dev    = to_pci_dev(hwif->dev);
-       u8 bmidecsr = 0, mask   = hwif->channel ? 0x02 : 0x01;
-
-       switch (dev->device) {
-       case PCI_DEVICE_ID_CMD_648:
-       case PCI_DEVICE_ID_CMD_649:
-               pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
-               return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-       default:
-               return ATA_CBL_PATA40;
-       }
-}
-
-static const struct ide_port_ops cmd64x_port_ops = {
-       .set_pio_mode           = cmd64x_set_pio_mode,
-       .set_dma_mode           = cmd64x_set_dma_mode,
-       .cable_detect           = cmd64x_cable_detect,
-};
-
-static const struct ide_dma_ops cmd64x_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                = cmd64x_dma_end,
-       .dma_test_irq           = cmd64x_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_dma_ops cmd646_rev1_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                = cmd646_1_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_dma_ops cmd648_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                = cmd648_dma_end,
-       .dma_test_irq           = cmd648_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
-       {       /* 0: CMD643 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_cmd64x,
-               .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd64x_dma_ops,
-               .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
-                                 IDE_HFLAG_ABUSE_PREFETCH,
-               .pio_mask       = ATA_PIO5,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = 0x00, /* no udma */
-       },
-       {       /* 1: CMD646 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_cmd64x,
-               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .chipset        = ide_cmd646,
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd648_dma_ops,
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
-               .pio_mask       = ATA_PIO5,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA2,
-       },
-       {       /* 2: CMD648 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_cmd64x,
-               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd648_dma_ops,
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
-               .pio_mask       = ATA_PIO5,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA4,
-       },
-       {       /* 3: CMD649 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_cmd64x,
-               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd648_dma_ops,
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
-               .pio_mask       = ATA_PIO5,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       }
-};
-
-static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d;
-       u8 idx = id->driver_data;
-
-       d = cmd64x_chipsets[idx];
-
-       if (idx == 1) {
-               /*
-                * UltraDMA only supported on PCI646U and PCI646U2, which
-                * correspond to revisions 0x03, 0x05 and 0x07 respectively.
-                * Actually, although the CMD tech support people won't
-                * tell me the details, the 0x03 revision cannot support
-                * UDMA correctly without hardware modifications, and even
-                * then it only works with Quantum disks due to some
-                * hold time assumptions in the 646U part which are fixed
-                * in the 646U2.
-                *
-                * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
-                */
-               if (dev->revision < 5) {
-                       d.udma_mask = 0x00;
-                       /*
-                        * The original PCI0646 didn't have the primary
-                        * channel enable bit, it appeared starting with
-                        * PCI0646U (i.e. revision ID 3).
-                        */
-                       if (dev->revision < 3) {
-                               d.enablebits[0].reg = 0;
-                               if (dev->revision == 1)
-                                       d.dma_ops = &cmd646_rev1_dma_ops;
-                               else
-                                       d.dma_ops = &cmd64x_dma_ops;
-                       }
-               }
-       }
-
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-static const struct pci_device_id cmd64x_pci_tbl[] = {
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 },
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
-
-static struct pci_driver cmd64x_pci_driver = {
-       .name           = "CMD64x_IDE",
-       .id_table       = cmd64x_pci_tbl,
-       .probe          = cmd64x_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init cmd64x_ide_init(void)
-{
-       return ide_pci_register_driver(&cmd64x_pci_driver);
-}
-
-static void __exit cmd64x_ide_exit(void)
-{
-       pci_unregister_driver(&cmd64x_pci_driver);
-}
-
-module_init(cmd64x_ide_init);
-module_exit(cmd64x_ide_exit);
-
-MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
deleted file mode 100644 (file)
index 5efb467..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *     IDE tuning and bus mastering support for the CS5510/CS5520
- *     chipsets
- *
- *     The CS5510/CS5520 are slightly unusual devices. Unlike the 
- *     typical IDE controllers they do bus mastering with the drive in
- *     PIO mode and smarter silicon.
- *
- *     The practical upshot of this is that we must always tune the
- *     drive for the right PIO mode. We must also ignore all the blacklists
- *     and the drive bus mastering DMA information.
- *
- *     *** This driver is strictly experimental ***
- *
- *     (c) Copyright Red Hat Inc 2002
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * For the avoidance of doubt the "preferred form" of this code is one which
- * is in an open non patent encumbered format. Where cryptographic key signing
- * forms part of the process of creating an executable the information
- * including keys needed to generate an equivalently functional executable
- * are deemed to be part of the source code.
- *
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/dma-mapping.h>
-
-#define DRV_NAME "cs5520"
-
-struct pio_clocks
-{
-       int address;
-       int assert;
-       int recovery;
-};
-
-static struct pio_clocks cs5520_pio_clocks[]={
-       {3, 6, 11},
-       {2, 5, 6},
-       {1, 4, 3},
-       {1, 3, 2},
-       {1, 2, 1}
-};
-
-static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       int controller = drive->dn > 1 ? 1 : 0;
-
-       /* 8bit CAT/CRT - 8bit command timing for channel */
-       pci_write_config_byte(pdev, 0x62 + controller, 
-               (cs5520_pio_clocks[pio].recovery << 4) |
-               (cs5520_pio_clocks[pio].assert));
-
-       /* 0x64 - 16bit Primary, 0x68 - 16bit Secondary */
-
-       /* FIXME: should these use address ? */
-       /* Data read timing */
-       pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1),
-               (cs5520_pio_clocks[pio].recovery << 4) |
-               (cs5520_pio_clocks[pio].assert));
-       /* Write command timing */
-       pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
-               (cs5520_pio_clocks[pio].recovery << 4) |
-               (cs5520_pio_clocks[pio].assert));
-}
-
-static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       printk(KERN_ERR "cs55x0: bad ide timing.\n");
-
-       cs5520_set_pio_mode(drive, 0);
-}
-
-static const struct ide_port_ops cs5520_port_ops = {
-       .set_pio_mode           = cs5520_set_pio_mode,
-       .set_dma_mode           = cs5520_set_dma_mode,
-};
-
-static const struct ide_port_info cyrix_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .enablebits     = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
-       .port_ops       = &cs5520_port_ops,
-       .host_flags     = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520,
-       .pio_mask       = ATA_PIO4,
-};
-
-/*
- *     The 5510/5520 are a bit weird. They don't quite set up the way
- *     the PCI helper layer expects so we must do much of the set up 
- *     work longhand.
- */
-static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       const struct ide_port_info *d = &cyrix_chipset;
-       hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
-
-       ide_setup_pci_noise(dev, d);
-
-       /* We must not grab the entire device, it has 'ISA' space in its
-        * BARS too and we will freak out other bits of the kernel
-        */
-       if (pci_enable_device_io(dev)) {
-               printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
-               return -ENODEV;
-       }
-       pci_set_master(dev);
-       if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
-               printk(KERN_WARNING "%s: No suitable DMA available.\n",
-                       d->name);
-               return -ENODEV;
-       }
-
-       /*
-        *      Now the chipset is configured we can let the core
-        *      do all the device setup for us
-        */
-
-       ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
-
-       return ide_host_add(d, hws, NULL);
-}
-
-static const struct pci_device_id cs5520_pci_tbl[] = {
-       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), 0 },
-       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), 1 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
-
-static struct pci_driver cs5520_pci_driver = {
-       .name           = "Cyrix_IDE",
-       .id_table       = cs5520_pci_tbl,
-       .probe          = cs5520_init_one,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init cs5520_ide_init(void)
-{
-       return ide_pci_register_driver(&cs5520_pci_driver);
-}
-
-module_init(cs5520_ide_init);
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for Cyrix 5510/5520 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
deleted file mode 100644 (file)
index 53f079c..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2000                  Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2000                  Mark Lord <mlord@pobox.com>
- * Copyright (C) 2007                  Bartlomiej Zolnierkiewicz
- *
- * May be copied or modified under the terms of the GNU General Public License
- *
- * Development of this chipset driver was funded
- * by the nice folks at National Semiconductor.
- *
- * Documentation:
- *     CS5530 documentation available from National Semiconductor.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "cs5530"
-
-/*
- * Here are the standard PIO mode 0-4 timings for each "format".
- * Format-0 uses fast data reg timings, with slower command reg timings.
- * Format-1 uses fast timings for all registers, but won't work with all drives.
- */
-static unsigned int cs5530_pio_timings[2][5] = {
-       {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
-       {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}
-};
-
-/*
- * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
- */
-#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
-#define CS5530_BASEREG(hwif)   (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
-
-/**
- *     cs5530_set_pio_mode     -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Handles setting of PIO mode for the chipset.
- *
- *     The init_hwif_cs5530() routine guarantees that all drives
- *     will have valid default PIO timings set up before we get here.
- */
-
-static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       unsigned long basereg = CS5530_BASEREG(drive->hwif);
-       unsigned int format = (inl(basereg + 4) >> 31) & 1;
-
-       outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
-}
-
-/**
- *     cs5530_udma_filter      -       UDMA filter
- *     @drive: drive
- *
- *     cs5530_udma_filter() does UDMA mask filtering for the given drive
- *     taking into the consideration capabilities of the mate device.
- *
- *     The CS5530 specifies that two drives sharing a cable cannot mix
- *     UDMA/MDMA.  It has to be one or the other, for the pair, though
- *     different timings can still be chosen for each drive.  We could
- *     set the appropriate timing bits on the fly, but that might be
- *     a bit confusing.  So, for now we statically handle this requirement
- *     by looking at our mate drive to see what it is capable of, before
- *     choosing a mode for our own drive.
- *
- *     Note: This relies on the fact we never fail from UDMA to MWDMA2
- *     but instead drop to PIO.
- */
-
-static u8 cs5530_udma_filter(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       ide_drive_t *mate = ide_get_pair_dev(drive);
-       u16 *mateid = mate->id;
-       u8 mask = hwif->ultra_mask;
-
-       if (mate == NULL)
-               goto out;
-
-       if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
-               if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
-                   (mateid[ATA_ID_UDMA_MODES] & 7))
-                       goto out;
-               if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
-                   (mateid[ATA_ID_MWDMA_MODES] & 7))
-                       mask = 0;
-       }
-out:
-       return mask;
-}
-
-static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
-{
-       unsigned long basereg;
-       unsigned int reg, timings = 0;
-
-       switch (mode) {
-               case XFER_UDMA_0:       timings = 0x00921250; break;
-               case XFER_UDMA_1:       timings = 0x00911140; break;
-               case XFER_UDMA_2:       timings = 0x00911030; break;
-               case XFER_MW_DMA_0:     timings = 0x00077771; break;
-               case XFER_MW_DMA_1:     timings = 0x00012121; break;
-               case XFER_MW_DMA_2:     timings = 0x00002020; break;
-       }
-       basereg = CS5530_BASEREG(drive->hwif);
-       reg = inl(basereg + 4);                 /* get drive0 config register */
-       timings |= reg & 0x80000000;            /* preserve PIO format bit */
-       if ((drive-> dn & 1) == 0) {            /* are we configuring drive0? */
-               outl(timings, basereg + 4);     /* write drive0 config register */
-       } else {
-               if (timings & 0x00100000)
-                       reg |=  0x00100000;     /* enable UDMA timings for both drives */
-               else
-                       reg &= ~0x00100000;     /* disable UDMA timings for both drives */
-               outl(reg, basereg + 4);         /* write drive0 config register */
-               outl(timings, basereg + 12);    /* write drive1 config register */
-       }
-}
-
-/**
- *     init_chipset_5530       -       set up 5530 bridge
- *     @dev: PCI device
- *
- *     Initialize the cs5530 bridge for reliable IDE DMA operation.
- */
-
-static unsigned int init_chipset_cs5530(struct pci_dev *dev)
-{
-       struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
-
-       if (pci_resource_start(dev, 4) == 0)
-               return -EFAULT;
-
-       dev = NULL;
-       while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
-               switch (dev->device) {
-                       case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
-                               master_0 = pci_dev_get(dev);
-                               break;
-                       case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
-                               cs5530_0 = pci_dev_get(dev);
-                               break;
-               }
-       }
-       if (!master_0) {
-               printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
-               goto out;
-       }
-       if (!cs5530_0) {
-               printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
-               goto out;
-       }
-
-       /*
-        * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
-        * -->  OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
-        */
-
-       pci_set_master(cs5530_0);
-       pci_try_set_mwi(cs5530_0);
-
-       /*
-        * Set PCI CacheLineSize to 16-bytes:
-        * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
-        */
-
-       pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
-
-       /*
-        * Disable trapping of UDMA register accesses (Win98 hack):
-        * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
-        */
-
-       pci_write_config_word(cs5530_0, 0xd0, 0x5006);
-
-       /*
-        * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
-        * The other settings are what is necessary to get the register
-        * into a sane state for IDE DMA operation.
-        */
-
-       pci_write_config_byte(master_0, 0x40, 0x1e);
-
-       /* 
-        * Set max PCI burst size (16-bytes seems to work best):
-        *         16bytes: set bit-1 at 0x41 (reg value of 0x16)
-        *      all others: clear bit-1 at 0x41, and do:
-        *        128bytes: OR 0x00 at 0x41
-        *        256bytes: OR 0x04 at 0x41
-        *        512bytes: OR 0x08 at 0x41
-        *       1024bytes: OR 0x0c at 0x41
-        */
-
-       pci_write_config_byte(master_0, 0x41, 0x14);
-
-       /*
-        * These settings are necessary to get the chip
-        * into a sane state for IDE DMA operation.
-        */
-
-       pci_write_config_byte(master_0, 0x42, 0x00);
-       pci_write_config_byte(master_0, 0x43, 0xc1);
-
-out:
-       pci_dev_put(master_0);
-       pci_dev_put(cs5530_0);
-       return 0;
-}
-
-/**
- *     init_hwif_cs5530        -       initialise an IDE channel
- *     @hwif: IDE to initialize
- *
- *     This gets invoked by the IDE driver once for each channel. It
- *     performs channel-specific pre-initialization before drive probing.
- */
-
-static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
-{
-       unsigned long basereg;
-       u32 d0_timings;
-
-       basereg = CS5530_BASEREG(hwif);
-       d0_timings = inl(basereg + 0);
-       if (CS5530_BAD_PIO(d0_timings))
-               outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
-       if (CS5530_BAD_PIO(inl(basereg + 8)))
-               outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
-}
-
-static const struct ide_port_ops cs5530_port_ops = {
-       .set_pio_mode           = cs5530_set_pio_mode,
-       .set_dma_mode           = cs5530_set_dma_mode,
-       .udma_filter            = cs5530_udma_filter,
-};
-
-static const struct ide_port_info cs5530_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_chipset   = init_chipset_cs5530,
-       .init_hwif      = init_hwif_cs5530,
-       .port_ops       = &cs5530_port_ops,
-       .host_flags     = IDE_HFLAG_SERIALIZE |
-                         IDE_HFLAG_POST_SET_MODE,
-       .pio_mask       = ATA_PIO4,
-       .mwdma_mask     = ATA_MWDMA2,
-       .udma_mask      = ATA_UDMA2,
-};
-
-static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &cs5530_chipset, NULL);
-}
-
-static const struct pci_device_id cs5530_pci_tbl[] = {
-       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
-
-static struct pci_driver cs5530_pci_driver = {
-       .name           = "CS5530 IDE",
-       .id_table       = cs5530_pci_tbl,
-       .probe          = cs5530_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init cs5530_ide_init(void)
-{
-       return ide_pci_register_driver(&cs5530_pci_driver);
-}
-
-static void __exit cs5530_ide_exit(void)
-{
-       pci_unregister_driver(&cs5530_pci_driver);
-}
-
-module_init(cs5530_ide_init);
-module_exit(cs5530_ide_exit);
-
-MODULE_AUTHOR("Mark Lord");
-MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
deleted file mode 100644 (file)
index 983d957..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
- * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
- *
- * History:
- * 09/20/2005 - Jaya Kumar <jayakumar.ide@gmail.com>
- * - Reworked tuneproc, set_drive, misc mods to prep for mainline
- * - Work was sponsored by CIS (M) Sdn Bhd.
- * Ported to Kernel 2.6.11 on June 26, 2005 by
- *   Wolfgang Zuleger <wolfgang.zuleger@gmx.de>
- *   Alexander Kiausch <alex.kiausch@t-online.de>
- * Originally developed by AMD for 2.4/2.6
- *
- * Development of this chipset driver was funded
- * by the nice folks at National Semiconductor/AMD.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * Documentation:
- *  CS5535 documentation available from AMD
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#define DRV_NAME "cs5535"
-
-#define MSR_ATAC_BASE          0x51300000
-#define ATAC_GLD_MSR_CAP       (MSR_ATAC_BASE+0)
-#define ATAC_GLD_MSR_CONFIG    (MSR_ATAC_BASE+0x01)
-#define ATAC_GLD_MSR_SMI       (MSR_ATAC_BASE+0x02)
-#define ATAC_GLD_MSR_ERROR     (MSR_ATAC_BASE+0x03)
-#define ATAC_GLD_MSR_PM                (MSR_ATAC_BASE+0x04)
-#define ATAC_GLD_MSR_DIAG      (MSR_ATAC_BASE+0x05)
-#define ATAC_IO_BAR            (MSR_ATAC_BASE+0x08)
-#define ATAC_RESET             (MSR_ATAC_BASE+0x10)
-#define ATAC_CH0D0_PIO         (MSR_ATAC_BASE+0x20)
-#define ATAC_CH0D0_DMA         (MSR_ATAC_BASE+0x21)
-#define ATAC_CH0D1_PIO         (MSR_ATAC_BASE+0x22)
-#define ATAC_CH0D1_DMA         (MSR_ATAC_BASE+0x23)
-#define ATAC_PCI_ABRTERR       (MSR_ATAC_BASE+0x24)
-#define ATAC_BM0_CMD_PRIM      0x00
-#define ATAC_BM0_STS_PRIM      0x02
-#define ATAC_BM0_PRD           0x04
-#define CS5535_CABLE_DETECT    0x48
-
-/* Format I PIO settings. We separate out cmd and data for safer timings */
-
-static unsigned int cs5535_pio_cmd_timings[5] =
-{ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 };
-static unsigned int cs5535_pio_dta_timings[5] =
-{ 0xF7F4, 0xF173, 0x8141, 0x5131, 0x1131 };
-
-static unsigned int cs5535_mwdma_timings[3] =
-{ 0x7F0FFFF3, 0x7F035352, 0x7f024241 };
-
-static unsigned int cs5535_udma_timings[5] =
-{ 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061 };
-
-/* Macros to check if the register is the reset value -  reset value is an
-   invalid timing and indicates the register has not been set previously */
-
-#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL) == 0x00009172 )
-#define CS5535_BAD_DMA(timings) ( (timings & 0x000FFFFF) == 0x00077771 )
-
-/****
- *     cs5535_set_speed         -     Configure the chipset to the new speed
- *     @drive: Drive to set up
- *     @speed: desired speed
- *
- *     cs5535_set_speed() configures the chipset to a new speed.
- */
-static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
-{
-       u32 reg = 0, dummy;
-       u8 unit = drive->dn & 1;
-
-       /* Set the PIO timings */
-       if (speed < XFER_SW_DMA_0) {
-               ide_drive_t *pair = ide_get_pair_dev(drive);
-               u8 cmd, pioa;
-
-               cmd = pioa = speed - XFER_PIO_0;
-
-               if (pair) {
-                       u8 piob = ide_get_best_pio_mode(pair, 255, 4);
-
-                       if (piob < cmd)
-                               cmd = piob;
-               }
-
-               /* Write the speed of the current drive */
-               reg = (cs5535_pio_cmd_timings[cmd] << 16) |
-                       cs5535_pio_dta_timings[pioa];
-               wrmsr(unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, reg, 0);
-
-               /* And if nessesary - change the speed of the other drive */
-               rdmsr(unit ?  ATAC_CH0D0_PIO : ATAC_CH0D1_PIO, reg, dummy);
-
-               if (((reg >> 16) & cs5535_pio_cmd_timings[cmd]) !=
-                       cs5535_pio_cmd_timings[cmd]) {
-                       reg &= 0x0000FFFF;
-                       reg |= cs5535_pio_cmd_timings[cmd] << 16;
-                       wrmsr(unit ? ATAC_CH0D0_PIO : ATAC_CH0D1_PIO, reg, 0);
-               }
-
-               /* Set bit 31 of the DMA register for PIO format 1 timings */
-               rdmsr(unit ?  ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
-               wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA,
-                                       reg | 0x80000000UL, 0);
-       } else {
-               rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
-
-               reg &= 0x80000000UL;  /* Preserve the PIO format bit */
-
-               if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_4)
-                       reg |= cs5535_udma_timings[speed - XFER_UDMA_0];
-               else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
-                       reg |= cs5535_mwdma_timings[speed - XFER_MW_DMA_0];
-               else
-                       return;
-
-               wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, 0);
-       }
-}
-
-/**
- *     cs5535_set_dma_mode     -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Programs the chipset for DMA mode.
- */
-
-static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       cs5535_set_speed(drive, speed);
-}
-
-/**
- *     cs5535_set_pio_mode     -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     A callback from the upper layers for PIO-only tuning.
- */
-
-static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       cs5535_set_speed(drive, XFER_PIO_0 + pio);
-}
-
-static u8 cs5535_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 bit;
-
-       /* if a 80 wire cable was detected */
-       pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
-
-       return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-}
-
-static const struct ide_port_ops cs5535_port_ops = {
-       .set_pio_mode           = cs5535_set_pio_mode,
-       .set_dma_mode           = cs5535_set_dma_mode,
-       .cable_detect           = cs5535_cable_detect,
-};
-
-static const struct ide_port_info cs5535_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .port_ops       = &cs5535_port_ops,
-       .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
-       .pio_mask       = ATA_PIO4,
-       .mwdma_mask     = ATA_MWDMA2,
-       .udma_mask      = ATA_UDMA4,
-};
-
-static int __devinit cs5535_init_one(struct pci_dev *dev,
-                                       const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &cs5535_chipset, NULL);
-}
-
-static const struct pci_device_id cs5535_pci_tbl[] = {
-       { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_CS5535_IDE), 0 },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
-
-static struct pci_driver cs5535_pci_driver = {
-       .name           = "CS5535_IDE",
-       .id_table       = cs5535_pci_tbl,
-       .probe          = cs5535_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init cs5535_ide_init(void)
-{
-       return ide_pci_register_driver(&cs5535_pci_driver);
-}
-
-static void __exit cs5535_ide_exit(void)
-{
-       pci_unregister_driver(&cs5535_pci_driver);
-}
-
-module_init(cs5535_ide_init);
-module_exit(cs5535_ide_exit);
-
-MODULE_AUTHOR("AMD");
-MODULE_DESCRIPTION("PCI driver module for AMD/NS CS5535 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
deleted file mode 100644 (file)
index 5297f07..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
- *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
- *
- * CYPRESS CY82C693 chipset IDE controller
- *
- * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
- * Writing the driver was quite simple, since most of the job is
- * done by the generic pci-ide support.
- * The hard part was finding the CY82C693's datasheet on Cypress's
- * web page :-(. But Altavista solved this problem :-).
- *
- *
- * Notes:
- * - I recently got a 16.8G IBM DTTA, so I was able to test it with
- *   a large and fast disk - the results look great, so I'd say the
- *   driver is working fine :-)
- *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
- * - this is my first linux driver, so there's probably a lot  of room
- *   for optimizations and bug fixing, so feel free to do it.
- * - if using PIO mode it's a good idea to set the PIO mode and
- *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
- * - I had some problems with my IBM DHEA with PIO modes < 2
- *   (lost interrupts) ?????
- * - first tests with DMA look okay, they seem to work, but there is a
- *   problem with sound - the BusMaster IDE TimeOut should fixed this
- *
- * Ancient History:
- * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693
- * ASK@1999-01-23: v0.33 made a few minor code clean ups
- *                       removed DMA clock speed setting by default
- *                       added boot message
- * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut
- *                       added support to set DMA Controller Clock Speed
- * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes
- *                       on some drives.
- * ASK@1998-10-29: v0.3 added support to set DMA modes
- * ASK@1998-10-28: v0.2 added support to set PIO modes
- * ASK@1998-10-27: v0.1 first version - chipset detection
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "cy82c693"
-
-/*
- *     The following are used to debug the driver.
- */
-#define CY82C693_DEBUG_INFO    0
-
-/*
- *     NOTE: the value for busmaster timeout is tricky and I got it by
- *     trial and error!  By using a to low value will cause DMA timeouts
- *     and drop IDE performance, and by using a to high value will cause
- *     audio playback to scatter.
- *     If you know a better value or how to calc it, please let me know.
- */
-
-/* twice the value written in cy82c693ub datasheet */
-#define BUSMASTER_TIMEOUT      0x50
-/*
- * the value above was tested on my machine and it seems to work okay
- */
-
-/* here are the offset definitions for the registers */
-#define CY82_IDE_CMDREG                0x04
-#define CY82_IDE_ADDRSETUP     0x48
-#define CY82_IDE_MASTER_IOR    0x4C
-#define CY82_IDE_MASTER_IOW    0x4D
-#define CY82_IDE_SLAVE_IOR     0x4E
-#define CY82_IDE_SLAVE_IOW     0x4F
-#define CY82_IDE_MASTER_8BIT   0x50
-#define CY82_IDE_SLAVE_8BIT    0x51
-
-#define CY82_INDEX_PORT                0x22
-#define CY82_DATA_PORT         0x23
-
-#define CY82_INDEX_CHANNEL0    0x30
-#define CY82_INDEX_CHANNEL1    0x31
-#define CY82_INDEX_TIMEOUT     0x32
-
-/* the min and max PCI bus speed in MHz - from datasheet */
-#define CY82C963_MIN_BUS_SPEED 25
-#define CY82C963_MAX_BUS_SPEED 33
-
-/* the struct for the PIO mode timings */
-typedef struct pio_clocks_s {
-       u8      address_time;   /* Address setup (clocks) */
-       u8      time_16r;       /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
-       u8      time_16w;       /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
-       u8      time_8;         /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
-} pio_clocks_t;
-
-/*
- * calc clocks using bus_speed
- * returns (rounded up) time in bus clocks for time in ns
- */
-static int calc_clk(int time, int bus_speed)
-{
-       int clocks;
-
-       clocks = (time*bus_speed+999)/1000 - 1;
-
-       if (clocks < 0)
-               clocks = 0;
-
-       if (clocks > 0x0F)
-               clocks = 0x0F;
-
-       return clocks;
-}
-
-/*
- * compute the values for the clock registers for PIO
- * mode and pci_clk [MHz] speed
- *
- * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
- *       for mode 3 and 4 drives 8 and 16-bit timings are the same
- *
- */
-static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
-{
-       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-       int clk1, clk2;
-       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-
-       /* we don't check against CY82C693's min and max speed,
-        * so you can play with the idebus=xx parameter
-        */
-
-       /* let's calc the address setup time clocks */
-       p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);
-
-       /* let's calc the active and recovery time clocks */
-       clk1 = calc_clk(t->active, bus_speed);
-
-       /* calc recovery timing */
-       clk2 = t->cycle - t->active - t->setup;
-
-       clk2 = calc_clk(clk2, bus_speed);
-
-       clk1 = (clk1<<4)|clk2;  /* combine active and recovery clocks */
-
-       /* note: we use the same values for 16bit IOR and IOW
-        *      those are all the same, since I don't have other
-        *      timings than those from ide-lib.c
-        */
-
-       p_pclk->time_16r = (u8)clk1;
-       p_pclk->time_16w = (u8)clk1;
-
-       /* what are good values for 8bit ?? */
-       p_pclk->time_8 = (u8)clk1;
-}
-
-/*
- * set DMA mode a specific channel for CY82C693
- */
-
-static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
-
-       index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
-
-       data = (mode & 3) | (single << 2);
-
-       outb(index, CY82_INDEX_PORT);
-       outb(data, CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
-       printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
-               drive->name, hwif->channel, drive->dn & 1, mode & 3, single);
-#endif /* CY82C693_DEBUG_INFO */
-
-       /*
-        * note: below we set the value for Bus Master IDE TimeOut Register
-        * I'm not absolutly sure what this does, but it solved my problem
-        * with IDE DMA and sound, so I now can play sound and work with
-        * my IDE driver at the same time :-)
-        *
-        * If you know the correct (best) value for this register please
-        * let me know - ASK
-        */
-
-       data = BUSMASTER_TIMEOUT;
-       outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
-       outb(data, CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
-       printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
-               drive->name, data);
-#endif /* CY82C693_DEBUG_INFO */
-}
-
-static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       pio_clocks_t pclk;
-       unsigned int addrCtrl;
-
-       /* select primary or secondary channel */
-       if (hwif->index > 0) {  /* drive is on the secondary channel */
-               dev = pci_get_slot(dev->bus, dev->devfn+1);
-               if (!dev) {
-                       printk(KERN_ERR "%s: tune_drive: "
-                               "Cannot find secondary interface!\n",
-                               drive->name);
-                       return;
-               }
-       }
-
-       /* let's calc the values for this PIO mode */
-       compute_clocks(pio, &pclk);
-
-       /* now let's write  the clocks registers */
-       if ((drive->dn & 1) == 0) {
-               /*
-                * set master drive
-                * address setup control register
-                * is 32 bit !!!
-                */
-               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-
-               addrCtrl &= (~0xF);
-               addrCtrl |= (unsigned int)pclk.address_time;
-               pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
-
-               /* now let's set the remaining registers */
-               pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
-               pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
-               pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
-
-               addrCtrl &= 0xF;
-       } else {
-               /*
-                * set slave drive
-                * address setup control register
-                * is 32 bit !!!
-                */
-               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-
-               addrCtrl &= (~0xF0);
-               addrCtrl |= ((unsigned int)pclk.address_time<<4);
-               pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
-
-               /* now let's set the remaining registers */
-               pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
-               pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
-               pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
-
-               addrCtrl >>= 4;
-               addrCtrl &= 0xF;
-       }
-
-#if CY82C693_DEBUG_INFO
-       printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
-               "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
-               drive->name, hwif->channel, drive->dn & 1,
-               addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
-#endif /* CY82C693_DEBUG_INFO */
-}
-
-static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
-{
-       static ide_hwif_t *primary;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       if (PCI_FUNC(dev->devfn) == 1)
-               primary = hwif;
-       else {
-               hwif->mate = primary;
-               hwif->channel = 1;
-       }
-}
-
-static const struct ide_port_ops cy82c693_port_ops = {
-       .set_pio_mode           = cy82c693_set_pio_mode,
-       .set_dma_mode           = cy82c693_set_dma_mode,
-};
-
-static const struct ide_port_info cy82c693_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_iops      = init_iops_cy82c693,
-       .port_ops       = &cy82c693_port_ops,
-       .chipset        = ide_cy82c693,
-       .host_flags     = IDE_HFLAG_SINGLE,
-       .pio_mask       = ATA_PIO4,
-       .swdma_mask     = ATA_SWDMA2,
-       .mwdma_mask     = ATA_MWDMA2,
-};
-
-static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct pci_dev *dev2;
-       int ret = -ENODEV;
-
-       /* CY82C693 is more than only a IDE controller.
-          Function 1 is primary IDE channel, function 2 - secondary. */
-       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
-           PCI_FUNC(dev->devfn) == 1) {
-               dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
-               ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
-               if (ret)
-                       pci_dev_put(dev2);
-       }
-       return ret;
-}
-
-static void __devexit cy82c693_remove(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
-
-       ide_pci_remove(dev);
-       pci_dev_put(dev2);
-}
-
-static const struct pci_device_id cy82c693_pci_tbl[] = {
-       { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
-
-static struct pci_driver cy82c693_pci_driver = {
-       .name           = "Cypress_IDE",
-       .id_table       = cy82c693_pci_tbl,
-       .probe          = cy82c693_init_one,
-       .remove         = __devexit_p(cy82c693_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init cy82c693_ide_init(void)
-{
-       return ide_pci_register_driver(&cy82c693_pci_driver);
-}
-
-static void __exit cy82c693_ide_exit(void)
-{
-       pci_unregister_driver(&cy82c693_pci_driver);
-}
-
-module_init(cy82c693_ide_init);
-module_exit(cy82c693_ide_exit);
-
-MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
deleted file mode 100644 (file)
index 8f1b2d9..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *  Created 20 Oct 2004 by Mark Lord
- *
- *  Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
- *
- *  Modeled after the 16-bit PCMCIA driver: ide-cs.c
- *
- *  This is slightly peculiar, in that it is a PCI driver,
- *  but is NOT an IDE PCI driver -- the IDE layer does not directly
- *  support hot insertion/removal of PCI interfaces, so this driver
- *  is unable to use the IDE PCI interfaces.  Instead, it uses the
- *  same interfaces as the ide-cs (PCMCIA) driver uses.
- *  On the plus side, the driver is also smaller/simpler this way.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-
-/*
- * No chip documentation has yet been found,
- * so these configuration values were pulled from
- * a running Win98 system using "debug".
- * This gives around 3MByte/second read performance,
- * which is about 2/3 of what the chip is capable of.
- *
- * There is also a 4KByte mmio region on the card,
- * but its purpose has yet to be reverse-engineered.
- */
-static const u8 setup[] = {
-       0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00,
-       0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
-};
-
-static const struct ide_port_ops delkin_cb_port_ops = {
-       .quirkproc              = ide_undecoded_slave,
-};
-
-static unsigned int delkin_cb_init_chipset(struct pci_dev *dev)
-{
-       unsigned long base = pci_resource_start(dev, 0);
-       int i;
-
-       outb(0x02, base + 0x1e);        /* set nIEN to block interrupts */
-       inb(base + 0x17);               /* read status to clear interrupts */
-
-       for (i = 0; i < sizeof(setup); ++i) {
-               if (setup[i])
-                       outb(setup[i], base + i);
-       }
-
-       return 0;
-}
-
-static const struct ide_port_info delkin_cb_port_info = {
-       .port_ops               = &delkin_cb_port_ops,
-       .host_flags             = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS |
-                                 IDE_HFLAG_NO_DMA,
-       .init_chipset           = delkin_cb_init_chipset,
-};
-
-static int __devinit
-delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_host *host;
-       unsigned long base;
-       int rc;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-
-       rc = pci_enable_device(dev);
-       if (rc) {
-               printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc);
-               return rc;
-       }
-       rc = pci_request_regions(dev, "delkin_cb");
-       if (rc) {
-               printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc);
-               pci_disable_device(dev);
-               return rc;
-       }
-       base = pci_resource_start(dev, 0);
-
-       delkin_cb_init_chipset(dev);
-
-       memset(&hw, 0, sizeof(hw));
-       ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
-       hw.irq = dev->irq;
-       hw.dev = &dev->dev;
-       hw.chipset = ide_pci;           /* this enables IRQ sharing */
-
-       rc = ide_host_add(&delkin_cb_port_info, hws, &host);
-       if (rc)
-               goto out_disable;
-
-       pci_set_drvdata(dev, host);
-
-       return 0;
-
-out_disable:
-       pci_release_regions(dev);
-       pci_disable_device(dev);
-       return rc;
-}
-
-static void
-delkin_cb_remove (struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-
-       ide_host_remove(host);
-
-       pci_release_regions(dev);
-       pci_disable_device(dev);
-}
-
-#ifdef CONFIG_PM
-static int delkin_cb_suspend(struct pci_dev *dev, pm_message_t state)
-{
-       pci_save_state(dev);
-       pci_disable_device(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
-
-       return 0;
-}
-
-static int delkin_cb_resume(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       int rc;
-
-       pci_set_power_state(dev, PCI_D0);
-
-       rc = pci_enable_device(dev);
-       if (rc)
-               return rc;
-
-       pci_restore_state(dev);
-       pci_set_master(dev);
-
-       if (host->init_chipset)
-               host->init_chipset(dev);
-
-       return 0;
-}
-#else
-#define delkin_cb_suspend NULL
-#define delkin_cb_resume NULL
-#endif
-
-static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
-       { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
-
-static struct pci_driver delkin_cb_pci_driver = {
-       .name           = "Delkin-ASKA-Workbit Cardbus IDE",
-       .id_table       = delkin_cb_pci_tbl,
-       .probe          = delkin_cb_probe,
-       .remove         = delkin_cb_remove,
-       .suspend        = delkin_cb_suspend,
-       .resume         = delkin_cb_resume,
-};
-
-static int __init delkin_cb_init(void)
-{
-       return pci_register_driver(&delkin_cb_pci_driver);
-}
-
-static void __exit delkin_cb_exit(void)
-{
-       pci_unregister_driver(&delkin_cb_pci_driver);
-}
-
-module_init(delkin_cb_init);
-module_exit(delkin_cb_exit);
-
-MODULE_AUTHOR("Mark Lord");
-MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
deleted file mode 100644 (file)
index 474f96a..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *  Copyright (C) 2001-2002    Andre Hedrick <andre@linux-ide.org>
- *  Portions (C) Copyright 2002  Red Hat Inc <alan@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * For the avoidance of doubt the "preferred form" of this code is one which
- * is in an open non patent encumbered format. Where cryptographic key signing
- * forms part of the process of creating an executable the information
- * including keys needed to generate an equivalently functional executable
- * are deemed to be part of the source code.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "ide_pci_generic"
-
-static int ide_generic_all;            /* Set to claim all devices */
-
-module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
-MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
-
-#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
-
-#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
-       { \
-               .name           = DRV_NAME, \
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
-                                 extra_flags, \
-               .swdma_mask     = ATA_SWDMA2, \
-               .mwdma_mask     = ATA_MWDMA2, \
-               .udma_mask      = ATA_UDMA6, \
-       }
-
-static const struct ide_port_info generic_chipsets[] __devinitdata = {
-       /*  0: Unknown */
-       DECLARE_GENERIC_PCI_DEV(0),
-
-       {       /* 1: NS87410 */
-               .name           = DRV_NAME,
-               .enablebits     = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
-               .swdma_mask     = ATA_SWDMA2,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-       },
-
-       /*  2: SAMURAI / HT6565 / HINT_IDE */
-       DECLARE_GENERIC_PCI_DEV(0),
-       /*  3: UM8673F / UM8886A / UM8886BF */
-       DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
-       /*  4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
-       DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
-
-       {       /* 5: VIA8237SATA */
-               .name           = DRV_NAME,
-               .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_OFF_BOARD,
-               .swdma_mask     = ATA_SWDMA2,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-       },
-
-       {       /* 6: Revolution */
-               .name           = DRV_NAME,
-               .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
-                                 IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                                 IDE_HFLAG_OFF_BOARD,
-               .swdma_mask     = ATA_SWDMA2,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA6,
-       }
-};
-
-/**
- *     generic_init_one        -       called when a PIIX is found
- *     @dev: the generic device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-
-static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       const struct ide_port_info *d = &generic_chipsets[id->driver_data];
-       int ret = -ENODEV;
-
-       /* Don't use the generic entry unless instructed to do so */
-       if (id->driver_data == 0 && ide_generic_all == 0)
-                       goto out;
-
-       switch (dev->vendor) {
-       case PCI_VENDOR_ID_UMC:
-               if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
-                               !(PCI_FUNC(dev->devfn) & 1))
-                       goto out; /* UM8886A/BF pair */
-               break;
-       case PCI_VENDOR_ID_OPTI:
-               if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
-                               !(PCI_FUNC(dev->devfn) & 1))
-                       goto out;
-               break;
-       case PCI_VENDOR_ID_JMICRON:
-               if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
-                               PCI_FUNC(dev->devfn) != 1)
-                       goto out;
-               break;
-       case PCI_VENDOR_ID_NS:
-               if (dev->device == PCI_DEVICE_ID_NS_87410 &&
-                               (dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
-                       goto out;
-               break;
-       }
-
-       if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
-               u16 command;
-               pci_read_config_word(dev, PCI_COMMAND, &command);
-               if (!(command & PCI_COMMAND_IO)) {
-                       printk(KERN_INFO "%s %s: skipping disabled "
-                               "controller\n", d->name, pci_name(dev));
-                       goto out;
-               }
-       }
-       ret = ide_pci_init_one(dev, d, NULL);
-out:
-       return ret;
-}
-
-static const struct pci_device_id generic_pci_tbl[] = {
-       { PCI_VDEVICE(NS,       PCI_DEVICE_ID_NS_87410),                 1 },
-       { PCI_VDEVICE(PCTECH,   PCI_DEVICE_ID_PCTECH_SAMURAI_IDE),       2 },
-       { PCI_VDEVICE(HOLTEK,   PCI_DEVICE_ID_HOLTEK_6565),              2 },
-       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8673F),              3 },
-       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886A),              3 },
-       { PCI_VDEVICE(UMC,      PCI_DEVICE_ID_UMC_UM8886BF),             3 },
-       { PCI_VDEVICE(HINT,     PCI_DEVICE_ID_HINT_VXPROII_IDE),         2 },
-       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_82C561),               4 },
-       { PCI_VDEVICE(OPTI,     PCI_DEVICE_ID_OPTI_82C558),              4 },
-#ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(VIA,      PCI_DEVICE_ID_VIA_8237_SATA),            5 },
-#endif
-       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO),          4 },
-       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_1),        4 },
-       { PCI_VDEVICE(TOSHIBA,  PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),        4 },
-       { PCI_VDEVICE(NETCELL,  PCI_DEVICE_ID_REVOLUTION),               6 },
-       /*
-        * Must come last.  If you add entries adjust
-        * this table and generic_chipsets[] appropriately.
-        */
-       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
-
-static struct pci_driver generic_pci_driver = {
-       .name           = "PCI_IDE",
-       .id_table       = generic_pci_tbl,
-       .probe          = generic_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init generic_ide_init(void)
-{
-       return ide_pci_register_driver(&generic_pci_driver);
-}
-
-static void __exit generic_ide_exit(void)
-{
-       pci_unregister_driver(&generic_pci_driver);
-}
-
-module_init(generic_ide_init);
-module_exit(generic_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
deleted file mode 100644 (file)
index a7909e9..0000000
+++ /dev/null
@@ -1,1643 +0,0 @@
-/*
- * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
- * Portions Copyright (C) 2001         Sun Microsystems, Inc.
- * Portions Copyright (C) 2003         Red Hat Inc
- * Portions Copyright (C) 2007         Bartlomiej Zolnierkiewicz
- * Portions Copyright (C) 2005-2008    MontaVista Software, Inc.
- *
- * Thanks to HighPoint Technologies for their assistance, and hardware.
- * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
- * donation of an ABit BP6 mainboard, processor, and memory acellerated
- * development and support.
- *
- *
- * HighPoint has its own drivers (open source except for the RAID part)
- * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
- * This may be useful to anyone wanting to work on this driver, however  do not
- * trust  them too much since the code tends to become less and less meaningful
- * as the time passes... :-/
- *
- * Note that final HPT370 support was done by force extraction of GPL.
- *
- * - add function for getting/setting power status of drive
- * - the HPT370's state machine can get confused. reset it before each dma 
- *   xfer to prevent that from happening.
- * - reset state engine whenever we get an error.
- * - check for busmaster state at end of dma. 
- * - use new highpoint timings.
- * - detect bus speed using highpoint register.
- * - use pll if we don't have a clock table. added a 66MHz table that's
- *   just 2x the 33MHz table.
- * - removed turnaround. NOTE: we never want to switch between pll and
- *   pci clocks as the chip can glitch in those cases. the highpoint
- *   approved workaround slows everything down too much to be useful. in
- *   addition, we would have to serialize access to each chip.
- *     Adrian Sun <a.sun@sun.com>
- *
- * add drive timings for 66MHz PCI bus,
- * fix ATA Cable signal detection, fix incorrect /proc info
- * add /proc display for per-drive PIO/DMA/UDMA mode and
- * per-channel ATA-33/66 Cable detect.
- *     Duncan Laurie <void@sun.com>
- *
- * fixup /proc output for multiple controllers
- *     Tim Hockin <thockin@sun.com>
- *
- * On hpt366: 
- * Reset the hpt366 on error, reset on dma
- * Fix disabling Fast Interrupt hpt366.
- *     Mike Waychison <crlf@sun.com>
- *
- * Added support for 372N clocking and clock switching. The 372N needs
- * different clocks on read/write. This requires overloading rw_disk and
- * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
- * keeping me sane. 
- *             Alan Cox <alan@redhat.com>
- *
- * - fix the clock turnaround code: it was writing to the wrong ports when
- *   called for the secondary channel, caching the current clock mode per-
- *   channel caused the cached register value to get out of sync with the
- *   actual one, the channels weren't serialized, the turnaround shouldn't
- *   be done on 66 MHz PCI bus
- * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used
- *   does not allow for this speed anyway
- * - avoid touching disabled channels (e.g. HPT371/N are single channel chips,
- *   their primary channel is kind of virtual, it isn't tied to any pins)
- * - fix/remove bad/unused timing tables and use one set of tables for the whole
- *   HPT37x chip family; save space by introducing the separate transfer mode
- *   table in which the mode lookup is done
- * - use f_CNT value saved by  the HighPoint BIOS as reading it directly gives
- *   the wrong PCI frequency since DPLL has already been calibrated by BIOS;
- *   read it only from the function 0 of HPT374 chips
- * - fix the hotswap code:  it caused RESET- to glitch when tristating the bus,
- *   and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
- * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
- *   they tamper with its fields
- * - pass  to the init_setup handlers a copy of the ide_pci_device_t structure
- *   since they may tamper with its fields
- * - prefix the driver startup messages with the real chip name
- * - claim the extra 240 bytes of I/O space for all chips
- * - optimize the UltraDMA filtering and the drive list lookup code
- * - use pci_get_slot() to get to the function 1 of HPT36x/374
- * - cache offset of the channel's misc. control registers (MCRs) being used
- *   throughout the driver
- * - only touch the relevant MCR when detecting the cable type on HPT374's
- *   function 1
- * - rename all the register related variables consistently
- * - move all the interrupt twiddling code from the speedproc handlers into
- *   init_hwif_hpt366(), also grouping all the DMA related code together there
- * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
- *   separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
- *   when setting an UltraDMA mode
- * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
- *   the best possible one
- * - clean up DMA timeout handling for HPT370
- * - switch to using the enumeration type to differ between the numerous chip
- *   variants, matching PCI device/revision ID with the chip type early, at the
- *   init_setup stage
- * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies,
- *   stop duplicating it for each channel by storing the pointer in the pci_dev
- *   structure: first, at the init_setup stage, point it to a static "template"
- *   with only the chip type and its specific base DPLL frequency, the highest
- *   UltraDMA mode, and the chip settings table pointer filled,  then, at the
- *   init_chipset stage, allocate per-chip instance  and fill it with the rest
- *   of the necessary information
- * - get rid of the constant thresholds in the HPT37x PCI clock detection code,
- *   switch  to calculating  PCI clock frequency based on the chip's base DPLL
- *   frequency
- * - switch to using the  DPLL clock and enable UltraATA/133 mode by default on
- *   anything  newer than HPT370/A (except HPT374 that is not capable of this
- *   mode according to the manual)
- * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
- *   also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
- *   unify HPT36x/37x timing setup code and the speedproc handlers by joining
- *   the register setting lists into the table indexed by the clock selected
- * - set the correct hwif->ultra_mask for each individual chip
- * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
- *     Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/blkdev.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define DRV_NAME "hpt366"
-
-/* various tuning parameters */
-#define HPT_RESET_STATE_ENGINE
-#undef HPT_DELAY_INTERRUPT
-#define HPT_SERIALIZE_IO       0
-
-static const char *quirk_drives[] = {
-       "QUANTUM FIREBALLlct08 08",
-       "QUANTUM FIREBALLP KA6.4",
-       "QUANTUM FIREBALLP LM20.4",
-       "QUANTUM FIREBALLP LM20.5",
-       NULL
-};
-
-static const char *bad_ata100_5[] = {
-       "IBM-DTLA-307075",
-       "IBM-DTLA-307060",
-       "IBM-DTLA-307045",
-       "IBM-DTLA-307030",
-       "IBM-DTLA-307020",
-       "IBM-DTLA-307015",
-       "IBM-DTLA-305040",
-       "IBM-DTLA-305030",
-       "IBM-DTLA-305020",
-       "IC35L010AVER07-0",
-       "IC35L020AVER07-0",
-       "IC35L030AVER07-0",
-       "IC35L040AVER07-0",
-       "IC35L060AVER07-0",
-       "WDC AC310200R",
-       NULL
-};
-
-static const char *bad_ata66_4[] = {
-       "IBM-DTLA-307075",
-       "IBM-DTLA-307060",
-       "IBM-DTLA-307045",
-       "IBM-DTLA-307030",
-       "IBM-DTLA-307020",
-       "IBM-DTLA-307015",
-       "IBM-DTLA-305040",
-       "IBM-DTLA-305030",
-       "IBM-DTLA-305020",
-       "IC35L010AVER07-0",
-       "IC35L020AVER07-0",
-       "IC35L030AVER07-0",
-       "IC35L040AVER07-0",
-       "IC35L060AVER07-0",
-       "WDC AC310200R",
-       "MAXTOR STM3320620A",
-       NULL
-};
-
-static const char *bad_ata66_3[] = {
-       "WDC AC310200R",
-       NULL
-};
-
-static const char *bad_ata33[] = {
-       "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
-       "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
-       "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
-       "Maxtor 90510D4",
-       "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
-       "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
-       "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
-       NULL
-};
-
-static u8 xfer_speeds[] = {
-       XFER_UDMA_6,
-       XFER_UDMA_5,
-       XFER_UDMA_4,
-       XFER_UDMA_3,
-       XFER_UDMA_2,
-       XFER_UDMA_1,
-       XFER_UDMA_0,
-
-       XFER_MW_DMA_2,
-       XFER_MW_DMA_1,
-       XFER_MW_DMA_0,
-
-       XFER_PIO_4,
-       XFER_PIO_3,
-       XFER_PIO_2,
-       XFER_PIO_1,
-       XFER_PIO_0
-};
-
-/* Key for bus clock timings
- * 36x   37x
- * bits  bits
- * 0:3  0:3    data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
- *             cycles = value + 1
- * 4:7  4:8    data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
- *             cycles = value + 1
- * 8:11  9:12  cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
- *             register access.
- * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
- *             register access.
- * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
- * -    21     CLK frequency: 0=ATA clock, 1=dual ATA clock.
- * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
- *             MW DMA xfer.
- * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
- *             task file register access.
- * 28   28     UDMA enable.
- * 29   29     DMA  enable.
- * 30   30     PIO MST enable. If set, the chip is in bus master mode during
- *             PIO xfer.
- * 31   31     FIFO enable.
- */
-
-static u32 forty_base_hpt36x[] = {
-       /* XFER_UDMA_6 */       0x900fd943,
-       /* XFER_UDMA_5 */       0x900fd943,
-       /* XFER_UDMA_4 */       0x900fd943,
-       /* XFER_UDMA_3 */       0x900ad943,
-       /* XFER_UDMA_2 */       0x900bd943,
-       /* XFER_UDMA_1 */       0x9008d943,
-       /* XFER_UDMA_0 */       0x9008d943,
-
-       /* XFER_MW_DMA_2 */     0xa008d943,
-       /* XFER_MW_DMA_1 */     0xa010d955,
-       /* XFER_MW_DMA_0 */     0xa010d9fc,
-
-       /* XFER_PIO_4 */        0xc008d963,
-       /* XFER_PIO_3 */        0xc010d974,
-       /* XFER_PIO_2 */        0xc010d997,
-       /* XFER_PIO_1 */        0xc010d9c7,
-       /* XFER_PIO_0 */        0xc018d9d9
-};
-
-static u32 thirty_three_base_hpt36x[] = {
-       /* XFER_UDMA_6 */       0x90c9a731,
-       /* XFER_UDMA_5 */       0x90c9a731,
-       /* XFER_UDMA_4 */       0x90c9a731,
-       /* XFER_UDMA_3 */       0x90cfa731,
-       /* XFER_UDMA_2 */       0x90caa731,
-       /* XFER_UDMA_1 */       0x90cba731,
-       /* XFER_UDMA_0 */       0x90c8a731,
-
-       /* XFER_MW_DMA_2 */     0xa0c8a731,
-       /* XFER_MW_DMA_1 */     0xa0c8a732,     /* 0xa0c8a733 */
-       /* XFER_MW_DMA_0 */     0xa0c8a797,
-
-       /* XFER_PIO_4 */        0xc0c8a731,
-       /* XFER_PIO_3 */        0xc0c8a742,
-       /* XFER_PIO_2 */        0xc0d0a753,
-       /* XFER_PIO_1 */        0xc0d0a7a3,     /* 0xc0d0a793 */
-       /* XFER_PIO_0 */        0xc0d0a7aa      /* 0xc0d0a7a7 */
-};
-
-static u32 twenty_five_base_hpt36x[] = {
-       /* XFER_UDMA_6 */       0x90c98521,
-       /* XFER_UDMA_5 */       0x90c98521,
-       /* XFER_UDMA_4 */       0x90c98521,
-       /* XFER_UDMA_3 */       0x90cf8521,
-       /* XFER_UDMA_2 */       0x90cf8521,
-       /* XFER_UDMA_1 */       0x90cb8521,
-       /* XFER_UDMA_0 */       0x90cb8521,
-
-       /* XFER_MW_DMA_2 */     0xa0ca8521,
-       /* XFER_MW_DMA_1 */     0xa0ca8532,
-       /* XFER_MW_DMA_0 */     0xa0ca8575,
-
-       /* XFER_PIO_4 */        0xc0ca8521,
-       /* XFER_PIO_3 */        0xc0ca8532,
-       /* XFER_PIO_2 */        0xc0ca8542,
-       /* XFER_PIO_1 */        0xc0d08572,
-       /* XFER_PIO_0 */        0xc0d08585
-};
-
-#if 0
-/* These are the timing tables from the HighPoint open source drivers... */
-static u32 thirty_three_base_hpt37x[] = {
-       /* XFER_UDMA_6 */       0x12446231,     /* 0x12646231 ?? */
-       /* XFER_UDMA_5 */       0x12446231,
-       /* XFER_UDMA_4 */       0x12446231,
-       /* XFER_UDMA_3 */       0x126c6231,
-       /* XFER_UDMA_2 */       0x12486231,
-       /* XFER_UDMA_1 */       0x124c6233,
-       /* XFER_UDMA_0 */       0x12506297,
-
-       /* XFER_MW_DMA_2 */     0x22406c31,
-       /* XFER_MW_DMA_1 */     0x22406c33,
-       /* XFER_MW_DMA_0 */     0x22406c97,
-
-       /* XFER_PIO_4 */        0x06414e31,
-       /* XFER_PIO_3 */        0x06414e42,
-       /* XFER_PIO_2 */        0x06414e53,
-       /* XFER_PIO_1 */        0x06814e93,
-       /* XFER_PIO_0 */        0x06814ea7
-};
-
-static u32 fifty_base_hpt37x[] = {
-       /* XFER_UDMA_6 */       0x12848242,
-       /* XFER_UDMA_5 */       0x12848242,
-       /* XFER_UDMA_4 */       0x12ac8242,
-       /* XFER_UDMA_3 */       0x128c8242,
-       /* XFER_UDMA_2 */       0x120c8242,
-       /* XFER_UDMA_1 */       0x12148254,
-       /* XFER_UDMA_0 */       0x121882ea,
-
-       /* XFER_MW_DMA_2 */     0x22808242,
-       /* XFER_MW_DMA_1 */     0x22808254,
-       /* XFER_MW_DMA_0 */     0x228082ea,
-
-       /* XFER_PIO_4 */        0x0a81f442,
-       /* XFER_PIO_3 */        0x0a81f443,
-       /* XFER_PIO_2 */        0x0a81f454,
-       /* XFER_PIO_1 */        0x0ac1f465,
-       /* XFER_PIO_0 */        0x0ac1f48a
-};
-
-static u32 sixty_six_base_hpt37x[] = {
-       /* XFER_UDMA_6 */       0x1c869c62,
-       /* XFER_UDMA_5 */       0x1cae9c62,     /* 0x1c8a9c62 */
-       /* XFER_UDMA_4 */       0x1c8a9c62,
-       /* XFER_UDMA_3 */       0x1c8e9c62,
-       /* XFER_UDMA_2 */       0x1c929c62,
-       /* XFER_UDMA_1 */       0x1c9a9c62,
-       /* XFER_UDMA_0 */       0x1c829c62,
-
-       /* XFER_MW_DMA_2 */     0x2c829c62,
-       /* XFER_MW_DMA_1 */     0x2c829c66,
-       /* XFER_MW_DMA_0 */     0x2c829d2e,
-
-       /* XFER_PIO_4 */        0x0c829c62,
-       /* XFER_PIO_3 */        0x0c829c84,
-       /* XFER_PIO_2 */        0x0c829ca6,
-       /* XFER_PIO_1 */        0x0d029d26,
-       /* XFER_PIO_0 */        0x0d029d5e
-};
-#else
-/*
- * The following are the new timing tables with PIO mode data/taskfile transfer
- * overclocking fixed...
- */
-
-/* This table is taken from the HPT370 data manual rev. 1.02 */
-static u32 thirty_three_base_hpt37x[] = {
-       /* XFER_UDMA_6 */       0x16455031,     /* 0x16655031 ?? */
-       /* XFER_UDMA_5 */       0x16455031,
-       /* XFER_UDMA_4 */       0x16455031,
-       /* XFER_UDMA_3 */       0x166d5031,
-       /* XFER_UDMA_2 */       0x16495031,
-       /* XFER_UDMA_1 */       0x164d5033,
-       /* XFER_UDMA_0 */       0x16515097,
-
-       /* XFER_MW_DMA_2 */     0x26515031,
-       /* XFER_MW_DMA_1 */     0x26515033,
-       /* XFER_MW_DMA_0 */     0x26515097,
-
-       /* XFER_PIO_4 */        0x06515021,
-       /* XFER_PIO_3 */        0x06515022,
-       /* XFER_PIO_2 */        0x06515033,
-       /* XFER_PIO_1 */        0x06915065,
-       /* XFER_PIO_0 */        0x06d1508a
-};
-
-static u32 fifty_base_hpt37x[] = {
-       /* XFER_UDMA_6 */       0x1a861842,
-       /* XFER_UDMA_5 */       0x1a861842,
-       /* XFER_UDMA_4 */       0x1aae1842,
-       /* XFER_UDMA_3 */       0x1a8e1842,
-       /* XFER_UDMA_2 */       0x1a0e1842,
-       /* XFER_UDMA_1 */       0x1a161854,
-       /* XFER_UDMA_0 */       0x1a1a18ea,
-
-       /* XFER_MW_DMA_2 */     0x2a821842,
-       /* XFER_MW_DMA_1 */     0x2a821854,
-       /* XFER_MW_DMA_0 */     0x2a8218ea,
-
-       /* XFER_PIO_4 */        0x0a821842,
-       /* XFER_PIO_3 */        0x0a821843,
-       /* XFER_PIO_2 */        0x0a821855,
-       /* XFER_PIO_1 */        0x0ac218a8,
-       /* XFER_PIO_0 */        0x0b02190c
-};
-
-static u32 sixty_six_base_hpt37x[] = {
-       /* XFER_UDMA_6 */       0x1c86fe62,
-       /* XFER_UDMA_5 */       0x1caefe62,     /* 0x1c8afe62 */
-       /* XFER_UDMA_4 */       0x1c8afe62,
-       /* XFER_UDMA_3 */       0x1c8efe62,
-       /* XFER_UDMA_2 */       0x1c92fe62,
-       /* XFER_UDMA_1 */       0x1c9afe62,
-       /* XFER_UDMA_0 */       0x1c82fe62,
-
-       /* XFER_MW_DMA_2 */     0x2c82fe62,
-       /* XFER_MW_DMA_1 */     0x2c82fe66,
-       /* XFER_MW_DMA_0 */     0x2c82ff2e,
-
-       /* XFER_PIO_4 */        0x0c82fe62,
-       /* XFER_PIO_3 */        0x0c82fe84,
-       /* XFER_PIO_2 */        0x0c82fea6,
-       /* XFER_PIO_1 */        0x0d02ff26,
-       /* XFER_PIO_0 */        0x0d42ff7f
-};
-#endif
-
-#define HPT366_DEBUG_DRIVE_INFO                0
-#define HPT371_ALLOW_ATA133_6          1
-#define HPT302_ALLOW_ATA133_6          1
-#define HPT372_ALLOW_ATA133_6          1
-#define HPT370_ALLOW_ATA100_5          0
-#define HPT366_ALLOW_ATA66_4           1
-#define HPT366_ALLOW_ATA66_3           1
-#define HPT366_MAX_DEVS                        8
-
-/* Supported ATA clock frequencies */
-enum ata_clock {
-       ATA_CLOCK_25MHZ,
-       ATA_CLOCK_33MHZ,
-       ATA_CLOCK_40MHZ,
-       ATA_CLOCK_50MHZ,
-       ATA_CLOCK_66MHZ,
-       NUM_ATA_CLOCKS
-};
-
-struct hpt_timings {
-       u32 pio_mask;
-       u32 dma_mask;
-       u32 ultra_mask;
-       u32 *clock_table[NUM_ATA_CLOCKS];
-};
-
-/*
- *     Hold all the HighPoint chip information in one place.
- */
-
-struct hpt_info {
-       char *chip_name;        /* Chip name */
-       u8 chip_type;           /* Chip type */
-       u8 udma_mask;           /* Allowed UltraDMA modes mask. */
-       u8 dpll_clk;            /* DPLL clock in MHz */
-       u8 pci_clk;             /* PCI  clock in MHz */
-       struct hpt_timings *timings; /* Chipset timing data */
-       u8 clock;               /* ATA clock selected */
-};
-
-/* Supported HighPoint chips */
-enum {
-       HPT36x,
-       HPT370,
-       HPT370A,
-       HPT374,
-       HPT372,
-       HPT372A,
-       HPT302,
-       HPT371,
-       HPT372N,
-       HPT302N,
-       HPT371N
-};
-
-static struct hpt_timings hpt36x_timings = {
-       .pio_mask       = 0xc1f8ffff,
-       .dma_mask       = 0x303800ff,
-       .ultra_mask     = 0x30070000,
-       .clock_table    = {
-               [ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
-               [ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
-               [ATA_CLOCK_40MHZ] = forty_base_hpt36x,
-               [ATA_CLOCK_50MHZ] = NULL,
-               [ATA_CLOCK_66MHZ] = NULL
-       }
-};
-
-static struct hpt_timings hpt37x_timings = {
-       .pio_mask       = 0xcfc3ffff,
-       .dma_mask       = 0x31c001ff,
-       .ultra_mask     = 0x303c0000,
-       .clock_table    = {
-               [ATA_CLOCK_25MHZ] = NULL,
-               [ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
-               [ATA_CLOCK_40MHZ] = NULL,
-               [ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
-               [ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
-       }
-};
-
-static const struct hpt_info hpt36x __devinitdata = {
-       .chip_name      = "HPT36x",
-       .chip_type      = HPT36x,
-       .udma_mask      = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
-       .dpll_clk       = 0,    /* no DPLL */
-       .timings        = &hpt36x_timings
-};
-
-static const struct hpt_info hpt370 __devinitdata = {
-       .chip_name      = "HPT370",
-       .chip_type      = HPT370,
-       .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
-       .dpll_clk       = 48,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt370a __devinitdata = {
-       .chip_name      = "HPT370A",
-       .chip_type      = HPT370A,
-       .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
-       .dpll_clk       = 48,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt374 __devinitdata = {
-       .chip_name      = "HPT374",
-       .chip_type      = HPT374,
-       .udma_mask      = ATA_UDMA5,
-       .dpll_clk       = 48,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt372 __devinitdata = {
-       .chip_name      = "HPT372",
-       .chip_type      = HPT372,
-       .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 55,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt372a __devinitdata = {
-       .chip_name      = "HPT372A",
-       .chip_type      = HPT372A,
-       .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 66,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt302 __devinitdata = {
-       .chip_name      = "HPT302",
-       .chip_type      = HPT302,
-       .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 66,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt371 __devinitdata = {
-       .chip_name      = "HPT371",
-       .chip_type      = HPT371,
-       .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 66,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt372n __devinitdata = {
-       .chip_name      = "HPT372N",
-       .chip_type      = HPT372N,
-       .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 77,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt302n __devinitdata = {
-       .chip_name      = "HPT302N",
-       .chip_type      = HPT302N,
-       .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 77,
-       .timings        = &hpt37x_timings
-};
-
-static const struct hpt_info hpt371n __devinitdata = {
-       .chip_name      = "HPT371N",
-       .chip_type      = HPT371N,
-       .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
-       .dpll_clk       = 77,
-       .timings        = &hpt37x_timings
-};
-
-static int check_in_drive_list(ide_drive_t *drive, const char **list)
-{
-       char *m = (char *)&drive->id[ATA_ID_PROD];
-
-       while (*list)
-               if (!strcmp(*list++, m))
-                       return 1;
-       return 0;
-}
-
-static struct hpt_info *hpt3xx_get_info(struct device *dev)
-{
-       struct ide_host *host   = dev_get_drvdata(dev);
-       struct hpt_info *info   = (struct hpt_info *)host->host_priv;
-
-       return dev == host->dev[1] ? info + 1 : info;
-}
-
-/*
- * The Marvell bridge chips used on the HighPoint SATA cards do not seem
- * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
- */
-
-static u8 hpt3xx_udma_filter(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
-       u8 mask                 = hwif->ultra_mask;
-
-       switch (info->chip_type) {
-       case HPT36x:
-               if (!HPT366_ALLOW_ATA66_4 ||
-                   check_in_drive_list(drive, bad_ata66_4))
-                       mask = ATA_UDMA3;
-
-               if (!HPT366_ALLOW_ATA66_3 ||
-                   check_in_drive_list(drive, bad_ata66_3))
-                       mask = ATA_UDMA2;
-               break;
-       case HPT370:
-               if (!HPT370_ALLOW_ATA100_5 ||
-                   check_in_drive_list(drive, bad_ata100_5))
-                       mask = ATA_UDMA4;
-               break;
-       case HPT370A:
-               if (!HPT370_ALLOW_ATA100_5 ||
-                   check_in_drive_list(drive, bad_ata100_5))
-                       return ATA_UDMA4;
-       case HPT372 :
-       case HPT372A:
-       case HPT372N:
-       case HPT374 :
-               if (ata_id_is_sata(drive->id))
-                       mask &= ~0x0e;
-               /* Fall thru */
-       default:
-               return mask;
-       }
-
-       return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
-}
-
-static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
-
-       switch (info->chip_type) {
-       case HPT372 :
-       case HPT372A:
-       case HPT372N:
-       case HPT374 :
-               if (ata_id_is_sata(drive->id))
-                       return 0x00;
-               /* Fall thru */
-       default:
-               return 0x07;
-       }
-}
-
-static u32 get_speed_setting(u8 speed, struct hpt_info *info)
-{
-       int i;
-
-       /*
-        * Lookup the transfer mode table to get the index into
-        * the timing table.
-        *
-        * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
-        */
-       for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
-               if (xfer_speeds[i] == speed)
-                       break;
-
-       return info->timings->clock_table[info->clock][i];
-}
-
-static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif        = drive->hwif;
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
-       struct hpt_timings *t   = info->timings;
-       u8  itr_addr            = 0x40 + (drive->dn * 4);
-       u32 old_itr             = 0;
-       u32 new_itr             = get_speed_setting(speed, info);
-       u32 itr_mask            = speed < XFER_MW_DMA_0 ? t->pio_mask :
-                                (speed < XFER_UDMA_0   ? t->dma_mask :
-                                                         t->ultra_mask);
-
-       pci_read_config_dword(dev, itr_addr, &old_itr);
-       new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
-       /*
-        * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
-        * to avoid problems handling I/O errors later
-        */
-       new_itr &= ~0xc0000000;
-
-       pci_write_config_dword(dev, itr_addr, new_itr);
-}
-
-static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
-}
-
-static void hpt3xx_quirkproc(ide_drive_t *drive)
-{
-       char *m                 = (char *)&drive->id[ATA_ID_PROD];
-       const  char **list      = quirk_drives;
-
-       while (*list)
-               if (strstr(m, *list++)) {
-                       drive->quirk_list = 1;
-                       return;
-               }
-
-       drive->quirk_list = 0;
-}
-
-static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev  *dev    = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
-
-       if (drive->quirk_list == 0)
-               return;
-
-       if (info->chip_type >= HPT370) {
-               u8 scr1 = 0;
-
-               pci_read_config_byte(dev, 0x5a, &scr1);
-               if (((scr1 & 0x10) >> 4) != mask) {
-                       if (mask)
-                               scr1 |=  0x10;
-                       else
-                               scr1 &= ~0x10;
-                       pci_write_config_byte(dev, 0x5a, scr1);
-               }
-       } else if (mask)
-               disable_irq(hwif->irq);
-       else
-               enable_irq(hwif->irq);
-}
-
-/*
- * This is specific to the HPT366 UDMA chipset
- * by HighPoint|Triones Technologies, Inc.
- */
-static void hpt366_dma_lost_irq(ide_drive_t *drive)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
-
-       pci_read_config_byte(dev, 0x50, &mcr1);
-       pci_read_config_byte(dev, 0x52, &mcr3);
-       pci_read_config_byte(dev, 0x5a, &scr1);
-       printk("%s: (%s)  mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",
-               drive->name, __func__, mcr1, mcr3, scr1);
-       if (scr1 & 0x10)
-               pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
-       ide_dma_lost_irq(drive);
-}
-
-static void hpt370_clear_engine(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       pci_write_config_byte(dev, hwif->select_data, 0x37);
-       udelay(10);
-}
-
-static void hpt370_irq_timeout(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u16 bfifo               = 0;
-       u8  dma_cmd;
-
-       pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
-       printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
-
-       /* get DMA command mode */
-       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-       /* stop DMA */
-       outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
-       hpt370_clear_engine(drive);
-}
-
-static void hpt370_dma_start(ide_drive_t *drive)
-{
-#ifdef HPT_RESET_STATE_ENGINE
-       hpt370_clear_engine(drive);
-#endif
-       ide_dma_start(drive);
-}
-
-static int hpt370_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8  dma_stat            = inb(hwif->dma_base + ATA_DMA_STATUS);
-
-       if (dma_stat & 0x01) {
-               /* wait a little */
-               udelay(20);
-               dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
-               if (dma_stat & 0x01)
-                       hpt370_irq_timeout(drive);
-       }
-       return ide_dma_end(drive);
-}
-
-static void hpt370_dma_timeout(ide_drive_t *drive)
-{
-       hpt370_irq_timeout(drive);
-       ide_dma_timeout(drive);
-}
-
-/* returns 1 if DMA IRQ issued, 0 otherwise */
-static int hpt374_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u16 bfifo               = 0;
-       u8  dma_stat;
-
-       pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
-       if (bfifo & 0x1FF) {
-//             printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
-               return 0;
-       }
-
-       dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
-       /* return 1 if INTR asserted */
-       if (dma_stat & 4)
-               return 1;
-
-       return 0;
-}
-
-static int hpt374_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 mcr  = 0, mcr_addr   = hwif->select_data;
-       u8 bwsr = 0, mask       = hwif->channel ? 0x02 : 0x01;
-
-       pci_read_config_byte(dev, 0x6a, &bwsr);
-       pci_read_config_byte(dev, mcr_addr, &mcr);
-       if (bwsr & mask)
-               pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
-       return ide_dma_end(drive);
-}
-
-/**
- *     hpt3xxn_set_clock       -       perform clock switching dance
- *     @hwif: hwif to switch
- *     @mode: clocking mode (0x21 for write, 0x23 otherwise)
- *
- *     Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
- */
-
-static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
-{
-       unsigned long base = hwif->extra_base;
-       u8 scr2 = inb(base + 0x6b);
-
-       if ((scr2 & 0x7f) == mode)
-               return;
-
-       /* Tristate the bus */
-       outb(0x80, base + 0x63);
-       outb(0x80, base + 0x67);
-
-       /* Switch clock and reset channels */
-       outb(mode, base + 0x6b);
-       outb(0xc0, base + 0x69);
-
-       /*
-        * Reset the state machines.
-        * NOTE: avoid accidentally enabling the disabled channels.
-        */
-       outb(inb(base + 0x60) | 0x32, base + 0x60);
-       outb(inb(base + 0x64) | 0x32, base + 0x64);
-
-       /* Complete reset */
-       outb(0x00, base + 0x69);
-
-       /* Reconnect channels to bus */
-       outb(0x00, base + 0x63);
-       outb(0x00, base + 0x67);
-}
-
-/**
- *     hpt3xxn_rw_disk         -       prepare for I/O
- *     @drive: drive for command
- *     @rq: block request structure
- *
- *     This is called when a disk I/O is issued to HPT3xxN.
- *     We need it because of the clock switching.
- */
-
-static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
-{
-       hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
-}
-
-/**
- *     hpt37x_calibrate_dpll   -       calibrate the DPLL
- *     @dev: PCI device
- *
- *     Perform a calibration cycle on the DPLL.
- *     Returns 1 if this succeeds
- */
-static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
-{
-       u32 dpll = (f_high << 16) | f_low | 0x100;
-       u8  scr2;
-       int i;
-
-       pci_write_config_dword(dev, 0x5c, dpll);
-
-       /* Wait for oscillator ready */
-       for(i = 0; i < 0x5000; ++i) {
-               udelay(50);
-               pci_read_config_byte(dev, 0x5b, &scr2);
-               if (scr2 & 0x80)
-                       break;
-       }
-       /* See if it stays ready (we'll just bail out if it's not yet) */
-       for(i = 0; i < 0x1000; ++i) {
-               pci_read_config_byte(dev, 0x5b, &scr2);
-               /* DPLL destabilized? */
-               if(!(scr2 & 0x80))
-                       return 0;
-       }
-       /* Turn off tuning, we have the DPLL set */
-       pci_read_config_dword (dev, 0x5c, &dpll);
-       pci_write_config_dword(dev, 0x5c, (dpll & ~0x100));
-       return 1;
-}
-
-static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
-{
-       struct ide_host *host   = pci_get_drvdata(dev);
-       struct hpt_info *info   = host->host_priv + (&dev->dev == host->dev[1]);
-       u8  chip_type           = info->chip_type;
-       u8  new_mcr, old_mcr    = 0;
-
-       /*
-        * Disable the "fast interrupt" prediction.  Don't hold off
-        * on interrupts. (== 0x01 despite what the docs say)
-        */
-       pci_read_config_byte(dev, mcr_addr + 1, &old_mcr);
-
-       if (chip_type >= HPT374)
-               new_mcr = old_mcr & ~0x07;
-       else if (chip_type >= HPT370) {
-               new_mcr = old_mcr;
-               new_mcr &= ~0x02;
-#ifdef HPT_DELAY_INTERRUPT
-               new_mcr &= ~0x01;
-#else
-               new_mcr |=  0x01;
-#endif
-       } else                                  /* HPT366 and HPT368  */
-               new_mcr = old_mcr & ~0x80;
-
-       if (new_mcr != old_mcr)
-               pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
-}
-
-static unsigned int init_chipset_hpt366(struct pci_dev *dev)
-{
-       unsigned long io_base   = pci_resource_start(dev, 4);
-       struct hpt_info *info   = hpt3xx_get_info(&dev->dev);
-       const char *name        = DRV_NAME;
-       u8 pci_clk,  dpll_clk   = 0;    /* PCI and DPLL clock in MHz */
-       u8 chip_type;
-       enum ata_clock  clock;
-
-       chip_type = info->chip_type;
-
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
-       pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
-       pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
-
-       /*
-        * First, try to estimate the PCI clock frequency...
-        */
-       if (chip_type >= HPT370) {
-               u8  scr1  = 0;
-               u16 f_cnt = 0;
-               u32 temp  = 0;
-
-               /* Interrupt force enable. */
-               pci_read_config_byte(dev, 0x5a, &scr1);
-               if (scr1 & 0x10)
-                       pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
-
-               /*
-                * HighPoint does this for HPT372A.
-                * NOTE: This register is only writeable via I/O space.
-                */
-               if (chip_type == HPT372A)
-                       outb(0x0e, io_base + 0x9c);
-
-               /*
-                * Default to PCI clock. Make sure MA15/16 are set to output
-                * to prevent drives having problems with 40-pin cables.
-                */
-               pci_write_config_byte(dev, 0x5b, 0x23);
-
-               /*
-                * We'll have to read f_CNT value in order to determine
-                * the PCI clock frequency according to the following ratio:
-                *
-                * f_CNT = Fpci * 192 / Fdpll
-                *
-                * First try reading the register in which the HighPoint BIOS
-                * saves f_CNT value before  reprogramming the DPLL from its
-                * default setting (which differs for the various chips).
-                *
-                * NOTE: This register is only accessible via I/O space;
-                * HPT374 BIOS only saves it for the function 0, so we have to
-                * always read it from there -- no need to check the result of
-                * pci_get_slot() for the function 0 as the whole device has
-                * been already "pinned" (via function 1) in init_setup_hpt374()
-                */
-               if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
-                       struct pci_dev  *dev1 = pci_get_slot(dev->bus,
-                                                            dev->devfn - 1);
-                       unsigned long io_base = pci_resource_start(dev1, 4);
-
-                       temp =  inl(io_base + 0x90);
-                       pci_dev_put(dev1);
-               } else
-                       temp =  inl(io_base + 0x90);
-
-               /*
-                * In case the signature check fails, we'll have to
-                * resort to reading the f_CNT register itself in hopes
-                * that nobody has touched the DPLL yet...
-                */
-               if ((temp & 0xFFFFF000) != 0xABCDE000) {
-                       int i;
-
-                       printk(KERN_WARNING "%s %s: no clock data saved by "
-                               "BIOS\n", name, pci_name(dev));
-
-                       /* Calculate the average value of f_CNT. */
-                       for (temp = i = 0; i < 128; i++) {
-                               pci_read_config_word(dev, 0x78, &f_cnt);
-                               temp += f_cnt & 0x1ff;
-                               mdelay(1);
-                       }
-                       f_cnt = temp / 128;
-               } else
-                       f_cnt = temp & 0x1ff;
-
-               dpll_clk = info->dpll_clk;
-               pci_clk  = (f_cnt * dpll_clk) / 192;
-
-               /* Clamp PCI clock to bands. */
-               if (pci_clk < 40)
-                       pci_clk = 33;
-               else if(pci_clk < 45)
-                       pci_clk = 40;
-               else if(pci_clk < 55)
-                       pci_clk = 50;
-               else
-                       pci_clk = 66;
-
-               printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
-                       "assuming %d MHz PCI\n", name, pci_name(dev),
-                       dpll_clk, f_cnt, pci_clk);
-       } else {
-               u32 itr1 = 0;
-
-               pci_read_config_dword(dev, 0x40, &itr1);
-
-               /* Detect PCI clock by looking at cmd_high_time. */
-               switch((itr1 >> 8) & 0x07) {
-                       case 0x09:
-                               pci_clk = 40;
-                               break;
-                       case 0x05:
-                               pci_clk = 25;
-                               break;
-                       case 0x07:
-                       default:
-                               pci_clk = 33;
-                               break;
-               }
-       }
-
-       /* Let's assume we'll use PCI clock for the ATA clock... */
-       switch (pci_clk) {
-               case 25:
-                       clock = ATA_CLOCK_25MHZ;
-                       break;
-               case 33:
-               default:
-                       clock = ATA_CLOCK_33MHZ;
-                       break;
-               case 40:
-                       clock = ATA_CLOCK_40MHZ;
-                       break;
-               case 50:
-                       clock = ATA_CLOCK_50MHZ;
-                       break;
-               case 66:
-                       clock = ATA_CLOCK_66MHZ;
-                       break;
-       }
-
-       /*
-        * Only try the DPLL if we don't have a table for the PCI clock that
-        * we are running at for HPT370/A, always use it  for anything newer...
-        *
-        * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI.
-        * We also  don't like using  the DPLL because this causes glitches
-        * on PRST-/SRST- when the state engine gets reset...
-        */
-       if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
-               u16 f_low, delta = pci_clk < 50 ? 2 : 4;
-               int adjust;
-
-                /*
-                 * Select 66 MHz DPLL clock only if UltraATA/133 mode is
-                 * supported/enabled, use 50 MHz DPLL clock otherwise...
-                 */
-               if (info->udma_mask == ATA_UDMA6) {
-                       dpll_clk = 66;
-                       clock = ATA_CLOCK_66MHZ;
-               } else if (dpll_clk) {  /* HPT36x chips don't have DPLL */
-                       dpll_clk = 50;
-                       clock = ATA_CLOCK_50MHZ;
-               }
-
-               if (info->timings->clock_table[clock] == NULL) {
-                       printk(KERN_ERR "%s %s: unknown bus timing!\n",
-                               name, pci_name(dev));
-                       return -EIO;
-               }
-
-               /* Select the DPLL clock. */
-               pci_write_config_byte(dev, 0x5b, 0x21);
-
-               /*
-                * Adjust the DPLL based upon PCI clock, enable it,
-                * and wait for stabilization...
-                */
-               f_low = (pci_clk * 48) / dpll_clk;
-
-               for (adjust = 0; adjust < 8; adjust++) {
-                       if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta))
-                               break;
-
-                       /*
-                        * See if it'll settle at a fractionally different clock
-                        */
-                       if (adjust & 1)
-                               f_low -= adjust >> 1;
-                       else
-                               f_low += adjust >> 1;
-               }
-               if (adjust == 8) {
-                       printk(KERN_ERR "%s %s: DPLL did not stabilize!\n",
-                               name, pci_name(dev));
-                       return -EIO;
-               }
-
-               printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n",
-                       name, pci_name(dev), dpll_clk);
-       } else {
-               /* Mark the fact that we're not using the DPLL. */
-               dpll_clk = 0;
-
-               printk(KERN_INFO "%s %s: using %d MHz PCI clock\n",
-                       name, pci_name(dev), pci_clk);
-       }
-
-       /* Store the clock frequencies. */
-       info->dpll_clk  = dpll_clk;
-       info->pci_clk   = pci_clk;
-       info->clock     = clock;
-
-       if (chip_type >= HPT370) {
-               u8  mcr1, mcr4;
-
-               /*
-                * Reset the state engines.
-                * NOTE: Avoid accidentally enabling the disabled channels.
-                */
-               pci_read_config_byte (dev, 0x50, &mcr1);
-               pci_read_config_byte (dev, 0x54, &mcr4);
-               pci_write_config_byte(dev, 0x50, (mcr1 | 0x32));
-               pci_write_config_byte(dev, 0x54, (mcr4 | 0x32));
-               udelay(100);
-       }
-
-       /*
-        * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
-        * the MISC. register to stretch the UltraDMA Tss timing.
-        * NOTE: This register is only writeable via I/O space.
-        */
-       if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
-               outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
-
-       hpt3xx_disable_fast_irq(dev, 0x50);
-       hpt3xx_disable_fast_irq(dev, 0x54);
-
-       return dev->irq;
-}
-
-static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev  *dev    = to_pci_dev(hwif->dev);
-       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
-       u8 chip_type            = info->chip_type;
-       u8 scr1 = 0, ata66      = hwif->channel ? 0x01 : 0x02;
-
-       /*
-        * The HPT37x uses the CBLID pins as outputs for MA15/MA16
-        * address lines to access an external EEPROM.  To read valid
-        * cable detect state the pins must be enabled as inputs.
-        */
-       if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
-               /*
-                * HPT374 PCI function 1
-                * - set bit 15 of reg 0x52 to enable TCBLID as input
-                * - set bit 15 of reg 0x56 to enable FCBLID as input
-                */
-               u8  mcr_addr = hwif->select_data + 2;
-               u16 mcr;
-
-               pci_read_config_word(dev, mcr_addr, &mcr);
-               pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
-               /* now read cable id register */
-               pci_read_config_byte(dev, 0x5a, &scr1);
-               pci_write_config_word(dev, mcr_addr, mcr);
-       } else if (chip_type >= HPT370) {
-               /*
-                * HPT370/372 and 374 pcifn 0
-                * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
-                */
-               u8 scr2 = 0;
-
-               pci_read_config_byte(dev, 0x5b, &scr2);
-               pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
-               /* now read cable id register */
-               pci_read_config_byte(dev, 0x5a, &scr1);
-               pci_write_config_byte(dev, 0x5b,  scr2);
-       } else
-               pci_read_config_byte(dev, 0x5a, &scr1);
-
-       return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-}
-
-static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
-{
-       struct hpt_info *info   = hpt3xx_get_info(hwif->dev);
-       int serialize           = HPT_SERIALIZE_IO;
-       u8  chip_type           = info->chip_type;
-
-       /* Cache the channel's MISC. control registers' offset */
-       hwif->select_data       = hwif->channel ? 0x54 : 0x50;
-
-       /*
-        * HPT3xxN chips have some complications:
-        *
-        * - on 33 MHz PCI we must clock switch
-        * - on 66 MHz PCI we must NOT use the PCI clock
-        */
-       if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) {
-               /*
-                * Clock is shared between the channels,
-                * so we'll have to serialize them... :-(
-                */
-               serialize = 1;
-               hwif->rw_disk = &hpt3xxn_rw_disk;
-       }
-
-       /* Serialize access to this device if needed */
-       if (serialize && hwif->mate)
-               hwif->serialized = hwif->mate->serialized = 1;
-}
-
-static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
-                                    const struct ide_port_info *d)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned long flags, base = ide_pci_dma_base(hwif, d);
-       u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
-
-       if (base == 0)
-               return -1;
-
-       hwif->dma_base = base;
-
-       if (ide_pci_check_simplex(hwif, d) < 0)
-               return -1;
-
-       if (ide_pci_set_master(dev, d->name) < 0)
-               return -1;
-
-       dma_old = inb(base + 2);
-
-       local_irq_save(flags);
-
-       dma_new = dma_old;
-       pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma);
-       pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47,  &slavedma);
-
-       if (masterdma & 0x30)   dma_new |= 0x20;
-       if ( slavedma & 0x30)   dma_new |= 0x40;
-       if (dma_new != dma_old)
-               outb(dma_new, base + 2);
-
-       local_irq_restore(flags);
-
-       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
-                        hwif->name, base, base + 7);
-
-       hwif->extra_base = base + (hwif->channel ? 8 : 16);
-
-       if (ide_allocate_dma_engine(hwif))
-               return -1;
-
-       hwif->dma_ops = &sff_dma_ops;
-
-       return 0;
-}
-
-static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
-{
-       if (dev2->irq != dev->irq) {
-               /* FIXME: we need a core pci_set_interrupt() */
-               dev2->irq = dev->irq;
-               printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
-                       "fixed\n", pci_name(dev2));
-       }
-}
-
-static void __devinit hpt371_init(struct pci_dev *dev)
-{
-       u8 mcr1 = 0;
-
-       /*
-        * HPT371 chips physically have only one channel, the secondary one,
-        * but the primary channel registers do exist!  Go figure...
-        * So,  we manually disable the non-existing channel here
-        * (if the BIOS hasn't done this already).
-        */
-       pci_read_config_byte(dev, 0x50, &mcr1);
-       if (mcr1 & 0x04)
-               pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
-}
-
-static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
-{
-       u8 mcr1 = 0, pin1 = 0, pin2 = 0;
-
-       /*
-        * Now we'll have to force both channels enabled if
-        * at least one of them has been enabled by BIOS...
-        */
-       pci_read_config_byte(dev, 0x50, &mcr1);
-       if (mcr1 & 0x30)
-               pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
-
-       pci_read_config_byte(dev,  PCI_INTERRUPT_PIN, &pin1);
-       pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
-
-       if (pin1 != pin2 && dev->irq == dev2->irq) {
-               printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
-                       "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2);
-               return 1;
-       }
-
-       return 0;
-}
-
-#define IDE_HFLAGS_HPT3XX \
-       (IDE_HFLAG_NO_ATAPI_DMA | \
-        IDE_HFLAG_OFF_BOARD)
-
-static const struct ide_port_ops hpt3xx_port_ops = {
-       .set_pio_mode           = hpt3xx_set_pio_mode,
-       .set_dma_mode           = hpt3xx_set_mode,
-       .quirkproc              = hpt3xx_quirkproc,
-       .maskproc               = hpt3xx_maskproc,
-       .mdma_filter            = hpt3xx_mdma_filter,
-       .udma_filter            = hpt3xx_udma_filter,
-       .cable_detect           = hpt3xx_cable_detect,
-};
-
-static const struct ide_dma_ops hpt37x_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                = hpt374_dma_end,
-       .dma_test_irq           = hpt374_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_dma_ops hpt370_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = hpt370_dma_start,
-       .dma_end                = hpt370_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = hpt370_dma_timeout,
-};
-
-static const struct ide_dma_ops hpt36x_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_lost_irq           = hpt366_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
-       {       /* 0: HPT36x */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_hpt366,
-               .init_hwif      = init_hwif_hpt366,
-               .init_dma       = init_dma_hpt366,
-               /*
-                * HPT36x chips have one channel per function and have
-                * both channel enable bits located differently and visible
-                * to both functions -- really stupid design decision... :-(
-                * Bit 4 is for the primary channel, bit 5 for the secondary.
-                */
-               .enablebits     = {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
-               .port_ops       = &hpt3xx_port_ops,
-               .dma_ops        = &hpt36x_dma_ops,
-               .host_flags     = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-       },
-       {       /* 1: HPT3xx */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_hpt366,
-               .init_hwif      = init_hwif_hpt366,
-               .init_dma       = init_dma_hpt366,
-               .enablebits     = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
-               .port_ops       = &hpt3xx_port_ops,
-               .dma_ops        = &hpt37x_dma_ops,
-               .host_flags     = IDE_HFLAGS_HPT3XX,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-       }
-};
-
-/**
- *     hpt366_init_one -       called when an HPT366 is found
- *     @dev: the hpt366 device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       const struct hpt_info *info = NULL;
-       struct hpt_info *dyn_info;
-       struct pci_dev *dev2 = NULL;
-       struct ide_port_info d;
-       u8 idx = id->driver_data;
-       u8 rev = dev->revision;
-       int ret;
-
-       if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
-               return -ENODEV;
-
-       switch (idx) {
-       case 0:
-               if (rev < 3)
-                       info = &hpt36x;
-               else {
-                       switch (min_t(u8, rev, 6)) {
-                       case 3: info = &hpt370;  break;
-                       case 4: info = &hpt370a; break;
-                       case 5: info = &hpt372;  break;
-                       case 6: info = &hpt372n; break;
-                       }
-                       idx++;
-               }
-               break;
-       case 1:
-               info = (rev > 1) ? &hpt372n : &hpt372a;
-               break;
-       case 2:
-               info = (rev > 1) ? &hpt302n : &hpt302;
-               break;
-       case 3:
-               hpt371_init(dev);
-               info = (rev > 1) ? &hpt371n : &hpt371;
-               break;
-       case 4:
-               info = &hpt374;
-               break;
-       case 5:
-               info = &hpt372n;
-               break;
-       }
-
-       printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name);
-
-       d = hpt366_chipsets[min_t(u8, idx, 1)];
-
-       d.udma_mask = info->udma_mask;
-
-       /* fixup ->dma_ops for HPT370/HPT370A */
-       if (info == &hpt370 || info == &hpt370a)
-               d.dma_ops = &hpt370_dma_ops;
-
-       if (info == &hpt36x || info == &hpt374)
-               dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
-
-       dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
-       if (dyn_info == NULL) {
-               printk(KERN_ERR "%s %s: out of memory!\n",
-                       d.name, pci_name(dev));
-               pci_dev_put(dev2);
-               return -ENOMEM;
-       }
-
-       /*
-        * Copy everything from a static "template" structure
-        * to just allocated per-chip hpt_info structure.
-        */
-       memcpy(dyn_info, info, sizeof(*dyn_info));
-
-       if (dev2) {
-               memcpy(dyn_info + 1, info, sizeof(*dyn_info));
-
-               if (info == &hpt374)
-                       hpt374_init(dev, dev2);
-               else {
-                       if (hpt36x_init(dev, dev2))
-                               d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
-               }
-
-               ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
-               if (ret < 0) {
-                       pci_dev_put(dev2);
-                       kfree(dyn_info);
-               }
-               return ret;
-       }
-
-       ret = ide_pci_init_one(dev, &d, dyn_info);
-       if (ret < 0)
-               kfree(dyn_info);
-
-       return ret;
-}
-
-static void __devexit hpt366_remove(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct ide_info *info = host->host_priv;
-       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
-
-       ide_pci_remove(dev);
-       pci_dev_put(dev2);
-       kfree(info);
-}
-
-static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
-       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366),  0 },
-       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372),  1 },
-       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302),  2 },
-       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371),  3 },
-       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374),  4 },
-       { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
-
-static struct pci_driver hpt366_pci_driver = {
-       .name           = "HPT366_IDE",
-       .id_table       = hpt366_pci_tbl,
-       .probe          = hpt366_init_one,
-       .remove         = __devexit_p(hpt366_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init hpt366_ide_init(void)
-{
-       return ide_pci_register_driver(&hpt366_pci_driver);
-}
-
-static void __exit hpt366_ide_exit(void)
-{
-       pci_unregister_driver(&hpt366_pci_driver);
-}
-
-module_init(hpt366_ide_init);
-module_exit(hpt366_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
deleted file mode 100644 (file)
index 7c2feeb..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * ITE 8213 IDE driver
- *
- * Copyright (C) 2006 Jack Lee
- * Copyright (C) 2006 Alan Cox
- * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "it8213"
-
-/**
- *     it8213_set_pio_mode     -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Set the interface PIO mode.
- */
-
-static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       int is_slave            = drive->dn & 1;
-       int master_port         = 0x40;
-       int slave_port          = 0x44;
-       unsigned long flags;
-       u16 master_data;
-       u8 slave_data;
-       static DEFINE_SPINLOCK(tune_lock);
-       int control = 0;
-
-       static const u8 timings[][2] = {
-                                       { 0, 0 },
-                                       { 0, 0 },
-                                       { 1, 0 },
-                                       { 2, 1 },
-                                       { 2, 3 }, };
-
-       spin_lock_irqsave(&tune_lock, flags);
-       pci_read_config_word(dev, master_port, &master_data);
-
-       if (pio > 1)
-               control |= 1;   /* Programmable timing on */
-       if (drive->media != ide_disk)
-               control |= 4;   /* ATAPI */
-       if (pio > 2)
-               control |= 2;   /* IORDY */
-       if (is_slave) {
-               master_data |=  0x4000;
-               master_data &= ~0x0070;
-               if (pio > 1)
-                       master_data = master_data | (control << 4);
-               pci_read_config_byte(dev, slave_port, &slave_data);
-               slave_data = slave_data & 0xf0;
-               slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1];
-       } else {
-               master_data &= ~0x3307;
-               if (pio > 1)
-                       master_data = master_data | control;
-               master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
-       }
-       pci_write_config_word(dev, master_port, master_data);
-       if (is_slave)
-               pci_write_config_byte(dev, slave_port, slave_data);
-       spin_unlock_irqrestore(&tune_lock, flags);
-}
-
-/**
- *     it8213_set_dma_mode     -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Tune the ITE chipset for the DMA mode.
- */
-
-static void it8213_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 maslave              = 0x40;
-       int a_speed             = 3 << (drive->dn * 4);
-       int u_flag              = 1 << drive->dn;
-       int v_flag              = 0x01 << drive->dn;
-       int w_flag              = 0x10 << drive->dn;
-       int u_speed             = 0;
-       u16                     reg4042, reg4a;
-       u8                      reg48, reg54, reg55;
-
-       pci_read_config_word(dev, maslave, &reg4042);
-       pci_read_config_byte(dev, 0x48, &reg48);
-       pci_read_config_word(dev, 0x4a, &reg4a);
-       pci_read_config_byte(dev, 0x54, &reg54);
-       pci_read_config_byte(dev, 0x55, &reg55);
-
-       if (speed >= XFER_UDMA_0) {
-               u8 udma = speed - XFER_UDMA_0;
-
-               u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
-
-               if (!(reg48 & u_flag))
-                       pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-               if (speed >= XFER_UDMA_5)
-                       pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
-               else
-                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-
-               if ((reg4a & a_speed) != u_speed)
-                       pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
-               if (speed > XFER_UDMA_2) {
-                       if (!(reg54 & v_flag))
-                               pci_write_config_byte(dev, 0x54, reg54 | v_flag);
-               } else
-                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
-       } else {
-               const u8 mwdma_to_pio[] = { 0, 3, 4 };
-               u8 pio;
-
-               if (reg48 & u_flag)
-                       pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
-               if (reg4a & a_speed)
-                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
-               if (reg54 & v_flag)
-                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
-               if (reg55 & w_flag)
-                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-
-               if (speed >= XFER_MW_DMA_0)
-                       pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
-               else
-                       pio = 2; /* only SWDMA2 is allowed */
-
-               it8213_set_pio_mode(drive, pio);
-       }
-}
-
-static u8 it8213_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 reg42h = 0;
-
-       pci_read_config_byte(dev, 0x42, &reg42h);
-
-       return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-}
-
-static const struct ide_port_ops it8213_port_ops = {
-       .set_pio_mode           = it8213_set_pio_mode,
-       .set_dma_mode           = it8213_set_dma_mode,
-       .cable_detect           = it8213_cable_detect,
-};
-
-static const struct ide_port_info it8213_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .enablebits     = { {0x41, 0x80, 0x80} },
-       .port_ops       = &it8213_port_ops,
-       .host_flags     = IDE_HFLAG_SINGLE,
-       .pio_mask       = ATA_PIO4,
-       .swdma_mask     = ATA_SWDMA2_ONLY,
-       .mwdma_mask     = ATA_MWDMA12_ONLY,
-       .udma_mask      = ATA_UDMA6,
-};
-
-/**
- *     it8213_init_one -       pci layer discovery entry
- *     @dev: PCI device
- *     @id: ident table entry
- *
- *     Called by the PCI code when it finds an ITE8213 controller. As
- *     this device follows the standard interfaces we can use the
- *     standard helper functions to do almost all the work for us.
- */
-
-static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &it8213_chipset, NULL);
-}
-
-static const struct pci_device_id it8213_pci_tbl[] = {
-       { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
-
-static struct pci_driver it8213_pci_driver = {
-       .name           = "ITE8213_IDE",
-       .id_table       = it8213_pci_tbl,
-       .probe          = it8213_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init it8213_ide_init(void)
-{
-       return ide_pci_register_driver(&it8213_pci_driver);
-}
-
-static void __exit it8213_ide_exit(void)
-{
-       pci_unregister_driver(&it8213_pci_driver);
-}
-
-module_init(it8213_ide_init);
-module_exit(it8213_ide_exit);
-
-MODULE_AUTHOR("Jack Lee, Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
deleted file mode 100644 (file)
index 995e18b..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * Copyright (C) 2004          Red Hat <alan@redhat.com>
- * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
- *
- *  May be copied or modified under the terms of the GNU General Public License
- *  Based in part on the ITE vendor provided SCSI driver.
- *
- *  Documentation available from
- *     http://www.ite.com.tw/pc/IT8212F_V04.pdf
- *  Some other documents are NDA.
- *
- *  The ITE8212 isn't exactly a standard IDE controller. It has two
- *  modes. In pass through mode then it is an IDE controller. In its smart
- *  mode its actually quite a capable hardware raid controller disguised
- *  as an IDE controller. Smart mode only understands DMA read/write and
- *  identify, none of the fancier commands apply. The IT8211 is identical
- *  in other respects but lacks the raid mode.
- *
- *  Errata:
- *  o  Rev 0x10 also requires master/slave hold the same DMA timings and
- *     cannot do ATAPI MWDMA.
- *  o  The identify data for raid volumes lacks CHS info (technically ok)
- *     but also fails to set the LBA28 and other bits. We fix these in
- *     the IDE probe quirk code.
- *  o  If you write LBA48 sized I/O's (ie > 256 sector) in smart mode
- *     raid then the controller firmware dies
- *  o  Smart mode without RAID doesn't clear all the necessary identify
- *     bits to reduce the command set to the one used
- *
- *  This has a few impacts on the driver
- *  - In pass through mode we do all the work you would expect
- *  - In smart mode the clocking set up is done by the controller generally
- *    but we must watch the other limits and filter.
- *  - There are a few extra vendor commands that actually talk to the
- *    controller but only work PIO with no IRQ.
- *
- *  Vendor areas of the identify block in smart mode are used for the
- *  timing and policy set up. Each HDD in raid mode also has a serial
- *  block on the disk. The hardware extra commands are get/set chip status,
- *  rebuild, get rebuild status.
- *
- *  In Linux the driver supports pass through mode as if the device was
- *  just another IDE controller. If the smart mode is running then
- *  volumes are managed by the controller firmware and each IDE "disk"
- *  is a raid volume. Even more cute - the controller can do automated
- *  hotplug and rebuild.
- *
- *  The pass through controller itself is a little demented. It has a
- *  flaw that it has a single set of PIO/MWDMA timings per channel so
- *  non UDMA devices restrict each others performance. It also has a
- *  single clock source per channel so mixed UDMA100/133 performance
- *  isn't perfect and we have to pick a clock. Thankfully none of this
- *  matters in smart mode. ATAPI DMA is not currently supported.
- *
- *  It seems the smart mode is a win for RAID1/RAID10 but otherwise not.
- *
- *  TODO
- *     -       ATAPI UDMA is ok but not MWDMA it seems
- *     -       RAID configuration ioctls
- *     -       Move to libata once it grows up
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "it821x"
-
-struct it821x_dev
-{
-       unsigned int smart:1,           /* Are we in smart raid mode */
-               timing10:1;             /* Rev 0x10 */
-       u8      clock_mode;             /* 0, ATA_50 or ATA_66 */
-       u8      want[2][2];             /* Mode/Pri log for master slave */
-       /* We need these for switching the clock when DMA goes on/off
-          The high byte is the 66Mhz timing */
-       u16     pio[2];                 /* Cached PIO values */
-       u16     mwdma[2];               /* Cached MWDMA values */
-       u16     udma[2];                /* Cached UDMA values (per drive) */
-};
-
-#define ATA_66         0
-#define ATA_50         1
-#define ATA_ANY                2
-
-#define UDMA_OFF       0
-#define MWDMA_OFF      0
-
-/*
- *     We allow users to force the card into non raid mode without
- *     flashing the alternative BIOS. This is also necessary right now
- *     for embedded platforms that cannot run a PC BIOS but are using this
- *     device.
- */
-
-static int it8212_noraid;
-
-/**
- *     it821x_program  -       program the PIO/MWDMA registers
- *     @drive: drive to tune
- *     @timing: timing info
- *
- *     Program the PIO/MWDMA timing for this channel according to the
- *     current clock.
- */
-
-static void it821x_program(ide_drive_t *drive, u16 timing)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int channel = hwif->channel;
-       u8 conf;
-
-       /* Program PIO/MWDMA timing bits */
-       if(itdev->clock_mode == ATA_66)
-               conf = timing >> 8;
-       else
-               conf = timing & 0xFF;
-
-       pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
-}
-
-/**
- *     it821x_program_udma     -       program the UDMA registers
- *     @drive: drive to tune
- *     @timing: timing info
- *
- *     Program the UDMA timing for this drive according to the
- *     current clock.
- */
-
-static void it821x_program_udma(ide_drive_t *drive, u16 timing)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int channel = hwif->channel;
-       u8 unit = drive->dn & 1, conf;
-
-       /* Program UDMA timing bits */
-       if(itdev->clock_mode == ATA_66)
-               conf = timing >> 8;
-       else
-               conf = timing & 0xFF;
-
-       if (itdev->timing10 == 0)
-               pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
-       else {
-               pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
-               pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
-       }
-}
-
-/**
- *     it821x_clock_strategy
- *     @drive: drive to set up
- *
- *     Select between the 50 and 66Mhz base clocks to get the best
- *     results for this interface.
- */
-
-static void it821x_clock_strategy(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       ide_drive_t *pair;
-       int clock, altclock, sel = 0;
-       u8 unit = drive->dn & 1, v;
-
-       pair = &hwif->drives[1 - unit];
-
-       if(itdev->want[0][0] > itdev->want[1][0]) {
-               clock = itdev->want[0][1];
-               altclock = itdev->want[1][1];
-       } else {
-               clock = itdev->want[1][1];
-               altclock = itdev->want[0][1];
-       }
-
-       /*
-        * if both clocks can be used for the mode with the higher priority
-        * use the clock needed by the mode with the lower priority
-        */
-       if (clock == ATA_ANY)
-               clock = altclock;
-
-       /* Nobody cares - keep the same clock */
-       if(clock == ATA_ANY)
-               return;
-       /* No change */
-       if(clock == itdev->clock_mode)
-               return;
-
-       /* Load this into the controller ? */
-       if(clock == ATA_66)
-               itdev->clock_mode = ATA_66;
-       else {
-               itdev->clock_mode = ATA_50;
-               sel = 1;
-       }
-
-       pci_read_config_byte(dev, 0x50, &v);
-       v &= ~(1 << (1 + hwif->channel));
-       v |= sel << (1 + hwif->channel);
-       pci_write_config_byte(dev, 0x50, v);
-
-       /*
-        *      Reprogram the UDMA/PIO of the pair drive for the switch
-        *      MWDMA will be dealt with by the dma switcher
-        */
-       if(pair && itdev->udma[1-unit] != UDMA_OFF) {
-               it821x_program_udma(pair, itdev->udma[1-unit]);
-               it821x_program(pair, itdev->pio[1-unit]);
-       }
-       /*
-        *      Reprogram the UDMA/PIO of our drive for the switch.
-        *      MWDMA will be dealt with by the dma switcher
-        */
-       if(itdev->udma[unit] != UDMA_OFF) {
-               it821x_program_udma(drive, itdev->udma[unit]);
-               it821x_program(drive, itdev->pio[unit]);
-       }
-}
-
-/**
- *     it821x_set_pio_mode     -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Tune the host to the desired PIO mode taking into the consideration
- *     the maximum PIO mode supported by the other device on the cable.
- */
-
-static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       ide_drive_t *pair;
-       u8 unit = drive->dn & 1, set_pio = pio;
-
-       /* Spec says 89 ref driver uses 88 */
-       static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
-       static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
-
-       pair = &hwif->drives[1 - unit];
-
-       /*
-        * Compute the best PIO mode we can for a given device. We must
-        * pick a speed that does not cause problems with the other device
-        * on the cable.
-        */
-       if (pair) {
-               u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
-               /* trim PIO to the slowest of the master/slave */
-               if (pair_pio < set_pio)
-                       set_pio = pair_pio;
-       }
-
-       /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
-       itdev->want[unit][1] = pio_want[set_pio];
-       itdev->want[unit][0] = 1;       /* PIO is lowest priority */
-       itdev->pio[unit] = pio_timings[set_pio];
-       it821x_clock_strategy(drive);
-       it821x_program(drive, itdev->pio[unit]);
-}
-
-/**
- *     it821x_tune_mwdma       -       tune a channel for MWDMA
- *     @drive: drive to set up
- *     @mode_wanted: the target operating mode
- *
- *     Load the timing settings for this device mode into the
- *     controller when doing MWDMA in pass through mode. The caller
- *     must manage the whole lack of per device MWDMA/PIO timings and
- *     the shared MWDMA/PIO timing register.
- */
-
-static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
-       u8 unit = drive->dn & 1, channel = hwif->channel, conf;
-
-       static u16 dma[]        = { 0x8866, 0x3222, 0x3121 };
-       static u8 mwdma_want[]  = { ATA_ANY, ATA_66, ATA_ANY };
-
-       itdev->want[unit][1] = mwdma_want[mode_wanted];
-       itdev->want[unit][0] = 2;       /* MWDMA is low priority */
-       itdev->mwdma[unit] = dma[mode_wanted];
-       itdev->udma[unit] = UDMA_OFF;
-
-       /* UDMA bits off - Revision 0x10 do them in pairs */
-       pci_read_config_byte(dev, 0x50, &conf);
-       if (itdev->timing10)
-               conf |= channel ? 0x60: 0x18;
-       else
-               conf |= 1 << (3 + 2 * channel + unit);
-       pci_write_config_byte(dev, 0x50, conf);
-
-       it821x_clock_strategy(drive);
-       /* FIXME: do we need to program this ? */
-       /* it821x_program(drive, itdev->mwdma[unit]); */
-}
-
-/**
- *     it821x_tune_udma        -       tune a channel for UDMA
- *     @drive: drive to set up
- *     @mode_wanted: the target operating mode
- *
- *     Load the timing settings for this device mode into the
- *     controller when doing UDMA modes in pass through.
- */
-
-static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       u8 unit = drive->dn & 1, channel = hwif->channel, conf;
-
-       static u16 udma[]       = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
-       static u8 udma_want[]   = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
-
-       itdev->want[unit][1] = udma_want[mode_wanted];
-       itdev->want[unit][0] = 3;       /* UDMA is high priority */
-       itdev->mwdma[unit] = MWDMA_OFF;
-       itdev->udma[unit] = udma[mode_wanted];
-       if(mode_wanted >= 5)
-               itdev->udma[unit] |= 0x8080;    /* UDMA 5/6 select on */
-
-       /* UDMA on. Again revision 0x10 must do the pair */
-       pci_read_config_byte(dev, 0x50, &conf);
-       if (itdev->timing10)
-               conf &= channel ? 0x9F: 0xE7;
-       else
-               conf &= ~ (1 << (3 + 2 * channel + unit));
-       pci_write_config_byte(dev, 0x50, conf);
-
-       it821x_clock_strategy(drive);
-       it821x_program_udma(drive, itdev->udma[unit]);
-
-}
-
-/**
- *     it821x_dma_read -       DMA hook
- *     @drive: drive for DMA
- *
- *     The IT821x has a single timing register for MWDMA and for PIO
- *     operations. As we flip back and forth we have to reload the
- *     clock. In addition the rev 0x10 device only works if the same
- *     timing value is loaded into the master and slave UDMA clock
- *     so we must also reload that.
- *
- *     FIXME: we could figure out in advance if we need to do reloads
- */
-
-static void it821x_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       u8 unit = drive->dn & 1;
-
-       if(itdev->mwdma[unit] != MWDMA_OFF)
-               it821x_program(drive, itdev->mwdma[unit]);
-       else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
-               it821x_program_udma(drive, itdev->udma[unit]);
-       ide_dma_start(drive);
-}
-
-/**
- *     it821x_dma_write        -       DMA hook
- *     @drive: drive for DMA stop
- *
- *     The IT821x has a single timing register for MWDMA and for PIO
- *     operations. As we flip back and forth we have to reload the
- *     clock.
- */
-
-static int it821x_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int ret = ide_dma_end(drive);
-       u8 unit = drive->dn & 1;
-
-       if(itdev->mwdma[unit] != MWDMA_OFF)
-               it821x_program(drive, itdev->pio[unit]);
-       return ret;
-}
-
-/**
- *     it821x_set_dma_mode     -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Tune the ITE chipset for the desired DMA mode.
- */
-
-static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       /*
-        * MWDMA tuning is really hard because our MWDMA and PIO
-        * timings are kept in the same place.  We can switch in the
-        * host dma on/off callbacks.
-        */
-       if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6)
-               it821x_tune_udma(drive, speed - XFER_UDMA_0);
-       else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
-               it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0);
-}
-
-/**
- *     it821x_cable_detect     -       cable detection
- *     @hwif: interface to check
- *
- *     Check for the presence of an ATA66 capable cable on the
- *     interface. Problematic as it seems some cards don't have
- *     the needed logic onboard.
- */
-
-static u8 it821x_cable_detect(ide_hwif_t *hwif)
-{
-       /* The reference driver also only does disk side */
-       return ATA_CBL_PATA80;
-}
-
-/**
- *     it821x_quirkproc        -       post init callback
- *     @drive: drive
- *
- *     This callback is run after the drive has been probed but
- *     before anything gets attached. It allows drivers to do any
- *     final tuning that is needed, or fixups to work around bugs.
- */
-
-static void it821x_quirkproc(ide_drive_t *drive)
-{
-       struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
-       u16 *id = drive->id;
-
-       if (!itdev->smart) {
-               /*
-                *      If we are in pass through mode then not much
-                *      needs to be done, but we do bother to clear the
-                *      IRQ mask as we may well be in PIO (eg rev 0x10)
-                *      for now and we know unmasking is safe on this chipset.
-                */
-               drive->dev_flags |= IDE_DFLAG_UNMASK;
-       } else {
-       /*
-        *      Perform fixups on smart mode. We need to "lose" some
-        *      capabilities the firmware lacks but does not filter, and
-        *      also patch up some capability bits that it forgets to set
-        *      in RAID mode.
-        */
-
-               /* Check for RAID v native */
-               if (strstr((char *)&id[ATA_ID_PROD],
-                          "Integrated Technology Express")) {
-                       /* In raid mode the ident block is slightly buggy
-                          We need to set the bits so that the IDE layer knows
-                          LBA28. LBA48 and DMA ar valid */
-                       id[ATA_ID_CAPABILITY]    |= (3 << 8); /* LBA28, DMA */
-                       id[ATA_ID_COMMAND_SET_2] |= 0x0400;   /* LBA48 valid */
-                       id[ATA_ID_CFS_ENABLE_2]  |= 0x0400;   /* LBA48 on */
-                       /* Reporting logic */
-                       printk(KERN_INFO "%s: IT8212 %sRAID %d volume",
-                               drive->name, id[147] ? "Bootable " : "",
-                               id[ATA_ID_CSFO]);
-                       if (id[ATA_ID_CSFO] != 1)
-                               printk(KERN_CONT "(%dK stripe)", id[146]);
-                       printk(KERN_CONT ".\n");
-               } else {
-                       /* Non RAID volume. Fixups to stop the core code
-                          doing unsupported things */
-                       id[ATA_ID_FIELD_VALID]   &= 3;
-                       id[ATA_ID_QUEUE_DEPTH]    = 0;
-                       id[ATA_ID_COMMAND_SET_1]  = 0;
-                       id[ATA_ID_COMMAND_SET_2] &= 0xC400;
-                       id[ATA_ID_CFSSE]         &= 0xC000;
-                       id[ATA_ID_CFS_ENABLE_1]   = 0;
-                       id[ATA_ID_CFS_ENABLE_2]  &= 0xC400;
-                       id[ATA_ID_CSF_DEFAULT]   &= 0xC000;
-                       id[127]                   = 0;
-                       id[ATA_ID_DLF]            = 0;
-                       id[ATA_ID_CSFO]           = 0;
-                       id[ATA_ID_CFA_POWER]      = 0;
-                       printk(KERN_INFO "%s: Performing identify fixups.\n",
-                               drive->name);
-               }
-
-               /*
-                * Set MWDMA0 mode as enabled/support - just to tell
-                * IDE core that DMA is supported (it821x hardware
-                * takes care of DMA mode programming).
-                */
-               if (ata_id_has_dma(id)) {
-                       id[ATA_ID_MWDMA_MODES] |= 0x0101;
-                       drive->current_speed = XFER_MW_DMA_0;
-               }
-       }
-
-}
-
-static struct ide_dma_ops it821x_pass_through_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = it821x_dma_start,
-       .dma_end                = it821x_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_timeout            = ide_dma_timeout,
-       .dma_lost_irq           = ide_dma_lost_irq,
-};
-
-/**
- *     init_hwif_it821x        -       set up hwif structs
- *     @hwif: interface to set up
- *
- *     We do the basic set up of the interface structure. The IT8212
- *     requires several custom handlers so we override the default
- *     ide DMA handlers appropriately
- */
-
-static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct it821x_dev *itdevs = host->host_priv;
-       struct it821x_dev *idev = itdevs + hwif->channel;
-       u8 conf;
-
-       ide_set_hwifdata(hwif, idev);
-
-       pci_read_config_byte(dev, 0x50, &conf);
-       if (conf & 1) {
-               idev->smart = 1;
-               hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
-               /* Long I/O's although allowed in LBA48 space cause the
-                  onboard firmware to enter the twighlight zone */
-               hwif->rqsize = 256;
-       }
-
-       /* Pull the current clocks from 0x50 also */
-       if (conf & (1 << (1 + hwif->channel)))
-               idev->clock_mode = ATA_50;
-       else
-               idev->clock_mode = ATA_66;
-
-       idev->want[0][1] = ATA_ANY;
-       idev->want[1][1] = ATA_ANY;
-
-       /*
-        *      Not in the docs but according to the reference driver
-        *      this is necessary.
-        */
-
-       pci_read_config_byte(dev, 0x08, &conf);
-       if (conf == 0x10) {
-               idev->timing10 = 1;
-               hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
-               if (idev->smart == 0)
-                       printk(KERN_WARNING DRV_NAME " %s: revision 0x10, "
-                               "workarounds activated\n", pci_name(dev));
-       }
-
-       if (idev->smart == 0) {
-               /* MWDMA/PIO clock switching for pass through mode */
-               hwif->dma_ops = &it821x_pass_through_dma_ops;
-       } else
-               hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
-
-       if (hwif->dma_base == 0)
-               return;
-
-       hwif->ultra_mask = ATA_UDMA6;
-       hwif->mwdma_mask = ATA_MWDMA2;
-}
-
-static void it8212_disable_raid(struct pci_dev *dev)
-{
-       /* Reset local CPU, and set BIOS not ready */
-       pci_write_config_byte(dev, 0x5E, 0x01);
-
-       /* Set to bypass mode, and reset PCI bus */
-       pci_write_config_byte(dev, 0x50, 0x00);
-       pci_write_config_word(dev, PCI_COMMAND,
-                             PCI_COMMAND_PARITY | PCI_COMMAND_IO |
-                             PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-       pci_write_config_word(dev, 0x40, 0xA0F3);
-
-       pci_write_config_dword(dev,0x4C, 0x02040204);
-       pci_write_config_byte(dev, 0x42, 0x36);
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
-}
-
-static unsigned int init_chipset_it821x(struct pci_dev *dev)
-{
-       u8 conf;
-       static char *mode[2] = { "pass through", "smart" };
-
-       /* Force the card into bypass mode if so requested */
-       if (it8212_noraid) {
-               printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n",
-                       pci_name(dev));
-               it8212_disable_raid(dev);
-       }
-       pci_read_config_byte(dev, 0x50, &conf);
-       printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n",
-               pci_name(dev), mode[conf & 1]);
-       return 0;
-}
-
-static const struct ide_port_ops it821x_port_ops = {
-       /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */
-       .set_pio_mode           = it821x_set_pio_mode,
-       .set_dma_mode           = it821x_set_dma_mode,
-       .quirkproc              = it821x_quirkproc,
-       .cable_detect           = it821x_cable_detect,
-};
-
-static const struct ide_port_info it821x_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_chipset   = init_chipset_it821x,
-       .init_hwif      = init_hwif_it821x,
-       .port_ops       = &it821x_port_ops,
-       .pio_mask       = ATA_PIO4,
-};
-
-/**
- *     it821x_init_one -       pci layer discovery entry
- *     @dev: PCI device
- *     @id: ident table entry
- *
- *     Called by the PCI code when it finds an ITE821x controller.
- *     We then use the IDE PCI generic helper to do most of the work.
- */
-
-static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct it821x_dev *itdevs;
-       int rc;
-
-       itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL);
-       if (itdevs == NULL) {
-               printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev));
-               return -ENOMEM;
-       }
-
-       rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
-       if (rc)
-               kfree(itdevs);
-
-       return rc;
-}
-
-static void __devexit it821x_remove(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct it821x_dev *itdevs = host->host_priv;
-
-       ide_pci_remove(dev);
-       kfree(itdevs);
-}
-
-static const struct pci_device_id it821x_pci_tbl[] = {
-       { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },
-       { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
-
-static struct pci_driver it821x_pci_driver = {
-       .name           = "ITE821x IDE",
-       .id_table       = it821x_pci_tbl,
-       .probe          = it821x_init_one,
-       .remove         = __devexit_p(it821x_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init it821x_ide_init(void)
-{
-       return ide_pci_register_driver(&it821x_pci_driver);
-}
-
-static void __exit it821x_ide_exit(void)
-{
-       pci_unregister_driver(&it821x_pci_driver);
-}
-
-module_init(it821x_ide_init);
-module_exit(it821x_ide_exit);
-
-module_param_named(noraid, it8212_noraid, int, S_IRUGO);
-MODULE_PARM_DESC(noraid, "Force card into bypass mode");
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for the ITE 821x");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
deleted file mode 100644 (file)
index 9a68433..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-
-/*
- * Copyright (C) 2006          Red Hat <alan@redhat.com>
- *
- *  May be copied or modified under the terms of the GNU General Public License
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "jmicron"
-
-typedef enum {
-       PORT_PATA0 = 0,
-       PORT_PATA1 = 1,
-       PORT_SATA = 2,
-} port_type;
-
-/**
- *     jmicron_cable_detect    -       cable detection
- *     @hwif: IDE port
- *
- *     Returns the cable type.
- */
-
-static u8 jmicron_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-
-       u32 control;
-       u32 control5;
-
-       int port = hwif->channel;
-       port_type port_map[2];
-
-       pci_read_config_dword(pdev, 0x40, &control);
-
-       /* There are two basic mappings. One has the two SATA ports merged
-          as master/slave and the secondary as PATA, the other has only the
-          SATA port mapped */
-       if (control & (1 << 23)) {
-               port_map[0] = PORT_SATA;
-               port_map[1] = PORT_PATA0;
-       } else {
-               port_map[0] = PORT_SATA;
-               port_map[1] = PORT_SATA;
-       }
-
-       /* The 365/366 may have this bit set to map the second PATA port
-          as the internal primary channel */
-       pci_read_config_dword(pdev, 0x80, &control5);
-       if (control5 & (1<<24))
-               port_map[0] = PORT_PATA1;
-
-       /* The two ports may then be logically swapped by the firmware */
-       if (control & (1 << 22))
-               port = port ^ 1;
-
-       /*
-        *      Now we know which physical port we are talking about we can
-        *      actually do our cable checking etc. Thankfully we don't need
-        *      to do the plumbing for other cases.
-        */
-       switch (port_map[port]) {
-       case PORT_PATA0:
-               if (control & (1 << 3)) /* 40/80 pin primary */
-                       return ATA_CBL_PATA40;
-               return ATA_CBL_PATA80;
-       case PORT_PATA1:
-               if (control5 & (1 << 19))       /* 40/80 pin secondary */
-                       return ATA_CBL_PATA40;
-               return ATA_CBL_PATA80;
-       case PORT_SATA:
-               break;
-       }
-       /* Avoid bogus "control reaches end of non-void function" */
-       return ATA_CBL_PATA80;
-}
-
-static void jmicron_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-}
-
-/**
- *     jmicron_set_dma_mode    -       set host controller for DMA mode
- *     @drive: drive
- *     @mode: DMA mode
- *
- *     As the JMicron snoops for timings we don't need to do anything here.
- */
-
-static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
-{
-}
-
-static const struct ide_port_ops jmicron_port_ops = {
-       .set_pio_mode           = jmicron_set_pio_mode,
-       .set_dma_mode           = jmicron_set_dma_mode,
-       .cable_detect           = jmicron_cable_detect,
-};
-
-static const struct ide_port_info jmicron_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
-       .port_ops       = &jmicron_port_ops,
-       .pio_mask       = ATA_PIO5,
-       .mwdma_mask     = ATA_MWDMA2,
-       .udma_mask      = ATA_UDMA6,
-};
-
-/**
- *     jmicron_init_one        -       pci layer discovery entry
- *     @dev: PCI device
- *     @id: ident table entry
- *
- *     Called by the PCI code when it finds a Jmicron controller.
- *     We then use the IDE PCI generic helper to do most of the work.
- */
-
-static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &jmicron_chipset, NULL);
-}
-
-/* All JMB PATA controllers have and will continue to have the same
- * interface.  Matching vendor and device class is enough for all
- * current and future controllers if the controller is programmed
- * properly.
- *
- * If libata is configured, jmicron PCI quirk programs the controller
- * into the correct mode.  If libata isn't configured, match known
- * device IDs too to maintain backward compatibility.
- */
-static struct pci_device_id jmicron_pci_tbl[] = {
-#if !defined(CONFIG_ATA) && !defined(CONFIG_ATA_MODULE)
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361) },
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363) },
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365) },
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366) },
-       { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368) },
-#endif
-       { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-         PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
-
-static struct pci_driver jmicron_pci_driver = {
-       .name           = "JMicron IDE",
-       .id_table       = jmicron_pci_tbl,
-       .probe          = jmicron_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init jmicron_ide_init(void)
-{
-       return ide_pci_register_driver(&jmicron_pci_driver);
-}
-
-static void __exit jmicron_ide_exit(void)
-{
-       pci_unregister_driver(&jmicron_pci_driver);
-}
-
-module_init(jmicron_ide_init);
-module_exit(jmicron_ide_exit);
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
deleted file mode 100644 (file)
index 1378906..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (C) 1997-1998     Mark Lord <mlord@pobox.com>
- * Copyright (C) 1998          Eddie C. Dost <ecd@skynet.be>
- * Copyright (C) 1999-2000     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2004          Grant Grundler <grundler at parisc-linux.org>
- *
- * Inspired by an earlier effort from David S. Miller <davem@redhat.com>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "ns87415"
-
-#ifdef CONFIG_SUPERIO
-/* SUPERIO 87560 is a PoS chip that NatSem denies exists.
- * Unfortunately, it's built-in on all Astro-based PA-RISC workstations
- * which use the integrated NS87514 cell for CD-ROM support.
- * i.e we have to support for CD-ROM installs.
- * See drivers/parisc/superio.c for more gory details.
- */
-#include <asm/superio.h>
-
-#define SUPERIO_IDE_MAX_RETRIES 25
-
-/* Because of a defect in Super I/O, all reads of the PCI DMA status 
- * registers, IDE status register and the IDE select register need to be 
- * retried
- */
-static u8 superio_ide_inb (unsigned long port)
-{
-       u8 tmp;
-       int retries = SUPERIO_IDE_MAX_RETRIES;
-
-       /* printk(" [ reading port 0x%x with retry ] ", port); */
-
-       do {
-               tmp = inb(port);
-               if (tmp == 0)
-                       udelay(50);
-       } while (tmp == 0 && retries-- > 0);
-
-       return tmp;
-}
-
-static u8 superio_read_status(ide_hwif_t *hwif)
-{
-       return superio_ide_inb(hwif->io_ports.status_addr);
-}
-
-static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
-{
-       return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
-}
-
-static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
-{
-       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-       struct ide_taskfile *tf = &task->tf;
-
-       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-               u16 data = inw(io_ports->data_addr);
-
-               tf->data = data & 0xff;
-               tf->hob_data = (data >> 8) & 0xff;
-       }
-
-       /* be sure we're looking at the low order bits */
-       outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
-
-       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
-               tf->feature = inb(io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-               tf->nsect  = inb(io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-               tf->lbal   = inb(io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-               tf->lbam   = inb(io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-               tf->lbah   = inb(io_ports->lbah_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-               tf->device = superio_ide_inb(io_ports->device_addr);
-
-       if (task->tf_flags & IDE_TFLAG_LBA48) {
-               outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
-
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-                       tf->hob_feature = inb(io_ports->feature_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-                       tf->hob_nsect   = inb(io_ports->nsect_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-                       tf->hob_lbal    = inb(io_ports->lbal_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-                       tf->hob_lbam    = inb(io_ports->lbam_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-                       tf->hob_lbah    = inb(io_ports->lbah_addr);
-       }
-}
-
-static const struct ide_tp_ops superio_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = superio_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = superio_read_sff_dma_status,
-
-       .set_irq                = ide_set_irq,
-
-       .tf_load                = ide_tf_load,
-       .tf_read                = superio_tf_read,
-
-       .input_data             = ide_input_data,
-       .output_data            = ide_output_data,
-};
-
-static void __devinit superio_init_iops(struct hwif_s *hwif)
-{
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       u32 dma_stat;
-       u8 port = hwif->channel, tmp;
-
-       dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
-
-       /* Clear error/interrupt, enable dma */
-       tmp = superio_ide_inb(dma_stat);
-       outb(tmp | 0x66, dma_stat);
-}
-#endif
-
-static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
-
-/*
- * This routine either enables/disables (according to IDE_DFLAG_PRESENT)
- * the IRQ associated with the port (HWIF(drive)),
- * and selects either PIO or DMA handshaking for the next I/O operation.
- */
-static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       new = *old;
-
-       /* Adjust IRQ enable bit */
-       bit = 1 << (8 + hwif->channel);
-
-       if (drive->dev_flags & IDE_DFLAG_PRESENT)
-               new &= ~bit;
-       else
-               new |= bit;
-
-       /* Select PIO or DMA, DMA may only be selected for one drive/channel. */
-       bit   = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1));
-       other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1));
-       new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
-
-       if (new != *old) {
-               unsigned char stat;
-
-               /*
-                * Don't change DMA engine settings while Write Buffers
-                * are busy.
-                */
-               (void) pci_read_config_byte(dev, 0x43, &stat);
-               while (stat & 0x03) {
-                       udelay(1);
-                       (void) pci_read_config_byte(dev, 0x43, &stat);
-               }
-
-               *old = new;
-               (void) pci_write_config_dword(dev, 0x40, new);
-
-               /*
-                * And let things settle...
-                */
-               udelay(10);
-       }
-
-       local_irq_restore(flags);
-}
-
-static void ns87415_selectproc (ide_drive_t *drive)
-{
-       ns87415_prepare_drive(drive,
-                             !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
-}
-
-static int ns87415_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t      *hwif = HWIF(drive);
-       u8 dma_stat = 0, dma_cmd = 0;
-
-       drive->waiting_for_dma = 0;
-       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-       /* get DMA command mode */
-       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-       /* stop DMA */
-       outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
-       /* from ERRATA: clear the INTR & ERROR bits */
-       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-       outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
-       /* and free any DMA resources */
-       ide_destroy_dmatable(drive);
-       /* verify good DMA status */
-       return (dma_stat & 7) != 4;
-}
-
-static int ns87415_dma_setup(ide_drive_t *drive)
-{
-       /* select DMA xfer */
-       ns87415_prepare_drive(drive, 1);
-       if (!ide_dma_setup(drive))
-               return 0;
-       /* DMA failed: select PIO xfer */
-       ns87415_prepare_drive(drive, 0);
-       return 1;
-}
-
-static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned int ctrl, using_inta;
-       u8 progif;
-#ifdef __sparc_v9__
-       int timeout;
-       u8 stat;
-#endif
-
-       /*
-        * We cannot probe for IRQ: both ports share common IRQ on INTA.
-        * Also, leave IRQ masked during drive probing, to prevent infinite
-        * interrupts from a potentially floating INTA..
-        *
-        * IRQs get unmasked in selectproc when drive is first used.
-        */
-       (void) pci_read_config_dword(dev, 0x40, &ctrl);
-       (void) pci_read_config_byte(dev, 0x09, &progif);
-       /* is irq in "native" mode? */
-       using_inta = progif & (1 << (hwif->channel << 1));
-       if (!using_inta)
-               using_inta = ctrl & (1 << (4 + hwif->channel));
-       if (hwif->mate) {
-               hwif->select_data = hwif->mate->select_data;
-       } else {
-               hwif->select_data = (unsigned long)
-                                       &ns87415_control[ns87415_count++];
-               ctrl |= (1 << 8) | (1 << 9);    /* mask both IRQs */
-               if (using_inta)
-                       ctrl &= ~(1 << 6);      /* unmask INTA */
-               *((unsigned int *)hwif->select_data) = ctrl;
-               (void) pci_write_config_dword(dev, 0x40, ctrl);
-
-               /*
-                * Set prefetch size to 512 bytes for both ports,
-                * but don't turn on/off prefetching here.
-                */
-               pci_write_config_byte(dev, 0x55, 0xee);
-
-#ifdef __sparc_v9__
-               /*
-                * XXX: Reset the device, if we don't it will not respond to
-                *      SELECT_DRIVE() properly during first ide_probe_port().
-                */
-               timeout = 10000;
-               outb(12, hwif->io_ports.ctl_addr);
-               udelay(10);
-               outb(8, hwif->io_ports.ctl_addr);
-               do {
-                       udelay(50);
-                       stat = hwif->tp_ops->read_status(hwif);
-                       if (stat == 0xff)
-                               break;
-               } while ((stat & ATA_BUSY) && --timeout);
-#endif
-       }
-
-       if (!using_inta)
-               hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
-       else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-               hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
-
-       if (!hwif->dma_base)
-               return;
-
-       outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
-}
-
-static const struct ide_port_ops ns87415_port_ops = {
-       .selectproc             = ns87415_selectproc,
-};
-
-static const struct ide_dma_ops ns87415_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ns87415_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = ide_dma_start,
-       .dma_end                = ns87415_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info ns87415_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_hwif      = init_hwif_ns87415,
-       .port_ops       = &ns87415_port_ops,
-       .dma_ops        = &ns87415_dma_ops,
-       .host_flags     = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-                         IDE_HFLAG_NO_ATAPI_DMA,
-};
-
-static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d = ns87415_chipset;
-
-#ifdef CONFIG_SUPERIO
-       if (PCI_SLOT(dev->devfn) == 0xE) {
-               /* Built-in - assume it's under superio. */
-               d.init_iops = superio_init_iops;
-               d.tp_ops = &superio_tp_ops;
-       }
-#endif
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-static const struct pci_device_id ns87415_pci_tbl[] = {
-       { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
-
-static struct pci_driver ns87415_pci_driver = {
-       .name           = "NS87415_IDE",
-       .id_table       = ns87415_pci_tbl,
-       .probe          = ns87415_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init ns87415_ide_init(void)
-{
-       return ide_pci_register_driver(&ns87415_pci_driver);
-}
-
-static void __exit ns87415_ide_exit(void)
-{
-       pci_unregister_driver(&ns87415_pci_driver);
-}
-
-module_init(ns87415_ide_init);
-module_exit(ns87415_ide_exit);
-
-MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for NS87415 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
deleted file mode 100644 (file)
index 6048eda..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- *  Copyright (C) 1996-1998  Linus Torvalds & authors (see below)
- */
-
-/*
- * Authors:
- * Jaromir Koutek <miri@punknet.cz>,
- * Jan Harkes <jaharkes@cwi.nl>,
- * Mark Lord <mlord@pobox.com>
- * Some parts of code are from ali14xx.c and from rz1000.c.
- *
- * OPTi is trademark of OPTi, Octek is trademark of Octek.
- *
- * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps
- * and disassembled/traced setupvic.exe (DOS program).
- * It increases kernel code about 2 kB.
- * I don't have this card no more, but I hope I can get some in case
- * of needed development.
- * My card is Octek PIDE 1.01 (on card) or OPTiViC (program).
- * It has a place for a secondary connector in circuit, but nothing
- * is there. Also BIOS says no address for
- * secondary controller (see bellow in ide_init_opti621).
- * I've only tested this on my system, which only has one disk.
- * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus
- * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random
- * lockups). I tried the OCTEK double speed CD-ROM and
- * it does not work! But I can't boot DOS also, so it's probably
- * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no
- * problems) and Seagate 1GB (as slave, WD as master). My experiences
- * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes
- * it slows to about 100kB/s! I don't know why and I have
- * not this drive now, so I can't try it again.
- * I write this driver because I lost the paper ("manual") with
- * settings of jumpers on the card and I have to boot Linux with
- * Loadlin except LILO, cause I have to run the setupvic.exe program
- * already or I get disk errors (my test: rpm -Vf
- * /usr/X11R6/bin/XF86_SVGA - or any big file).
- * Some numbers from hdparm -t /dev/hda:
- * Timing buffer-cache reads:   32 MB in  3.02 seconds =10.60 MB/sec
- * Timing buffered disk reads:  16 MB in  5.52 seconds = 2.90 MB/sec
- * I have 4 Megs/s before, but I don't know why (maybe changes
- * in hdparm test).
- * After release of 0.1, I got some successful reports, so it might work.
- *
- * The main problem with OPTi is that some timings for master
- * and slave must be the same. For example, if you have master
- * PIO 3 and slave PIO 0, driver have to set some timings of
- * master for PIO 0. Second problem is that opti621_set_pio_mode
- * got only one drive to set, but have to set both drives.
- * This is solved in compute_pios. If you don't set
- * the second drive, compute_pios use ide_get_best_pio_mode
- * for autoselect mode (you can change it to PIO 0, if you want).
- * If you then set the second drive to another PIO, the old value
- * (automatically selected) will be overrided by yours.
- * There is a 25/33MHz switch in configuration
- * register, but driver is written for use at any frequency.
- *
- * Version 0.1, Nov 8, 1996
- * by Jaromir Koutek, for 2.1.8.
- * Initial version of driver.
- *
- * Version 0.2
- * Number 0.2 skipped.
- *
- * Version 0.3, Nov 29, 1997
- * by Mark Lord (probably), for 2.1.68
- * Updates for use with new IDE block driver.
- *
- * Version 0.4, Dec 14, 1997
- * by Jan Harkes
- * Fixed some errors and cleaned the code.
- *
- * Version 0.5, Jan 2, 1998
- * by Jaromir Koutek
- * Updates for use with (again) new IDE block driver.
- * Update of documentation.
- *
- * Version 0.6, Jan 2, 1999
- * by Jaromir Koutek
- * Reversed to version 0.3 of the driver, because
- * 0.5 doesn't work.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "opti621"
-
-#define READ_REG 0     /* index of Read cycle timing register */
-#define WRITE_REG 1    /* index of Write cycle timing register */
-#define CNTRL_REG 3    /* index of Control register */
-#define STRAP_REG 5    /* index of Strap register */
-#define MISC_REG 6     /* index of Miscellaneous register */
-
-static int reg_base;
-
-static DEFINE_SPINLOCK(opti621_lock);
-
-/* Write value to register reg, base of register
- * is at reg_base (0x1f0 primary, 0x170 secondary,
- * if not changed by PCI configuration).
- * This is from setupvic.exe program.
- */
-static void write_reg(u8 value, int reg)
-{
-       inw(reg_base + 1);
-       inw(reg_base + 1);
-       outb(3, reg_base + 2);
-       outb(value, reg_base + reg);
-       outb(0x83, reg_base + 2);
-}
-
-/* Read value from register reg, base of register
- * is at reg_base (0x1f0 primary, 0x170 secondary,
- * if not changed by PCI configuration).
- * This is from setupvic.exe program.
- */
-static u8 read_reg(int reg)
-{
-       u8 ret = 0;
-
-       inw(reg_base + 1);
-       inw(reg_base + 1);
-       outb(3, reg_base + 2);
-       ret = inb(reg_base + reg);
-       outb(0x83, reg_base + 2);
-
-       return ret;
-}
-
-static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       ide_drive_t *pair = ide_get_pair_dev(drive);
-       unsigned long flags;
-       u8 tim, misc, addr_pio = pio, clk;
-
-       /* DRDY is default 2 (by OPTi Databook) */
-       static const u8 addr_timings[2][5] = {
-               { 0x20, 0x10, 0x00, 0x00, 0x00 },       /* 33 MHz */
-               { 0x10, 0x10, 0x00, 0x00, 0x00 },       /* 25 MHz */
-       };
-       static const u8 data_rec_timings[2][5] = {
-               { 0x5b, 0x45, 0x32, 0x21, 0x20 },       /* 33 MHz */
-               { 0x48, 0x34, 0x21, 0x10, 0x10 }        /* 25 MHz */
-       };
-
-       drive->drive_data = XFER_PIO_0 + pio;
-
-       if (pair) {
-               if (pair->drive_data && pair->drive_data < drive->drive_data)
-                       addr_pio = pair->drive_data - XFER_PIO_0;
-       }
-
-       spin_lock_irqsave(&opti621_lock, flags);
-
-       reg_base = hwif->io_ports.data_addr;
-
-       /* allow Register-B */
-       outb(0xc0, reg_base + CNTRL_REG);
-       /* hmm, setupvic.exe does this ;-) */
-       outb(0xff, reg_base + 5);
-       /* if reads 0xff, adapter not exist? */
-       (void)inb(reg_base + CNTRL_REG);
-       /* if reads 0xc0, no interface exist? */
-       read_reg(CNTRL_REG);
-
-       /* check CLK speed */
-       clk = read_reg(STRAP_REG) & 1;
-
-       printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);
-
-       tim  = data_rec_timings[clk][pio];
-       misc = addr_timings[clk][addr_pio];
-
-       /* select Index-0/1 for Register-A/B */
-       write_reg(drive->dn & 1, MISC_REG);
-       /* set read cycle timings */
-       write_reg(tim, READ_REG);
-       /* set write cycle timings */
-       write_reg(tim, WRITE_REG);
-
-       /* use Register-A for drive 0 */
-       /* use Register-B for drive 1 */
-       write_reg(0x85, CNTRL_REG);
-
-       /* set address setup, DRDY timings,   */
-       /*  and read prefetch for both drives */
-       write_reg(misc, MISC_REG);
-
-       spin_unlock_irqrestore(&opti621_lock, flags);
-}
-
-static const struct ide_port_ops opti621_port_ops = {
-       .set_pio_mode           = opti621_set_pio_mode,
-};
-
-static const struct ide_port_info opti621_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
-       .port_ops       = &opti621_port_ops,
-       .host_flags     = IDE_HFLAG_NO_DMA,
-       .pio_mask       = ATA_PIO4,
-};
-
-static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &opti621_chipset, NULL);
-}
-
-static const struct pci_device_id opti621_pci_tbl[] = {
-       { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 },
-       { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
-
-static struct pci_driver opti621_pci_driver = {
-       .name           = "Opti621_IDE",
-       .id_table       = opti621_pci_tbl,
-       .probe          = opti621_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init opti621_ide_init(void)
-{
-       return ide_pci_register_driver(&opti621_pci_driver);
-}
-
-static void __exit opti621_ide_exit(void)
-{
-       pci_unregister_driver(&opti621_pci_driver);
-}
-
-module_init(opti621_ide_init);
-module_exit(opti621_ide_exit);
-
-MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
-MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
deleted file mode 100644 (file)
index 211ae46..0000000
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- *  Promise TX2/TX4/TX2000/133 IDE driver
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- *  Split from:
- *  linux/drivers/ide/pdc202xx.c       Version 0.35    Mar. 30, 2002
- *  Copyright (C) 1998-2002            Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2005-2007            MontaVista Software, Inc.
- *  Portions Copyright (C) 1999 Promise Technology, Inc.
- *  Author: Frank Tiernan (frankt@promise.com)
- *  Released under terms of General Public License
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif
-
-#define DRV_NAME "pdc202xx_new"
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args)
-#else
-#define DBG(fmt, args...)
-#endif
-
-static const char *pdc_quirk_drives[] = {
-       "QUANTUM FIREBALLlct08 08",
-       "QUANTUM FIREBALLP KA6.4",
-       "QUANTUM FIREBALLP KA9.1",
-       "QUANTUM FIREBALLP LM20.4",
-       "QUANTUM FIREBALLP KX13.6",
-       "QUANTUM FIREBALLP KX20.5",
-       "QUANTUM FIREBALLP KX27.3",
-       "QUANTUM FIREBALLP LM20.5",
-       NULL
-};
-
-static u8 max_dma_rate(struct pci_dev *pdev)
-{
-       u8 mode;
-
-       switch(pdev->device) {
-               case PCI_DEVICE_ID_PROMISE_20277:
-               case PCI_DEVICE_ID_PROMISE_20276:
-               case PCI_DEVICE_ID_PROMISE_20275:
-               case PCI_DEVICE_ID_PROMISE_20271:
-               case PCI_DEVICE_ID_PROMISE_20269:
-                       mode = 4;
-                       break;
-               case PCI_DEVICE_ID_PROMISE_20270:
-               case PCI_DEVICE_ID_PROMISE_20268:
-                       mode = 3;
-                       break;
-               default:
-                       return 0;
-       }
-
-       return mode;
-}
-
-/**
- * get_indexed_reg - Get indexed register
- * @hwif: for the port address
- * @index: index of the indexed register
- */
-static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
-{
-       u8 value;
-
-       outb(index, hwif->dma_base + 1);
-       value = inb(hwif->dma_base + 3);
-
-       DBG("index[%02X] value[%02X]\n", index, value);
-       return value;
-}
-
-/**
- * set_indexed_reg - Set indexed register
- * @hwif: for the port address
- * @index: index of the indexed register
- */
-static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
-{
-       outb(index, hwif->dma_base + 1);
-       outb(value, hwif->dma_base + 3);
-       DBG("index[%02X] value[%02X]\n", index, value);
-}
-
-/*
- * ATA Timing Tables based on 133 MHz PLL output clock.
- *
- * If the PLL outputs 100 MHz clock, the ASIC hardware will set
- * the timing registers automatically when "set features" command is
- * issued to the device. However, if the PLL output clock is 133 MHz,
- * the following tables must be used.
- */
-static struct pio_timing {
-       u8 reg0c, reg0d, reg13;
-} pio_timings [] = {
-       { 0xfb, 0x2b, 0xac },   /* PIO mode 0, IORDY off, Prefetch off */
-       { 0x46, 0x29, 0xa4 },   /* PIO mode 1, IORDY off, Prefetch off */
-       { 0x23, 0x26, 0x64 },   /* PIO mode 2, IORDY off, Prefetch off */
-       { 0x27, 0x0d, 0x35 },   /* PIO mode 3, IORDY on,  Prefetch off */
-       { 0x23, 0x09, 0x25 },   /* PIO mode 4, IORDY on,  Prefetch off */
-};
-
-static struct mwdma_timing {
-       u8 reg0e, reg0f;
-} mwdma_timings [] = {
-       { 0xdf, 0x5f },         /* MWDMA mode 0 */
-       { 0x6b, 0x27 },         /* MWDMA mode 1 */
-       { 0x69, 0x25 },         /* MWDMA mode 2 */
-};
-
-static struct udma_timing {
-       u8 reg10, reg11, reg12;
-} udma_timings [] = {
-       { 0x4a, 0x0f, 0xd5 },   /* UDMA mode 0 */
-       { 0x3a, 0x0a, 0xd0 },   /* UDMA mode 1 */
-       { 0x2a, 0x07, 0xcd },   /* UDMA mode 2 */
-       { 0x1a, 0x05, 0xcd },   /* UDMA mode 3 */
-       { 0x1a, 0x03, 0xcd },   /* UDMA mode 4 */
-       { 0x1a, 0x02, 0xcb },   /* UDMA mode 5 */
-       { 0x1a, 0x01, 0xcb },   /* UDMA mode 6 */
-};
-
-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;
-
-       /*
-        * 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.
-        *
-        * 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(dev) == 4) {
-               u8 mode = speed & 0x07;
-
-               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 */
-               u8 tmp = get_indexed_reg(hwif, 0x10 + adj);
-
-               set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
-       }
-}
-
-static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 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)
-{
-       if (get_indexed_reg(hwif, 0x0b) & 0x04)
-               return ATA_CBL_PATA40;
-       else
-               return ATA_CBL_PATA80;
-}
-
-static void pdcnew_quirkproc(ide_drive_t *drive)
-{
-       const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
-
-       for (list = pdc_quirk_drives; *list != NULL; list++)
-               if (strstr(m, *list) != NULL) {
-                       drive->quirk_list = 2;
-                       return;
-               }
-
-       drive->quirk_list = 0;
-}
-
-static void pdcnew_reset(ide_drive_t *drive)
-{
-       /*
-        * Deleted this because it is redundant from the caller.
-        */
-       printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",
-               HWIF(drive)->channel ? "Secondary" : "Primary");
-}
-
-/**
- * read_counter - Read the byte count registers
- * @dma_base: for the port address
- */
-static long read_counter(u32 dma_base)
-{
-       u32  pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
-       u8   cnt0, cnt1, cnt2, cnt3;
-       long count = 0, last;
-       int  retry = 3;
-
-       do {
-               last = count;
-
-               /* Read the current count */
-               outb(0x20, pri_dma_base + 0x01);
-               cnt0 = inb(pri_dma_base + 0x03);
-               outb(0x21, pri_dma_base + 0x01);
-               cnt1 = inb(pri_dma_base + 0x03);
-               outb(0x20, sec_dma_base + 0x01);
-               cnt2 = inb(sec_dma_base + 0x03);
-               outb(0x21, sec_dma_base + 0x01);
-               cnt3 = inb(sec_dma_base + 0x03);
-
-               count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0;
-
-               /*
-                * The 30-bit decrementing counter is read in 4 pieces.
-                * Incorrect value may be read when the most significant bytes
-                * are changing...
-                */
-       } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count));
-
-       DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n",
-                 cnt0, cnt1, cnt2, cnt3);
-
-       return count;
-}
-
-/**
- * detect_pll_input_clock - Detect the PLL input clock in Hz.
- * @dma_base: for the port address
- * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
- */
-static long detect_pll_input_clock(unsigned long dma_base)
-{
-       struct timeval start_time, end_time;
-       long start_count, end_count;
-       long pll_input, usec_elapsed;
-       u8 scr1;
-
-       start_count = read_counter(dma_base);
-       do_gettimeofday(&start_time);
-
-       /* Start the test mode */
-       outb(0x01, dma_base + 0x01);
-       scr1 = inb(dma_base + 0x03);
-       DBG("scr1[%02X]\n", scr1);
-       outb(scr1 | 0x40, dma_base + 0x03);
-
-       /* Let the counter run for 10 ms. */
-       mdelay(10);
-
-       end_count = read_counter(dma_base);
-       do_gettimeofday(&end_time);
-
-       /* Stop the test mode */
-       outb(0x01, dma_base + 0x01);
-       scr1 = inb(dma_base + 0x03);
-       DBG("scr1[%02X]\n", scr1);
-       outb(scr1 & ~0x40, dma_base + 0x03);
-
-       /*
-        * Calculate the input clock in Hz
-        * (the clock counter is 30 bit wide and counts down)
-        */
-       usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
-               (end_time.tv_usec - start_time.tv_usec);
-       pll_input = ((start_count - end_count) & 0x3fffffff) / 10 *
-               (10000000 / usec_elapsed);
-
-       DBG("start[%ld] end[%ld]\n", start_count, end_count);
-
-       return pll_input;
-}
-
-#ifdef CONFIG_PPC_PMAC
-static void apple_kiwi_init(struct pci_dev *pdev)
-{
-       struct device_node *np = pci_device_to_OF_node(pdev);
-       u8 conf;
-
-       if (np == NULL || !of_device_is_compatible(np, "kiwi-root"))
-               return;
-
-       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));
-       }
-}
-#endif /* CONFIG_PPC_PMAC */
-
-static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
-{
-       const char *name = DRV_NAME;
-       unsigned long dma_base = pci_resource_start(dev, 4);
-       unsigned long sec_dma_base = dma_base + 0x08;
-       long pll_input, pll_output, ratio;
-       int f, r;
-       u8 pll_ctl0, pll_ctl1;
-
-       if (dma_base == 0)
-               return -EFAULT;
-
-#ifdef CONFIG_PPC_PMAC
-       apple_kiwi_init(dev);
-#endif
-
-       /* Calculate the required PLL output frequency */
-       switch(max_dma_rate(dev)) {
-               case 4: /* it's 133 MHz for Ultra133 chips */
-                       pll_output = 133333333;
-                       break;
-               case 3: /* and  100 MHz for Ultra100 chips */
-               default:
-                       pll_output = 100000000;
-                       break;
-       }
-
-       /*
-        * Detect PLL input clock.
-        * On some systems, where PCI bus is running at non-standard clock rate
-        * (e.g. 25 or 40 MHz), we have to adjust the cycle time.
-        * PDC20268 and newer chips employ PLL circuit to help correct timing
-        * registers setting.
-        */
-       pll_input = detect_pll_input_clock(dma_base);
-       printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n",
-               name, pci_name(dev), pll_input / 1000);
-
-       /* Sanity check */
-       if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
-               printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!"
-                       "\n", name, pci_name(dev), pll_input);
-               goto out;
-       }
-
-#ifdef DEBUG
-       DBG("pll_output is %ld Hz\n", pll_output);
-
-       /* Show the current clock value of PLL control register
-        * (maybe already configured by the BIOS)
-        */
-       outb(0x02, sec_dma_base + 0x01);
-       pll_ctl0 = inb(sec_dma_base + 0x03);
-       outb(0x03, sec_dma_base + 0x01);
-       pll_ctl1 = inb(sec_dma_base + 0x03);
-
-       DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
-#endif
-
-       /*
-        * Calculate the ratio of F, R and NO
-        * POUT = (F + 2) / (( R + 2) * NO)
-        */
-       ratio = pll_output / (pll_input / 1000);
-       if (ratio < 8600L) { /* 8.6x */
-               /* Using NO = 0x01, R = 0x0d */
-               r = 0x0d;
-       } else if (ratio < 12900L) { /* 12.9x */
-               /* Using NO = 0x01, R = 0x08 */
-               r = 0x08;
-       } else if (ratio < 16100L) { /* 16.1x */
-               /* Using NO = 0x01, R = 0x06 */
-               r = 0x06;
-       } else if (ratio < 64000L) { /* 64x */
-               r = 0x00;
-       } else {
-               /* Invalid ratio */
-               printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n",
-                       name, pci_name(dev), ratio);
-               goto out;
-       }
-
-       f = (ratio * (r + 2)) / 1000 - 2;
-
-       DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio);
-
-       if (unlikely(f < 0 || f > 127)) {
-               /* Invalid F */
-               printk(KERN_ERR "%s %s: F[%d] invalid!\n",
-                       name, pci_name(dev), f);
-               goto out;
-       }
-
-       pll_ctl0 = (u8) f;
-       pll_ctl1 = (u8) r;
-
-       DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
-
-       outb(0x02,     sec_dma_base + 0x01);
-       outb(pll_ctl0, sec_dma_base + 0x03);
-       outb(0x03,     sec_dma_base + 0x01);
-       outb(pll_ctl1, sec_dma_base + 0x03);
-
-       /* Wait the PLL circuit to be stable */
-       mdelay(30);
-
-#ifdef DEBUG
-       /*
-        *  Show the current clock value of PLL control register
-        */
-       outb(0x02, sec_dma_base + 0x01);
-       pll_ctl0 = inb(sec_dma_base + 0x03);
-       outb(0x03, sec_dma_base + 0x01);
-       pll_ctl1 = inb(sec_dma_base + 0x03);
-
-       DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
-#endif
-
- out:
-       return dev->irq;
-}
-
-static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
-{
-       struct pci_dev *dev2;
-
-       dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1,
-                                               PCI_FUNC(dev->devfn)));
-
-       if (dev2 &&
-           dev2->vendor == dev->vendor &&
-           dev2->device == dev->device) {
-
-               if (dev2->irq != dev->irq) {
-                       dev2->irq = dev->irq;
-                       printk(KERN_INFO DRV_NAME " %s: PCI config space "
-                               "interrupt fixed\n", pci_name(dev));
-               }
-
-               return dev2;
-       }
-
-       return NULL;
-}
-
-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,
-};
-
-#define DECLARE_PDCNEW_DEV(udma) \
-       { \
-               .name           = DRV_NAME, \
-               .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, \
-       }
-
-static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
-       /* 0: PDC202{68,70} */          DECLARE_PDCNEW_DEV(ATA_UDMA5),
-       /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
-};
-
-/**
- *     pdc202new_init_one      -       called when a pdc202xx is found
- *     @dev: the pdc202new device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
-       struct pci_dev *bridge = dev->bus->self;
-
-       if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && 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_pci_init_two(dev, dev2, d, NULL);
-                       if (ret < 0)
-                               pci_dev_put(dev2);
-                       return ret;
-               }
-       }
-
-       if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge &&
-           bridge->vendor == PCI_VENDOR_ID_INTEL &&
-           (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
-            bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
-               printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller,"
-                       " skipping\n", pci_name(dev));
-               return -ENODEV;
-       }
-
-       return ide_pci_init_one(dev, d, NULL);
-}
-
-static void __devexit pdc202new_remove(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
-
-       ide_pci_remove(dev);
-       pci_dev_put(dev2);
-}
-
-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), 0 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
-
-static struct pci_driver pdc202new_pci_driver = {
-       .name           = "Promise_IDE",
-       .id_table       = pdc202new_pci_tbl,
-       .probe          = pdc202new_init_one,
-       .remove         = __devexit_p(pdc202new_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init pdc202new_ide_init(void)
-{
-       return ide_pci_register_driver(&pdc202new_pci_driver);
-}
-
-static void __exit pdc202new_ide_exit(void)
-{
-       pci_unregister_driver(&pdc202new_pci_driver);
-}
-
-module_init(pdc202new_ide_init);
-module_exit(pdc202new_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
-MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
deleted file mode 100644 (file)
index 799557c..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- *  Copyright (C) 1998-2002            Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2006-2007            MontaVista Software, Inc.
- *  Copyright (C) 2007                 Bartlomiej Zolnierkiewicz
- *
- *  Portions Copyright (C) 1999 Promise Technology, Inc.
- *  Author: Frank Tiernan (frankt@promise.com)
- *  Released under terms of General Public License
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/blkdev.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "pdc202xx_old"
-
-#define PDC202XX_DEBUG_DRIVE_INFO      0
-
-static const char *pdc_quirk_drives[] = {
-       "QUANTUM FIREBALLlct08 08",
-       "QUANTUM FIREBALLP KA6.4",
-       "QUANTUM FIREBALLP KA9.1",
-       "QUANTUM FIREBALLP LM20.4",
-       "QUANTUM FIREBALLP KX13.6",
-       "QUANTUM FIREBALLP KX20.5",
-       "QUANTUM FIREBALLP KX27.3",
-       "QUANTUM FIREBALLP LM20.5",
-       NULL
-};
-
-static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
-
-static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 drive_pci            = 0x60 + (drive->dn << 2);
-
-       u8                      AP = 0, BP = 0, CP = 0;
-       u8                      TA = 0, TB = 0, TC = 0;
-
-#if PDC202XX_DEBUG_DRIVE_INFO
-       u32                     drive_conf = 0;
-       pci_read_config_dword(dev, drive_pci, &drive_conf);
-#endif
-
-       /*
-        * TODO: do this once per channel
-        */
-       if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
-               pdc_old_disable_66MHz_clock(hwif);
-
-       pci_read_config_byte(dev, drive_pci,     &AP);
-       pci_read_config_byte(dev, drive_pci + 1, &BP);
-       pci_read_config_byte(dev, drive_pci + 2, &CP);
-
-       switch(speed) {
-               case XFER_UDMA_5:
-               case XFER_UDMA_4:       TB = 0x20; TC = 0x01; break;
-               case XFER_UDMA_2:       TB = 0x20; TC = 0x01; break;
-               case XFER_UDMA_3:
-               case XFER_UDMA_1:       TB = 0x40; TC = 0x02; break;
-               case XFER_UDMA_0:
-               case XFER_MW_DMA_2:     TB = 0x60; TC = 0x03; break;
-               case XFER_MW_DMA_1:     TB = 0x60; TC = 0x04; break;
-               case XFER_MW_DMA_0:     TB = 0xE0; TC = 0x0F; break;
-               case XFER_PIO_4:        TA = 0x01; TB = 0x04; break;
-               case XFER_PIO_3:        TA = 0x02; TB = 0x06; break;
-               case XFER_PIO_2:        TA = 0x03; TB = 0x08; break;
-               case XFER_PIO_1:        TA = 0x05; TB = 0x0C; break;
-               case XFER_PIO_0:
-               default:                TA = 0x09; TB = 0x13; break;
-       }
-
-       if (speed < XFER_SW_DMA_0) {
-               /*
-                * preserve SYNC_INT / ERDDY_EN bits while clearing
-                * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
-                */
-               AP &= ~0x3f;
-               if (ata_id_iordy_disable(drive->id))
-                       AP |= 0x20;     /* set IORDY_EN bit */
-               if (drive->media == ide_disk)
-                       AP |= 0x10;     /* set Prefetch_EN bit */
-               /* clear PB[4:0] bits of register B */
-               BP &= ~0x1f;
-               pci_write_config_byte(dev, drive_pci,     AP | TA);
-               pci_write_config_byte(dev, drive_pci + 1, BP | TB);
-       } else {
-               /* clear MB[2:0] bits of register B */
-               BP &= ~0xe0;
-               /* clear MC[3:0] bits of register C */
-               CP &= ~0x0f;
-               pci_write_config_byte(dev, drive_pci + 1, BP | TB);
-               pci_write_config_byte(dev, drive_pci + 2, CP | TC);
-       }
-
-#if PDC202XX_DEBUG_DRIVE_INFO
-       printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
-               drive->name, ide_xfer_verbose(speed),
-               drive->dn, drive_conf);
-       pci_read_config_dword(dev, drive_pci, &drive_conf);
-       printk("0x%08x\n", drive_conf);
-#endif
-}
-
-static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
-}
-
-static u8 pdc2026x_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
-
-       pci_read_config_word(dev, 0x50, &CIS);
-
-       return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-}
-
-/*
- * Set the control register to use the 66MHz system
- * clock for UDMA 3/4/5 mode operation when necessary.
- *
- * FIXME: this register is shared by both channels, some locking is needed
- *
- * It may also be possible to leave the 66MHz clock on
- * and readjust the timing parameters.
- */
-static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
-{
-       unsigned long clock_reg = hwif->extra_base + 0x01;
-       u8 clock = inb(clock_reg);
-
-       outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
-}
-
-static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
-{
-       unsigned long clock_reg = hwif->extra_base + 0x01;
-       u8 clock = inb(clock_reg);
-
-       outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
-}
-
-static void pdc202xx_quirkproc(ide_drive_t *drive)
-{
-       const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
-
-       for (list = pdc_quirk_drives; *list != NULL; list++)
-               if (strstr(m, *list) != NULL) {
-                       drive->quirk_list = 2;
-                       return;
-               }
-
-       drive->quirk_list = 0;
-}
-
-static void pdc202xx_dma_start(ide_drive_t *drive)
-{
-       if (drive->current_speed > XFER_UDMA_2)
-               pdc_old_enable_66MHz_clock(drive->hwif);
-       if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
-               struct request *rq      = HWGROUP(drive)->rq;
-               ide_hwif_t *hwif        = HWIF(drive);
-               unsigned long high_16   = hwif->extra_base - 16;
-               unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
-               u32 word_count  = 0;
-               u8 clock = inb(high_16 + 0x11);
-
-               outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
-               word_count = (rq->nr_sectors << 8);
-               word_count = (rq_data_dir(rq) == READ) ?
-                                       word_count | 0x05000000 :
-                                       word_count | 0x06000000;
-               outl(word_count, atapi_reg);
-       }
-       ide_dma_start(drive);
-}
-
-static int pdc202xx_dma_end(ide_drive_t *drive)
-{
-       if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
-               ide_hwif_t *hwif        = HWIF(drive);
-               unsigned long high_16   = hwif->extra_base - 16;
-               unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
-               u8 clock                = 0;
-
-               outl(0, atapi_reg); /* zero out extra */
-               clock = inb(high_16 + 0x11);
-               outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
-       }
-       if (drive->current_speed > XFER_UDMA_2)
-               pdc_old_disable_66MHz_clock(drive->hwif);
-       return ide_dma_end(drive);
-}
-
-static int pdc202xx_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long high_16   = hwif->extra_base - 16;
-       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
-       u8 sc1d                 = inb(high_16 + 0x001d);
-
-       if (hwif->channel) {
-               /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
-               if ((sc1d & 0x50) == 0x50)
-                       goto somebody_else;
-               else if ((sc1d & 0x40) == 0x40)
-                       return (dma_stat & 4) == 4;
-       } else {
-               /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */
-               if ((sc1d & 0x05) == 0x05)
-                       goto somebody_else;
-               else if ((sc1d & 0x04) == 0x04)
-                       return (dma_stat & 4) == 4;
-       }
-somebody_else:
-       return (dma_stat & 4) == 4;     /* return 1 if INTR asserted */
-}
-
-static void pdc202xx_reset_host (ide_hwif_t *hwif)
-{
-       unsigned long high_16   = hwif->extra_base - 16;
-       u8 udma_speed_flag      = inb(high_16 | 0x001f);
-
-       outb(udma_speed_flag | 0x10, high_16 | 0x001f);
-       mdelay(100);
-       outb(udma_speed_flag & ~0x10, high_16 | 0x001f);
-       mdelay(2000);   /* 2 seconds ?! */
-
-       printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
-               hwif->channel ? "Secondary" : "Primary");
-}
-
-static void pdc202xx_reset (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       ide_hwif_t *mate        = hwif->mate;
-
-       pdc202xx_reset_host(hwif);
-       pdc202xx_reset_host(mate);
-
-       ide_set_max_pio(drive);
-}
-
-static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
-{
-       pdc202xx_reset(drive);
-       ide_dma_lost_irq(drive);
-}
-
-static void pdc202xx_dma_timeout(ide_drive_t *drive)
-{
-       pdc202xx_reset(drive);
-       ide_dma_timeout(drive);
-}
-
-static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
-{
-       unsigned long dmabase = pci_resource_start(dev, 4);
-       u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
-
-       if (dmabase == 0)
-               goto out;
-
-       udma_speed_flag = inb(dmabase | 0x1f);
-       primary_mode    = inb(dmabase | 0x1a);
-       secondary_mode  = inb(dmabase | 0x1b);
-       printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
-               "Primary %s Mode " \
-               "Secondary %s Mode.\n", pci_name(dev),
-               (udma_speed_flag & 1) ? "EN" : "DIS",
-               (primary_mode & 1) ? "MASTER" : "PCI",
-               (secondary_mode & 1) ? "MASTER" : "PCI" );
-
-       if (!(udma_speed_flag & 1)) {
-               printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
-                       pci_name(dev), udma_speed_flag,
-                       (udma_speed_flag|1));
-               outb(udma_speed_flag | 1, dmabase | 0x1f);
-               printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
-       }
-out:
-       return dev->irq;
-}
-
-static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
-                                          const char *name)
-{
-       if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
-               u8 irq = 0, irq2 = 0;
-               pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-               /* 0xbc */
-               pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);
-               if (irq != irq2) {
-                       pci_write_config_byte(dev,
-                               (PCI_INTERRUPT_LINE)|0x80, irq);     /* 0xbc */
-                       printk(KERN_INFO "%s %s: PCI config space interrupt "
-                               "mirror fixed\n", name, pci_name(dev));
-               }
-       }
-}
-
-#define IDE_HFLAGS_PDC202XX \
-       (IDE_HFLAG_ERROR_STOPS_FIFO | \
-        IDE_HFLAG_OFF_BOARD)
-
-static const struct ide_port_ops pdc20246_port_ops = {
-       .set_pio_mode           = pdc202xx_set_pio_mode,
-       .set_dma_mode           = pdc202xx_set_mode,
-       .quirkproc              = pdc202xx_quirkproc,
-};
-
-static const struct ide_port_ops pdc2026x_port_ops = {
-       .set_pio_mode           = pdc202xx_set_pio_mode,
-       .set_dma_mode           = pdc202xx_set_mode,
-       .quirkproc              = pdc202xx_quirkproc,
-       .resetproc              = pdc202xx_reset,
-       .cable_detect           = pdc2026x_cable_detect,
-};
-
-static const struct ide_dma_ops pdc20246_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           = pdc202xx_dma_test_irq,
-       .dma_lost_irq           = pdc202xx_dma_lost_irq,
-       .dma_timeout            = pdc202xx_dma_timeout,
-};
-
-static const struct ide_dma_ops pdc2026x_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = pdc202xx_dma_start,
-       .dma_end                = pdc202xx_dma_end,
-       .dma_test_irq           = pdc202xx_dma_test_irq,
-       .dma_lost_irq           = pdc202xx_dma_lost_irq,
-       .dma_timeout            = pdc202xx_dma_timeout,
-};
-
-#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
-       { \
-               .name           = DRV_NAME, \
-               .init_chipset   = init_chipset_pdc202xx, \
-               .port_ops       = &pdc2026x_port_ops, \
-               .dma_ops        = &pdc2026x_dma_ops, \
-               .host_flags     = IDE_HFLAGS_PDC202XX | extra_flags, \
-               .pio_mask       = ATA_PIO4, \
-               .mwdma_mask     = ATA_MWDMA2, \
-               .udma_mask      = udma, \
-       }
-
-static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
-       {       /* 0: PDC20246 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_pdc202xx,
-               .port_ops       = &pdc20246_port_ops,
-               .dma_ops        = &pdc20246_dma_ops,
-               .host_flags     = IDE_HFLAGS_PDC202XX,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA2,
-       },
-
-       /* 1: PDC2026{2,3} */
-       DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
-       /* 2: PDC2026{5,7} */
-       DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
-};
-
-/**
- *     pdc202xx_init_one       -       called when a PDC202xx is found
- *     @dev: the pdc202xx device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       const struct ide_port_info *d;
-       u8 idx = id->driver_data;
-
-       d = &pdc202xx_chipsets[idx];
-
-       if (idx < 2)
-               pdc202ata4_fixup_irq(dev, d->name);
-
-       if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) {
-               struct pci_dev *bridge = dev->bus->self;
-
-               if (bridge &&
-                   bridge->vendor == PCI_VENDOR_ID_INTEL &&
-                   (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
-                    bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
-                       printk(KERN_INFO DRV_NAME " %s: skipping Promise "
-                               "PDC20265 attached to I2O RAID controller\n",
-                               pci_name(dev));
-                       return -ENODEV;
-               }
-       }
-
-       return ide_pci_init_one(dev, d, NULL);
-}
-
-static const struct pci_device_id pdc202xx_pci_tbl[] = {
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 },
-       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
-
-static struct pci_driver pdc202xx_pci_driver = {
-       .name           = "Promise_Old_IDE",
-       .id_table       = pdc202xx_pci_tbl,
-       .probe          = pdc202xx_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init pdc202xx_ide_init(void)
-{
-       return ide_pci_register_driver(&pdc202xx_pci_driver);
-}
-
-static void __exit pdc202xx_ide_exit(void)
-{
-       pci_unregister_driver(&pdc202xx_pci_driver);
-}
-
-module_init(pdc202xx_ide_init);
-module_exit(pdc202xx_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
-MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
deleted file mode 100644 (file)
index d63f9fd..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
- *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
- *
- *  May be copied or modified under the terms of the GNU General Public License
- *
- * Documentation:
- *
- *     Publically available from Intel web site. Errata documentation
- * is also publically available. As an aide to anyone hacking on this
- * driver the list of errata that are relevant is below.going back to
- * PIIX4. Older device documentation is now a bit tricky to find.
- *
- * Errata of note:
- *
- * Unfixable
- *     PIIX4    errata #9      - Only on ultra obscure hw
- *     ICH3     errata #13     - Not observed to affect real hw
- *                               by Intel
- *
- * Things we must deal with
- *     PIIX4   errata #10      - BM IDE hang with non UDMA
- *                               (must stop/start dma to recover)
- *     440MX   errata #15      - As PIIX4 errata #10
- *     PIIX4   errata #15      - Must not read control registers
- *                               during a PIO transfer
- *     440MX   errata #13      - As PIIX4 errata #15
- *     ICH2    errata #21      - DMA mode 0 doesn't work right
- *     ICH0/1  errata #55      - As ICH2 errata #21
- *     ICH2    spec c #9       - Extra operations needed to handle
- *                               drive hotswap [NOT YET SUPPORTED]
- *     ICH2    spec c #20      - IDE PRD must not cross a 64K boundary
- *                               and must be dword aligned
- *     ICH2    spec c #24      - UDMA mode 4,5 t85/86 should be 6ns not 3.3
- *
- * Should have been BIOS fixed:
- *     450NX:  errata #19      - DMA hangs on old 450NX
- *     450NX:  errata #20      - DMA hangs on old 450NX
- *     450NX:  errata #25      - Corruption with DMA on old 450NX
- *     ICH3    errata #15      - IDE deadlock under high load
- *                               (BIOS must set dev 31 fn 0 bit 23)
- *     ICH3    errata #18      - Don't use native mode
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "piix"
-
-static int no_piix_dma;
-
-/**
- *     piix_set_pio_mode       -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Set the interface PIO mode based upon the settings done by AMI BIOS.
- */
-
-static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       int is_slave            = drive->dn & 1;
-       int master_port         = hwif->channel ? 0x42 : 0x40;
-       int slave_port          = 0x44;
-       unsigned long flags;
-       u16 master_data;
-       u8 slave_data;
-       static DEFINE_SPINLOCK(tune_lock);
-       int control = 0;
-
-                                    /* ISP  RTC */
-       static const u8 timings[][2]= {
-                                       { 0, 0 },
-                                       { 0, 0 },
-                                       { 1, 0 },
-                                       { 2, 1 },
-                                       { 2, 3 }, };
-
-       /*
-        * Master vs slave is synchronized above us but the slave register is
-        * shared by the two hwifs so the corner case of two slave timeouts in
-        * parallel must be locked.
-        */
-       spin_lock_irqsave(&tune_lock, flags);
-       pci_read_config_word(dev, master_port, &master_data);
-
-       if (pio > 1)
-               control |= 1;   /* Programmable timing on */
-       if (drive->media == ide_disk)
-               control |= 4;   /* Prefetch, post write */
-       if (pio > 2)
-               control |= 2;   /* IORDY */
-       if (is_slave) {
-               master_data |=  0x4000;
-               master_data &= ~0x0070;
-               if (pio > 1) {
-                       /* Set PPE, IE and TIME */
-                       master_data |= control << 4;
-               }
-               pci_read_config_byte(dev, slave_port, &slave_data);
-               slave_data &= hwif->channel ? 0x0f : 0xf0;
-               slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
-                              (hwif->channel ? 4 : 0);
-       } else {
-               master_data &= ~0x3307;
-               if (pio > 1) {
-                       /* enable PPE, IE and TIME */
-                       master_data |= control;
-               }
-               master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
-       }
-       pci_write_config_word(dev, master_port, master_data);
-       if (is_slave)
-               pci_write_config_byte(dev, slave_port, slave_data);
-       spin_unlock_irqrestore(&tune_lock, flags);
-}
-
-/**
- *     piix_set_dma_mode       -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Set a PIIX host controller to the desired DMA mode.  This involves
- *     programming the right timing data into the PCI configuration space.
- */
-
-static void piix_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 maslave              = hwif->channel ? 0x42 : 0x40;
-       int a_speed             = 3 << (drive->dn * 4);
-       int u_flag              = 1 << drive->dn;
-       int v_flag              = 0x01 << drive->dn;
-       int w_flag              = 0x10 << drive->dn;
-       int u_speed             = 0;
-       int                     sitre;
-       u16                     reg4042, reg4a;
-       u8                      reg48, reg54, reg55;
-
-       pci_read_config_word(dev, maslave, &reg4042);
-       sitre = (reg4042 & 0x4000) ? 1 : 0;
-       pci_read_config_byte(dev, 0x48, &reg48);
-       pci_read_config_word(dev, 0x4a, &reg4a);
-       pci_read_config_byte(dev, 0x54, &reg54);
-       pci_read_config_byte(dev, 0x55, &reg55);
-
-       if (speed >= XFER_UDMA_0) {
-               u8 udma = speed - XFER_UDMA_0;
-
-               u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
-
-               if (!(reg48 & u_flag))
-                       pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-               if (speed == XFER_UDMA_5) {
-                       pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
-               } else {
-                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-               }
-               if ((reg4a & a_speed) != u_speed)
-                       pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
-               if (speed > XFER_UDMA_2) {
-                       if (!(reg54 & v_flag))
-                               pci_write_config_byte(dev, 0x54, reg54 | v_flag);
-               } else
-                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
-       } else {
-               const u8 mwdma_to_pio[] = { 0, 3, 4 };
-               u8 pio;
-
-               if (reg48 & u_flag)
-                       pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
-               if (reg4a & a_speed)
-                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
-               if (reg54 & v_flag)
-                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
-               if (reg55 & w_flag)
-                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-
-               if (speed >= XFER_MW_DMA_0)
-                       pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
-               else
-                       pio = 2; /* only SWDMA2 is allowed */
-
-               piix_set_pio_mode(drive, pio);
-       }
-}
-
-/**
- *     init_chipset_ich        -       set up the ICH chipset
- *     @dev: PCI device to set up
- *
- *     Initialize the PCI device as required.  For the ICH this turns
- *     out to be nice and simple.
- */
-
-static unsigned int init_chipset_ich(struct pci_dev *dev)
-{
-       u32 extra = 0;
-
-       pci_read_config_dword(dev, 0x54, &extra);
-       pci_write_config_dword(dev, 0x54, extra | 0x400);
-
-       return 0;
-}
-
-/**
- *     ich_clear_irq   -       clear BMDMA status
- *     @drive: IDE drive
- *
- *     ICHx contollers set DMA INTR no matter DMA or PIO.
- *     BMDMA status might need to be cleared even for
- *     PIO interrupts to prevent spurious/lost IRQ.
- */
-static void ich_clear_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       u8 dma_stat;
-
-       /*
-        * ide_dma_end() needs BMDMA status for error checking.
-        * So, skip clearing BMDMA status here and leave it
-        * to ide_dma_end() if this is DMA interrupt.
-        */
-       if (drive->waiting_for_dma || hwif->dma_base == 0)
-               return;
-
-       /* clear the INTR & ERROR bits */
-       dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
-       /* Should we force the bit as well ? */
-       outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
-}
-
-struct ich_laptop {
-       u16 device;
-       u16 subvendor;
-       u16 subdevice;
-};
-
-/*
- *     List of laptops that use short cables rather than 80 wire
- */
-
-static const struct ich_laptop ich_laptop[] = {
-       /* devid, subvendor, subdev */
-       { 0x27DF, 0x1025, 0x0102 },     /* ICH7 on Acer 5602aWLMi */
-       { 0x27DF, 0x0005, 0x0280 },     /* ICH7 on Acer 5602WLMi */
-       { 0x27DF, 0x1025, 0x0110 },     /* ICH7 on Acer 3682WLMi */
-       { 0x27DF, 0x1043, 0x1267 },     /* ICH7 on Asus W5F */
-       { 0x27DF, 0x103C, 0x30A1 },     /* ICH7 on HP Compaq nc2400 */
-       { 0x27DF, 0x1071, 0xD221 },     /* ICH7 on Hercules EC-900 */
-       { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on Acer Aspire 2023WLMi */
-       { 0x2653, 0x1043, 0x82D8 },     /* ICH6M on Asus Eee 701 */
-       /* end marker */
-       { 0, }
-};
-
-static u8 piix_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       const struct ich_laptop *lap = &ich_laptop[0];
-       u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
-
-       /* check for specials */
-       while (lap->device) {
-               if (lap->device == pdev->device &&
-                   lap->subvendor == pdev->subsystem_vendor &&
-                   lap->subdevice == pdev->subsystem_device) {
-                       return ATA_CBL_PATA40_SHORT;
-               }
-               lap++;
-       }
-
-       pci_read_config_byte(pdev, 0x54, &reg54h);
-
-       return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-}
-
-/**
- *     init_hwif_piix          -       fill in the hwif for the PIIX
- *     @hwif: IDE interface
- *
- *     Set up the ide_hwif_t for the PIIX interface according to the
- *     capabilities of the hardware.
- */
-
-static void __devinit init_hwif_piix(ide_hwif_t *hwif)
-{
-       if (!hwif->dma_base)
-               return;
-
-       if (no_piix_dma)
-               hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
-}
-
-static const struct ide_port_ops piix_port_ops = {
-       .set_pio_mode           = piix_set_pio_mode,
-       .set_dma_mode           = piix_set_dma_mode,
-       .cable_detect           = piix_cable_detect,
-};
-
-static const struct ide_port_ops ich_port_ops = {
-       .set_pio_mode           = piix_set_pio_mode,
-       .set_dma_mode           = piix_set_dma_mode,
-       .clear_irq              = ich_clear_irq,
-       .cable_detect           = piix_cable_detect,
-};
-
-#ifndef CONFIG_IA64
- #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
-#else
- #define IDE_HFLAGS_PIIX 0
-#endif
-
-#define DECLARE_PIIX_DEV(udma) \
-       {                                               \
-               .name           = DRV_NAME,             \
-               .init_hwif      = init_hwif_piix,       \
-               .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
-               .port_ops       = &piix_port_ops,       \
-               .host_flags     = IDE_HFLAGS_PIIX,      \
-               .pio_mask       = ATA_PIO4,             \
-               .swdma_mask     = ATA_SWDMA2_ONLY,      \
-               .mwdma_mask     = ATA_MWDMA12_ONLY,     \
-               .udma_mask      = udma,                 \
-       }
-
-#define DECLARE_ICH_DEV(udma) \
-       { \
-               .name           = DRV_NAME, \
-               .init_chipset   = init_chipset_ich, \
-               .init_hwif      = init_hwif_piix, \
-               .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
-               .port_ops       = &ich_port_ops, \
-               .host_flags     = IDE_HFLAGS_PIIX, \
-               .pio_mask       = ATA_PIO4, \
-               .swdma_mask     = ATA_SWDMA2_ONLY, \
-               .mwdma_mask     = ATA_MWDMA12_ONLY, \
-               .udma_mask      = udma, \
-       }
-
-static const struct ide_port_info piix_pci_info[] __devinitdata = {
-       /* 0: MPIIX */
-       {       /*
-                * MPIIX actually has only a single IDE channel mapped to
-                * the primary or secondary ports depending on the value
-                * of the bit 14 of the IDETIM register at offset 0x6c
-                */
-               .name           = DRV_NAME,
-               .enablebits     = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
-               .host_flags     = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
-                                 IDE_HFLAGS_PIIX,
-               .pio_mask       = ATA_PIO4,
-               /* This is a painful system best to let it self tune for now */
-       },
-       /* 1: PIIXa/PIIXb/PIIX3 */
-       DECLARE_PIIX_DEV(0x00), /* no udma */
-       /* 2: PIIX4 */
-       DECLARE_PIIX_DEV(ATA_UDMA2),
-       /* 3: ICH0 */
-       DECLARE_ICH_DEV(ATA_UDMA2),
-       /* 4: ICH */
-       DECLARE_ICH_DEV(ATA_UDMA4),
-       /* 5: PIIX4 */
-       DECLARE_PIIX_DEV(ATA_UDMA4),
-       /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
-       DECLARE_ICH_DEV(ATA_UDMA5),
-};
-
-/**
- *     piix_init_one   -       called when a PIIX is found
- *     @dev: the piix device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL);
-}
-
-/**
- *     piix_check_450nx        -       Check for problem 450NX setup
- *     
- *     Check for the present of 450NX errata #19 and errata #25. If
- *     they are found, disable use of DMA IDE
- */
-
-static void __devinit piix_check_450nx(void)
-{
-       struct pci_dev *pdev = NULL;
-       u16 cfg;
-       while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
-       {
-               /* Look for 450NX PXB. Check for problem configurations
-                  A PCI quirk checks bit 6 already */
-               pci_read_config_word(pdev, 0x41, &cfg);
-               /* Only on the original revision: IDE DMA can hang */
-               if (pdev->revision == 0x00)
-                       no_piix_dma = 1;
-               /* On all revisions below 5 PXB bus lock must be disabled for IDE */
-               else if (cfg & (1<<14) && pdev->revision < 5)
-                       no_piix_dma = 2;
-       }
-       if(no_piix_dma)
-               printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n");
-       if(no_piix_dma == 2)
-               printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n");
-}              
-
-static const struct pci_device_id piix_pci_tbl[] = {
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0),  1 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1),  1 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX),    0 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1),  1 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB),    2 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1),  3 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1),  2 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1),  4 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1),  5 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX),    2 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9),  6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8),  6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11),  6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 },
-#ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1),  6 },
-#endif
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
-
-static struct pci_driver piix_pci_driver = {
-       .name           = "PIIX_IDE",
-       .id_table       = piix_pci_tbl,
-       .probe          = piix_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init piix_ide_init(void)
-{
-       piix_check_450nx();
-       return ide_pci_register_driver(&piix_pci_driver);
-}
-
-static void __exit piix_ide_exit(void)
-{
-       pci_unregister_driver(&piix_pci_driver);
-}
-
-module_init(piix_ide_init);
-module_exit(piix_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");
-MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
deleted file mode 100644 (file)
index 7daf013..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *  Copyright (C) 1995-1998  Linus Torvalds & author (see below)
- */
-
-/*
- *  Principal Author:  mlord@pobox.com (Mark Lord)
- *
- *  See linux/MAINTAINERS for address of current maintainer.
- *
- *  This file provides support for disabling the buggy read-ahead
- *  mode of the RZ1000 IDE chipset, commonly used on Intel motherboards.
- *
- *  Dunno if this fixes both ports, or only the primary port (?).
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "rz1000"
-
-static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u16 reg;
-
-       if (!pci_read_config_word (dev, 0x40, &reg) &&
-           !pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
-               printk(KERN_INFO "%s: disabled chipset read-ahead "
-                       "(buggy RZ1000/RZ1001)\n", hwif->name);
-       } else {
-               if (hwif->mate)
-                       hwif->mate->serialized = hwif->serialized = 1;
-               hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
-               printk(KERN_INFO "%s: serialized, disabled unmasking "
-                       "(buggy RZ1000/RZ1001)\n", hwif->name);
-       }
-}
-
-static const struct ide_port_info rz1000_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_hwif      = init_hwif_rz1000,
-       .chipset        = ide_rz1000,
-       .host_flags     = IDE_HFLAG_NO_DMA,
-};
-
-static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &rz1000_chipset, NULL);
-}
-
-static const struct pci_device_id rz1000_pci_tbl[] = {
-       { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), 0 },
-       { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
-
-static struct pci_driver rz1000_pci_driver = {
-       .name           = "RZ1000_IDE",
-       .id_table       = rz1000_pci_tbl,
-       .probe          = rz1000_init_one,
-       .remove         = ide_pci_remove,
-};
-
-static int __init rz1000_ide_init(void)
-{
-       return ide_pci_register_driver(&rz1000_pci_driver);
-}
-
-static void __exit rz1000_ide_exit(void)
-{
-       pci_unregister_driver(&rz1000_pci_driver);
-}
-
-module_init(rz1000_ide_init);
-module_exit(rz1000_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
deleted file mode 100644 (file)
index f1a8758..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2000-2002             Mark Lord <mlord@pobox.com>
- * Copyright (C)      2007             Bartlomiej Zolnierkiewicz
- *
- * May be copied or modified under the terms of the GNU General Public License
- *
- * Development of this chipset driver was funded
- * by the nice folks at National Semiconductor.
- *
- * Documentation:
- *     Available from National Semiconductor
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/pm.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "sc1200"
-
-#define SC1200_REV_A   0x00
-#define SC1200_REV_B1  0x01
-#define SC1200_REV_B3  0x02
-#define SC1200_REV_C1  0x03
-#define SC1200_REV_D1  0x04
-
-#define PCI_CLK_33     0x00
-#define PCI_CLK_48     0x01
-#define PCI_CLK_66     0x02
-#define PCI_CLK_33A    0x03
-
-static unsigned short sc1200_get_pci_clock (void)
-{
-       unsigned char chip_id, silicon_revision;
-       unsigned int pci_clock;
-       /*
-        * Check the silicon revision, as not all versions of the chip
-        * have the register with the fast PCI bus timings.
-        */
-       chip_id = inb (0x903c);
-       silicon_revision = inb (0x903d);
-
-       // Read the fast pci clock frequency
-       if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) {
-               pci_clock = PCI_CLK_33;
-       } else {
-               // check clock generator configuration (cfcc)
-               // the clock is in bits 8 and 9 of this word
-
-               pci_clock = inw (0x901e);
-               pci_clock >>= 8;
-               pci_clock &= 0x03;
-               if (pci_clock == PCI_CLK_33A)
-                       pci_clock = PCI_CLK_33;
-       }
-       return pci_clock;
-}
-
-/*
- * Here are the standard PIO mode 0-4 timings for each "format".
- * Format-0 uses fast data reg timings, with slower command reg timings.
- * Format-1 uses fast timings for all registers, but won't work with all drives.
- */
-static const unsigned int sc1200_pio_timings[4][5] =
-       {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},  // format0  33Mhz
-        {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},  // format1, 33Mhz
-        {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},  // format1, 48Mhz
-        {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz
-
-/*
- * After chip reset, the PIO timings are set to 0x00009172, which is not valid.
- */
-//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
-
-static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
-
-       pci_read_config_dword(pdev, basereg + 4, &format);
-       format = (format >> 31) & 1;
-       if (format)
-               format += sc1200_get_pci_clock();
-       pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3),
-                              sc1200_pio_timings[format][pio]);
-}
-
-/*
- *     The SC1200 specifies that two drives sharing a cable cannot mix
- *     UDMA/MDMA.  It has to be one or the other, for the pair, though
- *     different timings can still be chosen for each drive.  We could
- *     set the appropriate timing bits on the fly, but that might be
- *     a bit confusing.  So, for now we statically handle this requirement
- *     by looking at our mate drive to see what it is capable of, before
- *     choosing a mode for our own drive.
- */
-static u8 sc1200_udma_filter(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       ide_drive_t *mate = ide_get_pair_dev(drive);
-       u16 *mateid = mate->id;
-       u8 mask = hwif->ultra_mask;
-
-       if (mate == NULL)
-               goto out;
-
-       if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
-               if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
-                   (mateid[ATA_ID_UDMA_MODES] & 7))
-                       goto out;
-               if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
-                   (mateid[ATA_ID_MWDMA_MODES] & 7))
-                       mask = 0;
-       }
-out:
-       return mask;
-}
-
-static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
-{
-       ide_hwif_t              *hwif = HWIF(drive);
-       struct pci_dev          *dev = to_pci_dev(hwif->dev);
-       unsigned int            reg, timings;
-       unsigned short          pci_clock;
-       unsigned int            basereg = hwif->channel ? 0x50 : 0x40;
-
-       static const u32 udma_timing[3][3] = {
-               { 0x00921250, 0x00911140, 0x00911030 },
-               { 0x00932470, 0x00922260, 0x00922140 },
-               { 0x009436a1, 0x00933481, 0x00923261 },
-       };
-
-       static const u32 mwdma_timing[3][3] = {
-               { 0x00077771, 0x00012121, 0x00002020 },
-               { 0x000bbbb2, 0x00024241, 0x00013131 },
-               { 0x000ffff3, 0x00035352, 0x00015151 },
-       };
-
-       pci_clock = sc1200_get_pci_clock();
-
-       /*
-        * Note that each DMA mode has several timings associated with it.
-        * The correct timing depends on the fast PCI clock freq.
-        */
-
-       if (mode >= XFER_UDMA_0)
-               timings =  udma_timing[pci_clock][mode - XFER_UDMA_0];
-       else
-               timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
-
-       if ((drive->dn & 1) == 0) {
-               pci_read_config_dword(dev, basereg + 4, &reg);
-               timings |= reg & 0x80000000;    /* preserve PIO format bit */
-               pci_write_config_dword(dev, basereg + 4, timings);
-       } else
-               pci_write_config_dword(dev, basereg + 12, timings);
-}
-
-/*  Replacement for the standard ide_dma_end action in
- *  dma_proc.
- *
- *  returns 1 on error, 0 otherwise
- */
-static int sc1200_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned long dma_base = hwif->dma_base;
-       byte dma_stat;
-
-       dma_stat = inb(dma_base+2);             /* get DMA status */
-
-       if (!(dma_stat & 4))
-               printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n",
-                 dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2));
-
-       outb(dma_stat|0x1b, dma_base+2);        /* clear the INTR & ERROR bits */
-       outb(inb(dma_base)&~1, dma_base);       /* !! DO THIS HERE !! stop DMA */
-
-       drive->waiting_for_dma = 0;
-       ide_destroy_dmatable(drive);            /* purge DMA mappings */
-
-       return (dma_stat & 7) != 4;             /* verify good DMA status */
-}
-
-/*
- * sc1200_set_pio_mode() handles setting of PIO modes
- * for both the chipset and drive.
- *
- * All existing BIOSs for this chipset guarantee that all drives
- * will have valid default PIO timings set up before we get here.
- */
-
-static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t      *hwif = HWIF(drive);
-       int             mode = -1;
-
-       /*
-        * bad abuse of ->set_pio_mode interface
-        */
-       switch (pio) {
-               case 200: mode = XFER_UDMA_0;   break;
-               case 201: mode = XFER_UDMA_1;   break;
-               case 202: mode = XFER_UDMA_2;   break;
-               case 100: mode = XFER_MW_DMA_0; break;
-               case 101: mode = XFER_MW_DMA_1; break;
-               case 102: mode = XFER_MW_DMA_2; break;
-       }
-       if (mode != -1) {
-               printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
-               ide_dma_off_quietly(drive);
-               if (ide_set_dma_mode(drive, mode) == 0 &&
-                   (drive->dev_flags & IDE_DFLAG_USING_DMA))
-                       hwif->dma_ops->dma_host_set(drive, 1);
-               return;
-       }
-
-       sc1200_tunepio(drive, pio);
-}
-
-#ifdef CONFIG_PM
-struct sc1200_saved_state {
-       u32 regs[8];
-};
-
-static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
-{
-       printk("SC1200: suspend(%u)\n", state.event);
-
-       /*
-        * we only save state when going from full power to less
-        */
-       if (state.event == PM_EVENT_ON) {
-               struct ide_host *host = pci_get_drvdata(dev);
-               struct sc1200_saved_state *ss = host->host_priv;
-               unsigned int r;
-
-               /*
-                * save timing registers
-                * (this may be unnecessary if BIOS also does it)
-                */
-               for (r = 0; r < 8; r++)
-                       pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
-       }
-
-       pci_disable_device(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
-       return 0;
-}
-
-static int sc1200_resume (struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct sc1200_saved_state *ss = host->host_priv;
-       unsigned int r;
-       int i;
-
-       i = pci_enable_device(dev);
-       if (i)
-               return i;
-
-       /*
-        * restore timing registers
-        * (this may be unnecessary if BIOS also does it)
-        */
-       for (r = 0; r < 8; r++)
-               pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
-
-       return 0;
-}
-#endif
-
-static const struct ide_port_ops sc1200_port_ops = {
-       .set_pio_mode           = sc1200_set_pio_mode,
-       .set_dma_mode           = sc1200_set_dma_mode,
-       .udma_filter            = sc1200_udma_filter,
-};
-
-static const struct ide_dma_ops sc1200_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                = sc1200_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info sc1200_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .port_ops       = &sc1200_port_ops,
-       .dma_ops        = &sc1200_dma_ops,
-       .host_flags     = IDE_HFLAG_SERIALIZE |
-                         IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_ABUSE_DMA_MODES,
-       .pio_mask       = ATA_PIO4,
-       .mwdma_mask     = ATA_MWDMA2,
-       .udma_mask      = ATA_UDMA2,
-};
-
-static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct sc1200_saved_state *ss = NULL;
-       int rc;
-
-#ifdef CONFIG_PM
-       ss = kmalloc(sizeof(*ss), GFP_KERNEL);
-       if (ss == NULL)
-               return -ENOMEM;
-#endif
-       rc = ide_pci_init_one(dev, &sc1200_chipset, ss);
-       if (rc)
-               kfree(ss);
-
-       return rc;
-}
-
-static const struct pci_device_id sc1200_pci_tbl[] = {
-       { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0},
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
-
-static struct pci_driver sc1200_pci_driver = {
-       .name           = "SC1200_IDE",
-       .id_table       = sc1200_pci_tbl,
-       .probe          = sc1200_init_one,
-       .remove         = ide_pci_remove,
-#ifdef CONFIG_PM
-       .suspend        = sc1200_suspend,
-       .resume         = sc1200_resume,
-#endif
-};
-
-static int __init sc1200_ide_init(void)
-{
-       return ide_pci_register_driver(&sc1200_pci_driver);
-}
-
-static void __exit sc1200_ide_exit(void)
-{
-       pci_unregister_driver(&sc1200_pci_driver);
-}
-
-module_init(sc1200_ide_init);
-module_exit(sc1200_ide_exit);
-
-MODULE_AUTHOR("Mark Lord");
-MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
deleted file mode 100644 (file)
index 49f163a..0000000
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Support for IDE interfaces on Celleb platform
- *
- * (C) Copyright 2006 TOSHIBA CORPORATION
- *
- * This code is based on drivers/ide/pci/siimage.c:
- * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003          Red Hat <alan@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA            0x01b4
-
-#define SCC_PATA_NAME           "scc IDE"
-
-#define TDVHSEL_MASTER          0x00000001
-#define TDVHSEL_SLAVE           0x00000004
-
-#define MODE_JCUSFEN            0x00000080
-
-#define CCKCTRL_ATARESET        0x00040000
-#define CCKCTRL_BUFCNT          0x00020000
-#define CCKCTRL_CRST            0x00010000
-#define CCKCTRL_OCLKEN          0x00000100
-#define CCKCTRL_ATACLKOEN       0x00000002
-#define CCKCTRL_LCLKEN          0x00000001
-
-#define QCHCD_IOS_SS           0x00000001
-
-#define QCHSD_STPDIAG          0x00020000
-
-#define INTMASK_MSK             0xD1000012
-#define INTSTS_SERROR          0x80000000
-#define INTSTS_PRERR           0x40000000
-#define INTSTS_RERR            0x10000000
-#define INTSTS_ICERR           0x01000000
-#define INTSTS_BMSINT          0x00000010
-#define INTSTS_BMHE            0x00000008
-#define INTSTS_IOIRQS           0x00000004
-#define INTSTS_INTRQ            0x00000002
-#define INTSTS_ACTEINT          0x00000001
-
-#define ECMODE_VALUE 0x01
-
-static struct scc_ports {
-       unsigned long ctl, dma;
-       struct ide_host *host;  /* for removing port from system */
-} scc_ports[MAX_HWIFS];
-
-/* PIO transfer mode  table */
-/* JCHST */
-static unsigned long JCHSTtbl[2][7] = {
-       {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00},   /* 100MHz */
-       {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00}    /* 133MHz */
-};
-
-/* JCHHT */
-static unsigned long JCHHTtbl[2][7] = {
-       {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00},   /* 100MHz */
-       {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}    /* 133MHz */
-};
-
-/* JCHCT */
-static unsigned long JCHCTtbl[2][7] = {
-       {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00},   /* 100MHz */
-       {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00}    /* 133MHz */
-};
-
-
-/* DMA transfer mode  table */
-/* JCHDCTM/JCHDCTS */
-static unsigned long JCHDCTxtbl[2][7] = {
-       {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00},   /* 100MHz */
-       {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00}    /* 133MHz */
-};
-
-/* JCSTWTM/JCSTWTS  */
-static unsigned long JCSTWTxtbl[2][7] = {
-       {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00},   /* 100MHz */
-       {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
-};
-
-/* JCTSS */
-static unsigned long JCTSStbl[2][7] = {
-       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00},   /* 100MHz */
-       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05}    /* 133MHz */
-};
-
-/* JCENVT */
-static unsigned long JCENVTtbl[2][7] = {
-       {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00},   /* 100MHz */
-       {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
-};
-
-/* JCACTSELS/JCACTSELM */
-static unsigned long JCACTSELtbl[2][7] = {
-       {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00},   /* 100MHz */
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}    /* 133MHz */
-};
-
-
-static u8 scc_ide_inb(unsigned long port)
-{
-       u32 data = in_be32((void*)port);
-       return (u8)data;
-}
-
-static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
-{
-       out_be32((void *)hwif->io_ports.command_addr, cmd);
-       eieio();
-       in_be32((void *)(hwif->dma_base + 0x01c));
-       eieio();
-}
-
-static u8 scc_read_status(ide_hwif_t *hwif)
-{
-       return (u8)in_be32((void *)hwif->io_ports.status_addr);
-}
-
-static u8 scc_read_altstatus(ide_hwif_t *hwif)
-{
-       return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
-}
-
-static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
-{
-       return (u8)in_be32((void *)(hwif->dma_base + 4));
-}
-
-static void scc_set_irq(ide_hwif_t *hwif, int on)
-{
-       u8 ctl = ATA_DEVCTL_OBS;
-
-       if (on == 4) { /* hack for SRST */
-               ctl |= 4;
-               on &= ~4;
-       }
-
-       ctl |= on ? 0 : 2;
-
-       out_be32((void *)hwif->io_ports.ctl_addr, ctl);
-       eieio();
-       in_be32((void *)(hwif->dma_base + 0x01c));
-       eieio();
-}
-
-static void scc_ide_insw(unsigned long port, void *addr, u32 count)
-{
-       u16 *ptr = (u16 *)addr;
-       while (count--) {
-               *ptr++ = le16_to_cpu(in_be32((void*)port));
-       }
-}
-
-static void scc_ide_insl(unsigned long port, void *addr, u32 count)
-{
-       u16 *ptr = (u16 *)addr;
-       while (count--) {
-               *ptr++ = le16_to_cpu(in_be32((void*)port));
-               *ptr++ = le16_to_cpu(in_be32((void*)port));
-       }
-}
-
-static void scc_ide_outb(u8 addr, unsigned long port)
-{
-       out_be32((void*)port, addr);
-}
-
-static void
-scc_ide_outsw(unsigned long port, void *addr, u32 count)
-{
-       u16 *ptr = (u16 *)addr;
-       while (count--) {
-               out_be32((void*)port, cpu_to_le16(*ptr++));
-       }
-}
-
-static void
-scc_ide_outsl(unsigned long port, void *addr, u32 count)
-{
-       u16 *ptr = (u16 *)addr;
-       while (count--) {
-               out_be32((void*)port, cpu_to_le16(*ptr++));
-               out_be32((void*)port, cpu_to_le16(*ptr++));
-       }
-}
-
-/**
- *     scc_set_pio_mode        -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Load the timing settings for this device mode into the
- *     controller.
- */
-
-static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct scc_ports *ports = ide_get_hwifdata(hwif);
-       unsigned long ctl_base = ports->ctl;
-       unsigned long cckctrl_port = ctl_base + 0xff0;
-       unsigned long piosht_port = ctl_base + 0x000;
-       unsigned long pioct_port = ctl_base + 0x004;
-       unsigned long reg;
-       int offset;
-
-       reg = in_be32((void __iomem *)cckctrl_port);
-       if (reg & CCKCTRL_ATACLKOEN) {
-               offset = 1; /* 133MHz */
-       } else {
-               offset = 0; /* 100MHz */
-       }
-       reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio];
-       out_be32((void __iomem *)piosht_port, reg);
-       reg = JCHCTtbl[offset][pio];
-       out_be32((void __iomem *)pioct_port, reg);
-}
-
-/**
- *     scc_set_dma_mode        -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Load the timing settings for this device mode into the
- *     controller.
- */
-
-static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct scc_ports *ports = ide_get_hwifdata(hwif);
-       unsigned long ctl_base = ports->ctl;
-       unsigned long cckctrl_port = ctl_base + 0xff0;
-       unsigned long mdmact_port = ctl_base + 0x008;
-       unsigned long mcrcst_port = ctl_base + 0x00c;
-       unsigned long sdmact_port = ctl_base + 0x010;
-       unsigned long scrcst_port = ctl_base + 0x014;
-       unsigned long udenvt_port = ctl_base + 0x018;
-       unsigned long tdvhsel_port   = ctl_base + 0x020;
-       int is_slave = (&hwif->drives[1] == drive);
-       int offset, idx;
-       unsigned long reg;
-       unsigned long jcactsel;
-
-       reg = in_be32((void __iomem *)cckctrl_port);
-       if (reg & CCKCTRL_ATACLKOEN) {
-               offset = 1; /* 133MHz */
-       } else {
-               offset = 0; /* 100MHz */
-       }
-
-       idx = speed - XFER_UDMA_0;
-
-       jcactsel = JCACTSELtbl[offset][idx];
-       if (is_slave) {
-               out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]);
-               out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]);
-               jcactsel = jcactsel << 2;
-               out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel);
-       } else {
-               out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]);
-               out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]);
-               out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel);
-       }
-       reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
-       out_be32((void __iomem *)udenvt_port, reg);
-}
-
-static void scc_dma_host_set(ide_drive_t *drive, int on)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 unit = drive->dn & 1;
-       u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
-
-       if (on)
-               dma_stat |= (1 << (5 + unit));
-       else
-               dma_stat &= ~(1 << (5 + unit));
-
-       scc_ide_outb(dma_stat, hwif->dma_base + 4);
-}
-
-/**
- *     scc_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.
- *
- *     Returns 0 on success. If a PIO fallback is required then 1
- *     is returned.
- */
-
-static int scc_dma_setup(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = HWGROUP(drive)->rq;
-       unsigned int reading;
-       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 */
-       out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
-
-       /* specify r/w */
-       out_be32((void __iomem *)hwif->dma_base, reading);
-
-       /* read DMA status for INTR & ERROR flags */
-       dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
-
-       /* clear INTR & ERROR flags */
-       out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
-       drive->waiting_for_dma = 1;
-       return 0;
-}
-
-static void scc_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 dma_cmd = scc_ide_inb(hwif->dma_base);
-
-       /* start DMA */
-       scc_ide_outb(dma_cmd | 1, hwif->dma_base);
-       wmb();
-}
-
-static int __scc_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 dma_stat, dma_cmd;
-
-       drive->waiting_for_dma = 0;
-       /* get DMA command mode */
-       dma_cmd = scc_ide_inb(hwif->dma_base);
-       /* stop DMA */
-       scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
-       /* get DMA status */
-       dma_stat = scc_ide_inb(hwif->dma_base + 4);
-       /* clear the INTR & ERROR bits */
-       scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
-       /* purge DMA mappings */
-       ide_destroy_dmatable(drive);
-       /* verify good DMA status */
-       wmb();
-       return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
-}
-
-/**
- *     scc_dma_end     -       Stop DMA
- *     @drive: IDE drive
- *
- *     Check and clear INT Status register.
- *     Then call __scc_dma_end().
- */
-
-static int scc_dma_end(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       void __iomem *dma_base = (void __iomem *)hwif->dma_base;
-       unsigned long intsts_port = hwif->dma_base + 0x014;
-       u32 reg;
-       int dma_stat, data_loss = 0;
-       static int retry = 0;
-
-       /* errata A308 workaround: Step5 (check data loss) */
-       /* We don't check non ide_disk because it is limited to UDMA4 */
-       if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr)
-             & ATA_ERR) &&
-           drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
-               reg = in_be32((void __iomem *)intsts_port);
-               if (!(reg & INTSTS_ACTEINT)) {
-                       printk(KERN_WARNING "%s: operation failed (transfer data loss)\n",
-                              drive->name);
-                       data_loss = 1;
-                       if (retry++) {
-                               struct request *rq = HWGROUP(drive)->rq;
-                               int unit;
-                               /* ERROR_RESET and drive->crc_count are needed
-                                * to reduce DMA transfer mode in retry process.
-                                */
-                               if (rq)
-                                       rq->errors |= ERROR_RESET;
-                               for (unit = 0; unit < MAX_DRIVES; unit++) {
-                                       ide_drive_t *drive = &hwif->drives[unit];
-                                       drive->crc_count++;
-                               }
-                       }
-               }
-       }
-
-       while (1) {
-               reg = in_be32((void __iomem *)intsts_port);
-
-               if (reg & INTSTS_SERROR) {
-                       printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
-                       out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
-
-                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
-                       continue;
-               }
-
-               if (reg & INTSTS_PRERR) {
-                       u32 maea0, maec0;
-                       unsigned long ctl_base = hwif->config_data;
-
-                       maea0 = in_be32((void __iomem *)(ctl_base + 0xF50));
-                       maec0 = in_be32((void __iomem *)(ctl_base + 0xF54));
-
-                       printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0);
-
-                       out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
-
-                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
-                       continue;
-               }
-
-               if (reg & INTSTS_RERR) {
-                       printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
-                       out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
-
-                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
-                       continue;
-               }
-
-               if (reg & INTSTS_ICERR) {
-                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
-
-                       printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
-                       out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
-                       continue;
-               }
-
-               if (reg & INTSTS_BMSINT) {
-                       printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME);
-                       out_be32((void __iomem *)intsts_port, INTSTS_BMSINT);
-
-                       ide_do_reset(drive);
-                       continue;
-               }
-
-               if (reg & INTSTS_BMHE) {
-                       out_be32((void __iomem *)intsts_port, INTSTS_BMHE);
-                       continue;
-               }
-
-               if (reg & INTSTS_ACTEINT) {
-                       out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT);
-                       continue;
-               }
-
-               if (reg & INTSTS_IOIRQS) {
-                       out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS);
-                       continue;
-               }
-               break;
-       }
-
-       dma_stat = __scc_dma_end(drive);
-       if (data_loss)
-               dma_stat |= 2; /* emulate DMA error (to retry command) */
-       return dma_stat;
-}
-
-/* returns 1 if dma irq issued, 0 otherwise */
-static int scc_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
-
-       /* SCC errata A252,A308 workaround: Step4 */
-       if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
-            & ATA_ERR) &&
-           (int_stat & INTSTS_INTRQ))
-               return 1;
-
-       /* SCC errata A308 workaround: Step5 (polling IOIRQS) */
-       if (int_stat & INTSTS_IOIRQS)
-               return 1;
-
-       return 0;
-}
-
-static u8 scc_udma_filter(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 mask = hwif->ultra_mask;
-
-       /* errata A308 workaround: limit non ide_disk drive to UDMA4 */
-       if ((drive->media != ide_disk) && (mask & 0xE0)) {
-               printk(KERN_INFO "%s: limit %s to UDMA4\n",
-                      SCC_PATA_NAME, drive->name);
-               mask = ATA_UDMA4;
-       }
-
-       return mask;
-}
-
-/**
- *     setup_mmio_scc  -       map CTRL/BMID region
- *     @dev: PCI device we are configuring
- *     @name: device name
- *
- */
-
-static int setup_mmio_scc (struct pci_dev *dev, const char *name)
-{
-       unsigned long ctl_base = pci_resource_start(dev, 0);
-       unsigned long dma_base = pci_resource_start(dev, 1);
-       unsigned long ctl_size = pci_resource_len(dev, 0);
-       unsigned long dma_size = pci_resource_len(dev, 1);
-       void __iomem *ctl_addr;
-       void __iomem *dma_addr;
-       int i, ret;
-
-       for (i = 0; i < MAX_HWIFS; i++) {
-               if (scc_ports[i].ctl == 0)
-                       break;
-       }
-       if (i >= MAX_HWIFS)
-               return -ENOMEM;
-
-       ret = pci_request_selected_regions(dev, (1 << 2) - 1, name);
-       if (ret < 0) {
-               printk(KERN_ERR "%s: can't reserve resources\n", name);
-               return ret;
-       }
-
-       if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
-               goto fail_0;
-
-       if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
-               goto fail_1;
-
-       pci_set_master(dev);
-       scc_ports[i].ctl = (unsigned long)ctl_addr;
-       scc_ports[i].dma = (unsigned long)dma_addr;
-       pci_set_drvdata(dev, (void *) &scc_ports[i]);
-
-       return 1;
-
- fail_1:
-       iounmap(ctl_addr);
- fail_0:
-       return -ENOMEM;
-}
-
-static int scc_ide_setup_pci_device(struct pci_dev *dev,
-                                   const struct ide_port_info *d)
-{
-       struct scc_ports *ports = pci_get_drvdata(dev);
-       struct ide_host *host;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-       int i, rc;
-
-       memset(&hw, 0, sizeof(hw));
-       for (i = 0; i <= 8; i++)
-               hw.io_ports_array[i] = ports->dma + 0x20 + i * 4;
-       hw.irq = dev->irq;
-       hw.dev = &dev->dev;
-       hw.chipset = ide_pci;
-
-       rc = ide_host_add(d, hws, &host);
-       if (rc)
-               return rc;
-
-       ports->host = host;
-
-       return 0;
-}
-
-/**
- *     init_setup_scc  -       set up an SCC PATA Controller
- *     @dev: PCI device
- *     @d: IDE port info
- *
- *     Perform the initial set up for this device.
- */
-
-static int __devinit init_setup_scc(struct pci_dev *dev,
-                                   const struct ide_port_info *d)
-{
-       unsigned long ctl_base;
-       unsigned long dma_base;
-       unsigned long cckctrl_port;
-       unsigned long intmask_port;
-       unsigned long mode_port;
-       unsigned long ecmode_port;
-       u32 reg = 0;
-       struct scc_ports *ports;
-       int rc;
-
-       rc = pci_enable_device(dev);
-       if (rc)
-               goto end;
-
-       rc = setup_mmio_scc(dev, d->name);
-       if (rc < 0)
-               goto end;
-
-       ports = pci_get_drvdata(dev);
-       ctl_base = ports->ctl;
-       dma_base = ports->dma;
-       cckctrl_port = ctl_base + 0xff0;
-       intmask_port = dma_base + 0x010;
-       mode_port = ctl_base + 0x024;
-       ecmode_port = ctl_base + 0xf00;
-
-       /* controller initialization */
-       reg = 0;
-       out_be32((void*)cckctrl_port, reg);
-       reg |= CCKCTRL_ATACLKOEN;
-       out_be32((void*)cckctrl_port, reg);
-       reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
-       out_be32((void*)cckctrl_port, reg);
-       reg |= CCKCTRL_CRST;
-       out_be32((void*)cckctrl_port, reg);
-
-       for (;;) {
-               reg = in_be32((void*)cckctrl_port);
-               if (reg & CCKCTRL_CRST)
-                       break;
-               udelay(5000);
-       }
-
-       reg |= CCKCTRL_ATARESET;
-       out_be32((void*)cckctrl_port, reg);
-
-       out_be32((void*)ecmode_port, ECMODE_VALUE);
-       out_be32((void*)mode_port, MODE_JCUSFEN);
-       out_be32((void*)intmask_port, INTMASK_MSK);
-
-       rc = scc_ide_setup_pci_device(dev, d);
-
- end:
-       return rc;
-}
-
-static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
-{
-       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-       struct ide_taskfile *tf = &task->tf;
-       u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
-
-       if (task->tf_flags & IDE_TFLAG_FLAGGED)
-               HIHI = 0xFF;
-
-       if (task->tf_flags & IDE_TFLAG_OUT_DATA)
-               out_be32((void *)io_ports->data_addr,
-                        (tf->hob_data << 8) | tf->data);
-
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-               scc_ide_outb(tf->hob_feature, io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-               scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-               scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-               scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-               scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr);
-
-       if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
-               scc_ide_outb(tf->feature, io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
-               scc_ide_outb(tf->nsect, io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
-               scc_ide_outb(tf->lbal, io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
-               scc_ide_outb(tf->lbam, io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
-               scc_ide_outb(tf->lbah, io_ports->lbah_addr);
-
-       if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               scc_ide_outb((tf->device & HIHI) | drive->select,
-                            io_ports->device_addr);
-}
-
-static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
-{
-       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-       struct ide_taskfile *tf = &task->tf;
-
-       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-               u16 data = (u16)in_be32((void *)io_ports->data_addr);
-
-               tf->data = data & 0xff;
-               tf->hob_data = (data >> 8) & 0xff;
-       }
-
-       /* be sure we're looking at the low order bits */
-       scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
-
-       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
-               tf->feature = scc_ide_inb(io_ports->feature_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-               tf->nsect  = scc_ide_inb(io_ports->nsect_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-               tf->lbal   = scc_ide_inb(io_ports->lbal_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-               tf->lbam   = scc_ide_inb(io_ports->lbam_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-               tf->lbah   = scc_ide_inb(io_ports->lbah_addr);
-       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-               tf->device = scc_ide_inb(io_ports->device_addr);
-
-       if (task->tf_flags & IDE_TFLAG_LBA48) {
-               scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
-
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-                       tf->hob_feature = scc_ide_inb(io_ports->feature_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-                       tf->hob_nsect   = scc_ide_inb(io_ports->nsect_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-                       tf->hob_lbal    = scc_ide_inb(io_ports->lbal_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-                       tf->hob_lbam    = scc_ide_inb(io_ports->lbam_addr);
-               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-                       tf->hob_lbah    = scc_ide_inb(io_ports->lbah_addr);
-       }
-}
-
-static void scc_input_data(ide_drive_t *drive, struct request *rq,
-                          void *buf, unsigned int len)
-{
-       unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
-       len++;
-
-       if (drive->io_32bit) {
-               scc_ide_insl(data_addr, buf, len / 4);
-
-               if ((len & 3) >= 2)
-                       scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1);
-       } else
-               scc_ide_insw(data_addr, buf, len / 2);
-}
-
-static void scc_output_data(ide_drive_t *drive,  struct request *rq,
-                           void *buf, unsigned int len)
-{
-       unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
-       len++;
-
-       if (drive->io_32bit) {
-               scc_ide_outsl(data_addr, buf, len / 4);
-
-               if ((len & 3) >= 2)
-                       scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1);
-       } else
-               scc_ide_outsw(data_addr, buf, len / 2);
-}
-
-/**
- *     init_mmio_iops_scc      -       set up the iops for MMIO
- *     @hwif: interface to set up
- *
- */
-
-static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct scc_ports *ports = pci_get_drvdata(dev);
-       unsigned long dma_base = ports->dma;
-
-       ide_set_hwifdata(hwif, ports);
-
-       hwif->dma_base = dma_base;
-       hwif->config_data = ports->ctl;
-}
-
-/**
- *     init_iops_scc   -       set up iops
- *     @hwif: interface to set up
- *
- *     Do the basic setup for the SCC hardware interface
- *     and then do the MMIO setup.
- */
-
-static void __devinit init_iops_scc(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       hwif->hwif_data = NULL;
-       if (pci_get_drvdata(dev) == NULL)
-               return;
-       init_mmio_iops_scc(hwif);
-}
-
-static int __devinit scc_init_dma(ide_hwif_t *hwif,
-                                 const struct ide_port_info *d)
-{
-       return ide_allocate_dma_engine(hwif);
-}
-
-static u8 scc_cable_detect(ide_hwif_t *hwif)
-{
-       return ATA_CBL_PATA80;
-}
-
-/**
- *     init_hwif_scc   -       set up hwif
- *     @hwif: interface to set up
- *
- *     We do the basic set up of the interface structure. The SCC
- *     requires several custom handlers so we override the default
- *     ide DMA handlers appropriately.
- */
-
-static void __devinit init_hwif_scc(ide_hwif_t *hwif)
-{
-       /* PTERADD */
-       out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
-
-       if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
-               hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
-       else
-               hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
-}
-
-static const struct ide_tp_ops scc_tp_ops = {
-       .exec_command           = scc_exec_command,
-       .read_status            = scc_read_status,
-       .read_altstatus         = scc_read_altstatus,
-       .read_sff_dma_status    = scc_read_sff_dma_status,
-
-       .set_irq                = scc_set_irq,
-
-       .tf_load                = scc_tf_load,
-       .tf_read                = scc_tf_read,
-
-       .input_data             = scc_input_data,
-       .output_data            = scc_output_data,
-};
-
-static const struct ide_port_ops scc_port_ops = {
-       .set_pio_mode           = scc_set_pio_mode,
-       .set_dma_mode           = scc_set_dma_mode,
-       .udma_filter            = scc_udma_filter,
-       .cable_detect           = scc_cable_detect,
-};
-
-static const struct ide_dma_ops scc_dma_ops = {
-       .dma_host_set           = scc_dma_host_set,
-       .dma_setup              = scc_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = scc_dma_start,
-       .dma_end                = scc_dma_end,
-       .dma_test_irq           = scc_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-#define DECLARE_SCC_DEV(name_str)                      \
-  {                                                    \
-      .name            = name_str,                     \
-      .init_iops       = init_iops_scc,                \
-      .init_dma                = scc_init_dma,                 \
-      .init_hwif       = init_hwif_scc,                \
-      .tp_ops          = &scc_tp_ops,          \
-      .port_ops                = &scc_port_ops,                \
-      .dma_ops         = &scc_dma_ops,                 \
-      .host_flags      = IDE_HFLAG_SINGLE,             \
-      .pio_mask                = ATA_PIO4,                     \
-  }
-
-static const struct ide_port_info scc_chipsets[] __devinitdata = {
-       /* 0 */ DECLARE_SCC_DEV("sccIDE"),
-};
-
-/**
- *     scc_init_one    -       pci layer discovery entry
- *     @dev: PCI device
- *     @id: ident table entry
- *
- *     Called by the PCI code when it finds an SCC PATA controller.
- *     We then use the IDE PCI generic helper to do most of the work.
- */
-
-static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return init_setup_scc(dev, &scc_chipsets[id->driver_data]);
-}
-
-/**
- *     scc_remove      -       pci layer remove entry
- *     @dev: PCI device
- *
- *     Called by the PCI code when it removes an SCC PATA controller.
- */
-
-static void __devexit scc_remove(struct pci_dev *dev)
-{
-       struct scc_ports *ports = pci_get_drvdata(dev);
-       struct ide_host *host = ports->host;
-
-       ide_host_remove(host);
-
-       iounmap((void*)ports->dma);
-       iounmap((void*)ports->ctl);
-       pci_release_selected_regions(dev, (1 << 2) - 1);
-       memset(ports, 0, sizeof(*ports));
-}
-
-static const struct pci_device_id scc_pci_tbl[] = {
-       { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
-
-static struct pci_driver scc_pci_driver = {
-       .name = "SCC IDE",
-       .id_table = scc_pci_tbl,
-       .probe = scc_init_one,
-       .remove = __devexit_p(scc_remove),
-};
-
-static int scc_ide_init(void)
-{
-       return ide_pci_register_driver(&scc_pci_driver);
-}
-
-module_init(scc_ide_init);
-/* -- No exit code?
-static void scc_ide_exit(void)
-{
-       ide_pci_unregister_driver(&scc_pci_driver);
-}
-module_exit(scc_ide_exit);
- */
-
-
-MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
deleted file mode 100644 (file)
index 437bc91..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 1998-2000 Michel Aubry
- * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
- * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
- * Portions copyright (c) 2001 Sun Microsystems
- *
- *
- * RCC/ServerWorks IDE driver for Linux
- *
- *   OSB4: `Open South Bridge' IDE Interface (fn 1)
- *         supports UDMA mode 2 (33 MB/s)
- *
- *   CSB5: `Champion South Bridge' IDE Interface (fn 1)
- *         all revisions support UDMA mode 4 (66 MB/s)
- *         revision A2.0 and up support UDMA mode 5 (100 MB/s)
- *
- *         *** The CSB5 does not provide ANY register ***
- *         *** to detect 80-conductor cable presence. ***
- *
- *   CSB6: `Champion South Bridge' IDE Interface (optional: third channel)
- *
- *   HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE
- *   controller same as the CSB6. Single channel ATA100 only.
- *
- * Documentation:
- *     Available under NDA only. Errata info very hard to get.
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "serverworks"
-
-#define SVWKS_CSB5_REVISION_NEW        0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
-#define SVWKS_CSB6_REVISION    0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
-
-/* Seagate Barracuda ATA IV Family drives in UDMA mode 5
- * can overrun their FIFOs when used with the CSB5 */
-static const char *svwks_bad_ata100[] = {
-       "ST320011A",
-       "ST340016A",
-       "ST360021A",
-       "ST380021A",
-       NULL
-};
-
-static struct pci_dev *isa_dev;
-
-static int check_in_drive_lists (ide_drive_t *drive, const char **list)
-{
-       char *m = (char *)&drive->id[ATA_ID_PROD];
-
-       while (*list)
-               if (!strcmp(*list++, m))
-                       return 1;
-       return 0;
-}
-
-static u8 svwks_udma_filter(ide_drive_t *drive)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u8 mask = 0;
-
-       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
-               return 0x1f;
-       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-               u32 reg = 0;
-               if (isa_dev)
-                       pci_read_config_dword(isa_dev, 0x64, &reg);
-                       
-               /*
-                *      Don't enable UDMA on disk devices for the moment
-                */
-               if(drive->media == ide_disk)
-                       return 0;
-               /* Check the OSB4 DMA33 enable bit */
-               return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
-       } else if (dev->revision < SVWKS_CSB5_REVISION_NEW) {
-               return 0x07;
-       } else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) {
-               u8 btr = 0, mode;
-               pci_read_config_byte(dev, 0x5A, &btr);
-               mode = btr & 0x3;
-
-               /* If someone decides to do UDMA133 on CSB5 the same
-                  issue will bite so be inclusive */
-               if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100))
-                       mode = 2;
-
-               switch(mode) {
-               case 3:  mask = 0x3f; break;
-               case 2:  mask = 0x1f; break;
-               case 1:  mask = 0x07; break;
-               default: mask = 0x00; break;
-               }
-       }
-       if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-            (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
-           (!(PCI_FUNC(dev->devfn) & 1)))
-               mask = 0x1f;
-
-       return mask;
-}
-
-static u8 svwks_csb_check (struct pci_dev *dev)
-{
-       switch (dev->device) {
-               case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
-               case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
-               case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
-               case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
-                       return 1;
-               default:
-                       break;
-       }
-       return 0;
-}
-
-static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
-       static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
-
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-
-       pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
-
-       if (svwks_csb_check(dev)) {
-               u16 csb_pio = 0;
-
-               pci_read_config_word(dev, 0x4a, &csb_pio);
-
-               csb_pio &= ~(0x0f << (4 * drive->dn));
-               csb_pio |= (pio << (4 * drive->dn));
-
-               pci_write_config_word(dev, 0x4a, csb_pio);
-       }
-}
-
-static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       static const u8 udma_modes[]            = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
-       static const u8 dma_modes[]             = { 0x77, 0x21, 0x20 };
-       static const u8 drive_pci2[]            = { 0x45, 0x44, 0x47, 0x46 };
-
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 unit                 = drive->dn & 1;
-
-       u8 ultra_enable  = 0, ultra_timing = 0, dma_timing = 0;
-
-       pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
-       pci_read_config_byte(dev, 0x54, &ultra_enable);
-
-       ultra_timing    &= ~(0x0F << (4*unit));
-       ultra_enable    &= ~(0x01 << drive->dn);
-
-       if (speed >= XFER_UDMA_0) {
-               dma_timing   |= dma_modes[2];
-               ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit));
-               ultra_enable |= (0x01 << drive->dn);
-       } else if (speed >= XFER_MW_DMA_0)
-               dma_timing   |= dma_modes[speed - XFER_MW_DMA_0];
-
-       pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
-       pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
-       pci_write_config_byte(dev, 0x54, ultra_enable);
-}
-
-static unsigned int init_chipset_svwks(struct pci_dev *dev)
-{
-       unsigned int reg;
-       u8 btr;
-
-       /* force Master Latency Timer value to 64 PCICLKs */
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
-
-       /* OSB4 : South Bridge and IDE */
-       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-               isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
-                         PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
-               if (isa_dev) {
-                       pci_read_config_dword(isa_dev, 0x64, &reg);
-                       reg &= ~0x00002000; /* disable 600ns interrupt mask */
-                       if(!(reg & 0x00004000))
-                               printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS "
-                                       "enabled.\n", pci_name(dev));
-                       reg |=  0x00004000; /* enable UDMA/33 support */
-                       pci_write_config_dword(isa_dev, 0x64, reg);
-               }
-       }
-
-       /* setup CSB5/CSB6 : South Bridge and IDE option RAID */
-       else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ||
-                (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-                (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
-
-               /* Third Channel Test */
-               if (!(PCI_FUNC(dev->devfn) & 1)) {
-                       struct pci_dev * findev = NULL;
-                       u32 reg4c = 0;
-                       findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
-                               PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
-                       if (findev) {
-                               pci_read_config_dword(findev, 0x4C, &reg4c);
-                               reg4c &= ~0x000007FF;
-                               reg4c |=  0x00000040;
-                               reg4c |=  0x00000020;
-                               pci_write_config_dword(findev, 0x4C, reg4c);
-                               pci_dev_put(findev);
-                       }
-                       outb_p(0x06, 0x0c00);
-                       dev->irq = inb_p(0x0c01);
-               } else {
-                       struct pci_dev * findev = NULL;
-                       u8 reg41 = 0;
-
-                       findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
-                                       PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL);
-                       if (findev) {
-                               pci_read_config_byte(findev, 0x41, &reg41);
-                               reg41 &= ~0x40;
-                               pci_write_config_byte(findev, 0x41, reg41);
-                               pci_dev_put(findev);
-                       }
-                       /*
-                        * This is a device pin issue on CSB6.
-                        * Since there will be a future raid mode,
-                        * early versions of the chipset require the
-                        * interrupt pin to be set, and it is a compatibility
-                        * mode issue.
-                        */
-                       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
-                               dev->irq = 0;
-               }
-//             pci_read_config_dword(dev, 0x40, &pioreg)
-//             pci_write_config_dword(dev, 0x40, 0x99999999);
-//             pci_read_config_dword(dev, 0x44, &dmareg);
-//             pci_write_config_dword(dev, 0x44, 0xFFFFFFFF);
-               /* setup the UDMA Control register
-                *
-                * 1. clear bit 6 to enable DMA
-                * 2. enable DMA modes with bits 0-1
-                *      00 : legacy
-                *      01 : udma2
-                *      10 : udma2/udma4
-                *      11 : udma2/udma4/udma5
-                */
-               pci_read_config_byte(dev, 0x5A, &btr);
-               btr &= ~0x40;
-               if (!(PCI_FUNC(dev->devfn) & 1))
-                       btr |= 0x2;
-               else
-                       btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
-               pci_write_config_byte(dev, 0x5A, btr);
-       }
-       /* Setup HT1000 SouthBridge Controller - Single Channel Only */
-       else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) {
-               pci_read_config_byte(dev, 0x5A, &btr);
-               btr &= ~0x40;
-               btr |= 0x3;
-               pci_write_config_byte(dev, 0x5A, btr);
-       }
-
-       return dev->irq;
-}
-
-static u8 ata66_svwks_svwks(ide_hwif_t *hwif)
-{
-       return ATA_CBL_PATA80;
-}
-
-/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
- * of the subsystem device ID indicate presence of an 80-pin cable.
- * Bit 15 clear = secondary IDE channel does not have 80-pin cable.
- * Bit 15 set   = secondary IDE channel has 80-pin cable.
- * Bit 14 clear = primary IDE channel does not have 80-pin cable.
- * Bit 14 set   = primary IDE channel has 80-pin cable.
- */
-static u8 ata66_svwks_dell(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
-           dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
-           (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
-            dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
-               return ((1 << (hwif->channel + 14)) &
-                       dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-       return ATA_CBL_PATA40;
-}
-
-/* Sun Cobalt Alpine hardware avoids the 80-pin cable
- * detect issue by attaching the drives directly to the board.
- * This check follows the Dell precedent (how scary is that?!)
- *
- * WARNING: this only works on Alpine hardware!
- */
-static u8 ata66_svwks_cobalt(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
-           dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
-           dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-               return ((1 << (hwif->channel + 14)) &
-                       dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-       return ATA_CBL_PATA40;
-}
-
-static u8 svwks_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       /* Server Works */
-       if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
-               return ata66_svwks_svwks (hwif);
-       
-       /* Dell PowerEdge */
-       if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL)
-               return ata66_svwks_dell (hwif);
-
-       /* Cobalt Alpine */
-       if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN)
-               return ata66_svwks_cobalt (hwif);
-
-       /* Per Specified Design by OEM, and ASIC Architect */
-       if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-           (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
-               return ATA_CBL_PATA80;
-
-       return ATA_CBL_PATA40;
-}
-
-static const struct ide_port_ops osb4_port_ops = {
-       .set_pio_mode           = svwks_set_pio_mode,
-       .set_dma_mode           = svwks_set_dma_mode,
-       .udma_filter            = svwks_udma_filter,
-};
-
-static const struct ide_port_ops svwks_port_ops = {
-       .set_pio_mode           = svwks_set_pio_mode,
-       .set_dma_mode           = svwks_set_dma_mode,
-       .udma_filter            = svwks_udma_filter,
-       .cable_detect           = svwks_cable_detect,
-};
-
-#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
-
-static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
-       {       /* 0: OSB4 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_svwks,
-               .port_ops       = &osb4_port_ops,
-               .host_flags     = IDE_HFLAGS_SVWKS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = 0x00, /* UDMA is problematic on OSB4 */
-       },
-       {       /* 1: CSB5 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_svwks,
-               .port_ops       = &svwks_port_ops,
-               .host_flags     = IDE_HFLAGS_SVWKS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       },
-       {       /* 2: CSB6 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_svwks,
-               .port_ops       = &svwks_port_ops,
-               .host_flags     = IDE_HFLAGS_SVWKS,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       },
-       {       /* 3: CSB6-2 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_svwks,
-               .port_ops       = &svwks_port_ops,
-               .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       },
-       {       /* 4: HT1000 */
-               .name           = DRV_NAME,
-               .init_chipset   = init_chipset_svwks,
-               .port_ops       = &svwks_port_ops,
-               .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
-               .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
-               .udma_mask      = ATA_UDMA5,
-       }
-};
-
-/**
- *     svwks_init_one  -       called when a OSB/CSB is found
- *     @dev: the svwks device
- *     @id: the matching pci id
- *
- *     Called when the PCI registration layer (or the IDE initialization)
- *     finds a device matching our IDE device tables.
- */
-static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d;
-       u8 idx = id->driver_data;
-
-       d = serverworks_chipsets[idx];
-
-       if (idx == 1)
-               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-       else if (idx == 2 || idx == 3) {
-               if ((PCI_FUNC(dev->devfn) & 1) == 0) {
-                       if (pci_resource_start(dev, 0) != 0x01f1)
-                               d.host_flags |= IDE_HFLAG_NON_BOOTABLE;
-                       d.host_flags |= IDE_HFLAG_SINGLE;
-               } else
-                       d.host_flags &= ~IDE_HFLAG_SINGLE;
-       }
-
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-static const struct pci_device_id svwks_pci_tbl[] = {
-       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE),   0 },
-       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE),   1 },
-       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE),   2 },
-       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2),  3 },
-       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
-
-static struct pci_driver svwks_pci_driver = {
-       .name           = "Serverworks_IDE",
-       .id_table       = svwks_pci_tbl,
-       .probe          = svwks_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init svwks_ide_init(void)
-{
-       return ide_pci_register_driver(&svwks_pci_driver);
-}
-
-static void __exit svwks_ide_exit(void)
-{
-       pci_unregister_driver(&svwks_pci_driver);
-}
-
-module_init(svwks_ide_init);
-module_exit(svwks_ide_exit);
-
-MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
deleted file mode 100644 (file)
index 8af9b23..0000000
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * Copyright (c) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
- * Copyright (C) 2008 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/scatterlist.h>
-#include <linux/ioc4.h>
-#include <asm/io.h>
-
-#include <linux/ide.h>
-
-#define DRV_NAME "SGIIOC4"
-
-/* IOC4 Specific Definitions */
-#define IOC4_CMD_OFFSET                0x100
-#define IOC4_CTRL_OFFSET       0x120
-#define IOC4_DMA_OFFSET                0x140
-#define IOC4_INTR_OFFSET       0x0
-
-#define IOC4_TIMING            0x00
-#define IOC4_DMA_PTR_L         0x01
-#define IOC4_DMA_PTR_H         0x02
-#define IOC4_DMA_ADDR_L                0x03
-#define IOC4_DMA_ADDR_H                0x04
-#define IOC4_BC_DEV            0x05
-#define IOC4_BC_MEM            0x06
-#define        IOC4_DMA_CTRL           0x07
-#define        IOC4_DMA_END_ADDR       0x08
-
-/* Bits in the IOC4 Control/Status Register */
-#define        IOC4_S_DMA_START        0x01
-#define        IOC4_S_DMA_STOP         0x02
-#define        IOC4_S_DMA_DIR          0x04
-#define        IOC4_S_DMA_ACTIVE       0x08
-#define        IOC4_S_DMA_ERROR        0x10
-#define        IOC4_ATA_MEMERR         0x02
-
-/* Read/Write Directions */
-#define        IOC4_DMA_WRITE          0x04
-#define        IOC4_DMA_READ           0x00
-
-/* Interrupt Register Offsets */
-#define IOC4_INTR_REG          0x03
-#define        IOC4_INTR_SET           0x05
-#define        IOC4_INTR_CLEAR         0x07
-
-#define IOC4_IDE_CACHELINE_SIZE        128
-#define IOC4_CMD_CTL_BLK_SIZE  0x20
-#define IOC4_SUPPORTED_FIRMWARE_REV 46
-
-typedef struct {
-       u32 timing_reg0;
-       u32 timing_reg1;
-       u32 low_mem_ptr;
-       u32 high_mem_ptr;
-       u32 low_mem_addr;
-       u32 high_mem_addr;
-       u32 dev_byte_count;
-       u32 mem_byte_count;
-       u32 status;
-} ioc4_dma_regs_t;
-
-/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */
-/* IOC4 has only 1 IDE channel */
-#define IOC4_PRD_BYTES       16
-#define IOC4_PRD_ENTRIES     (PAGE_SIZE /(4*IOC4_PRD_BYTES))
-
-
-static void
-sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
-                       unsigned long ctrl_port, unsigned long irq_port)
-{
-       unsigned long reg = data_port;
-       int i;
-
-       /* Registers are word (32 bit) aligned */
-       for (i = 0; i <= 7; i++)
-               hw->io_ports_array[i] = reg + i * 4;
-
-       hw->io_ports.ctl_addr = ctrl_port;
-       hw->io_ports.irq_addr = irq_port;
-}
-
-static int
-sgiioc4_checkirq(ide_hwif_t * hwif)
-{
-       unsigned long intr_addr =
-               hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
-
-       if ((u8)readl((void __iomem *)intr_addr) & 0x03)
-               return 1;
-
-       return 0;
-}
-
-static u8 sgiioc4_read_status(ide_hwif_t *);
-
-static int
-sgiioc4_clearirq(ide_drive_t * drive)
-{
-       u32 intr_reg;
-       ide_hwif_t *hwif = HWIF(drive);
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-       unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2);
-
-       /* Code to check for PCI error conditions */
-       intr_reg = readl((void __iomem *)other_ir);
-       if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
-               /*
-                * Using sgiioc4_read_status to read the Status register has a
-                * side effect of clearing the interrupt.  The first read should
-                * clear it if it is set.  The second read should return
-                * a "clear" status if it got cleared.  If not, then spin
-                * for a bit trying to clear it.
-                */
-               u8 stat = sgiioc4_read_status(hwif);
-               int count = 0;
-
-               stat = sgiioc4_read_status(hwif);
-               while ((stat & ATA_BUSY) && (count++ < 100)) {
-                       udelay(1);
-                       stat = sgiioc4_read_status(hwif);
-               }
-
-               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;
-
-                       pci_err_addr_low =
-                               readl((void __iomem *)io_ports->irq_addr);
-                       pci_err_addr_high =
-                               readl((void __iomem *)(io_ports->irq_addr + 4));
-                       pci_read_config_dword(dev, PCI_COMMAND,
-                                             &pci_stat_cmd_reg);
-                       printk(KERN_ERR
-                              "%s(%s) : PCI Bus Error when doing DMA:"
-                                  " status-cmd reg is 0x%x\n",
-                              __func__, drive->name, pci_stat_cmd_reg);
-                       printk(KERN_ERR
-                              "%s(%s) : PCI Error Address is 0x%x%x\n",
-                              __func__, drive->name,
-                              pci_err_addr_high, pci_err_addr_low);
-                       /* Clear the PCI Error indicator */
-                       pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
-               }
-
-               /* Clear the Interrupt, Error bits on the IOC4 */
-               writel(0x03, (void __iomem *)other_ir);
-
-               intr_reg = readl((void __iomem *)other_ir);
-       }
-
-       return intr_reg & 3;
-}
-
-static void sgiioc4_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
-       unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
-       unsigned int temp_reg = reg | IOC4_S_DMA_START;
-
-       writel(temp_reg, (void __iomem *)ioc4_dma_addr);
-}
-
-static u32
-sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
-{
-       unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
-       u32     ioc4_dma;
-       int     count;
-
-       count = 0;
-       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
-       while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
-               udelay(1);
-               ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
-       }
-       return ioc4_dma;
-}
-
-/* Stops the IOC4 DMA Engine */
-static int sgiioc4_dma_end(ide_drive_t *drive)
-{
-       u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned long dma_base = hwif->dma_base;
-       int dma_stat = 0;
-       unsigned long *ending_dma = ide_get_hwifdata(hwif);
-
-       writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4));
-
-       ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-
-       if (ioc4_dma & IOC4_S_DMA_STOP) {
-               printk(KERN_ERR
-                      "%s(%s): IOC4 DMA STOP bit is still 1 :"
-                      "ioc4_dma_reg 0x%x\n",
-                      __func__, drive->name, ioc4_dma);
-               dma_stat = 1;
-       }
-
-       /*
-        * The IOC4 will DMA 1's to the ending dma area to indicate that
-        * previous data DMA is complete.  This is necessary because of relaxed
-        * ordering between register reads and DMA writes on the Altix.
-        */
-       while ((cnt++ < 200) && (!valid)) {
-               for (num = 0; num < 16; num++) {
-                       if (ending_dma[num]) {
-                               valid = 1;
-                               break;
-                       }
-               }
-               udelay(1);
-       }
-       if (!valid) {
-               printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__,
-                      drive->name);
-               dma_stat = 1;
-       }
-
-       bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4));
-       bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4));
-
-       if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
-               if (bc_dev > bc_mem + 8) {
-                       printk(KERN_ERR
-                              "%s(%s): WARNING!! byte_count_dev %d "
-                              "!= byte_count_mem %d\n",
-                              __func__, drive->name, bc_dev, bc_mem);
-               }
-       }
-
-       drive->waiting_for_dma = 0;
-       ide_destroy_dmatable(drive);
-
-       return dma_stat;
-}
-
-static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-}
-
-/* returns 1 if dma irq issued, 0 otherwise */
-static int sgiioc4_dma_test_irq(ide_drive_t *drive)
-{
-       return sgiioc4_checkirq(HWIF(drive));
-}
-
-static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
-{
-       if (!on)
-               sgiioc4_clearirq(drive);
-}
-
-static void
-sgiioc4_resetproc(ide_drive_t * drive)
-{
-       sgiioc4_dma_end(drive);
-       sgiioc4_clearirq(drive);
-}
-
-static void
-sgiioc4_dma_lost_irq(ide_drive_t * drive)
-{
-       sgiioc4_resetproc(drive);
-
-       ide_dma_lost_irq(drive);
-}
-
-static u8 sgiioc4_read_status(ide_hwif_t *hwif)
-{
-       unsigned long port = hwif->io_ports.status_addr;
-       u8 reg = (u8) readb((void __iomem *) port);
-
-       if (!(reg & ATA_BUSY)) {        /* Not busy... check for interrupt */
-               unsigned long other_ir = port - 0x110;
-               unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
-
-               /* Clear the Interrupt, Error bits on the IOC4 */
-               if (intr_reg & 0x03) {
-                       writel(0x03, (void __iomem *) other_ir);
-                       intr_reg = (u32) readl((void __iomem *) other_ir);
-               }
-       }
-
-       return reg;
-}
-
-/* Creates a dma map for the scatter-gather list entries */
-static int __devinit
-ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
-       int num_ports = sizeof (ioc4_dma_regs_t);
-       void *pad;
-
-       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
-
-       if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
-               printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
-                      "already in use\n", __func__, hwif->name,
-                      dma_base, dma_base + num_ports - 1);
-               return -1;
-       }
-
-       hwif->dma_base = (unsigned long)hwif->io_ports.irq_addr +
-                        IOC4_DMA_OFFSET;
-
-       hwif->sg_max_nents = IOC4_PRD_ENTRIES;
-
-       hwif->prd_max_nents = IOC4_PRD_ENTRIES;
-       hwif->prd_ent_size = IOC4_PRD_BYTES;
-
-       if (ide_allocate_dma_engine(hwif))
-               goto dma_pci_alloc_failure;
-
-       pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
-                                  (dma_addr_t *)&hwif->extra_base);
-       if (pad) {
-               ide_set_hwifdata(hwif, pad);
-               return 0;
-       }
-
-       ide_release_dma_engine(hwif);
-
-       printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
-              __func__, hwif->name);
-       printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
-
-dma_pci_alloc_failure:
-       release_mem_region(dma_base, num_ports);
-
-       return -1;
-}
-
-/* Initializes the IOC4 DMA Engine */
-static void
-sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
-{
-       u32 ioc4_dma;
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned long dma_base = hwif->dma_base;
-       unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
-       u32 dma_addr, ending_dma_addr;
-
-       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
-
-       if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
-               printk(KERN_WARNING
-                       "%s(%s):Warning!! DMA from previous transfer was still active\n",
-                      __func__, drive->name);
-               writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
-               ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-
-               if (ioc4_dma & IOC4_S_DMA_STOP)
-                       printk(KERN_ERR
-                              "%s(%s) : IOC4 Dma STOP bit is still 1\n",
-                              __func__, drive->name);
-       }
-
-       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
-       if (ioc4_dma & IOC4_S_DMA_ERROR) {
-               printk(KERN_WARNING
-                      "%s(%s) : Warning!! - DMA Error during Previous"
-                      " transfer | status 0x%x\n",
-                      __func__, drive->name, ioc4_dma);
-               writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
-               ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
-
-               if (ioc4_dma & IOC4_S_DMA_STOP)
-                       printk(KERN_ERR
-                              "%s(%s) : IOC4 DMA STOP bit is still 1\n",
-                              __func__, drive->name);
-       }
-
-       /* Address of the Scatter Gather List */
-       dma_addr = cpu_to_le32(hwif->dmatable_dma);
-       writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4));
-
-       /* Address of the Ending DMA */
-       memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
-       ending_dma_addr = cpu_to_le32(hwif->extra_base);
-       writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
-
-       writel(dma_direction, (void __iomem *)ioc4_dma_addr);
-       drive->waiting_for_dma = 1;
-}
-
-/* IOC4 Scatter Gather list Format                                      */
-/* 128 Bit entries to support 64 bit addresses in the future            */
-/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format     */
-/* --------------------------------------------------------------------- */
-/* | Upper 32 bits - Zero           |          Lower 32 bits- address | */
-/* --------------------------------------------------------------------- */
-/* | Upper 32 bits - Zero          |EOL| 15 unused     | 16 Bit Length| */
-/* --------------------------------------------------------------------- */
-/* Creates the scatter gather list, DMA Table */
-static unsigned int
-sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       unsigned int *table = hwif->dmatable_cpu;
-       unsigned int count = 0, i = 1;
-       struct scatterlist *sg;
-
-       hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-       if (!i)
-               return 0;       /* sglist of length Zero */
-
-       sg = hwif->sg_table;
-       while (i && sg_dma_len(sg)) {
-               dma_addr_t cur_addr;
-               int cur_len;
-               cur_addr = sg_dma_address(sg);
-               cur_len = sg_dma_len(sg);
-
-               while (cur_len) {
-                       if (count++ >= IOC4_PRD_ENTRIES) {
-                               printk(KERN_WARNING
-                                      "%s: DMA table too small\n",
-                                      drive->name);
-                               goto use_pio_instead;
-                       } else {
-                               u32 bcount =
-                                   0x10000 - (cur_addr & 0xffff);
-
-                               if (bcount > cur_len)
-                                       bcount = cur_len;
-
-                               /* put the addr, length in
-                                * the IOC4 dma-table format */
-                               *table = 0x0;
-                               table++;
-                               *table = cpu_to_be32(cur_addr);
-                               table++;
-                               *table = 0x0;
-                               table++;
-
-                               *table = cpu_to_be32(bcount);
-                               table++;
-
-                               cur_addr += bcount;
-                               cur_len -= bcount;
-                       }
-               }
-
-               sg = sg_next(sg);
-               i--;
-       }
-
-       if (count) {
-               table--;
-               *table |= cpu_to_be32(0x80000000);
-               return count;
-       }
-
-use_pio_instead:
-       ide_destroy_dmatable(drive);
-
-       return 0;               /* revert to PIO for this request */
-}
-
-static int sgiioc4_dma_setup(ide_drive_t *drive)
-{
-       struct request *rq = HWGROUP(drive)->rq;
-       unsigned int count = 0;
-       int ddir;
-
-       if (rq_data_dir(rq))
-               ddir = PCI_DMA_TODEVICE;
-       else
-               ddir = PCI_DMA_FROMDEVICE;
-
-       if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) {
-               /* try PIO instead of DMA */
-               ide_map_sg(drive, rq);
-               return 1;
-       }
-
-       if (rq_data_dir(rq))
-               /* Writes TO the IOC4 FROM Main Memory */
-               ddir = IOC4_DMA_READ;
-       else
-               /* Writes FROM the IOC4 TO Main Memory */
-               ddir = IOC4_DMA_WRITE;
-
-       sgiioc4_configure_for_dma(ddir, drive);
-
-       return 0;
-}
-
-static const struct ide_tp_ops sgiioc4_tp_ops = {
-       .exec_command           = ide_exec_command,
-       .read_status            = sgiioc4_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
-
-       .set_irq                = ide_set_irq,
-
-       .tf_load                = ide_tf_load,
-       .tf_read                = ide_tf_read,
-
-       .input_data             = ide_input_data,
-       .output_data            = ide_output_data,
-};
-
-static const struct ide_port_ops sgiioc4_port_ops = {
-       .set_dma_mode           = sgiioc4_set_dma_mode,
-       /* reset DMA engine, clear IRQs */
-       .resetproc              = sgiioc4_resetproc,
-};
-
-static const struct ide_dma_ops sgiioc4_dma_ops = {
-       .dma_host_set           = sgiioc4_dma_host_set,
-       .dma_setup              = sgiioc4_dma_setup,
-       .dma_start              = sgiioc4_dma_start,
-       .dma_end                = sgiioc4_dma_end,
-       .dma_test_irq           = sgiioc4_dma_test_irq,
-       .dma_lost_irq           = sgiioc4_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info sgiioc4_port_info __devinitdata = {
-       .name                   = DRV_NAME,
-       .chipset                = ide_pci,
-       .init_dma               = ide_dma_sgiioc4,
-       .tp_ops                 = &sgiioc4_tp_ops,
-       .port_ops               = &sgiioc4_port_ops,
-       .dma_ops                = &sgiioc4_dma_ops,
-       .host_flags             = IDE_HFLAG_MMIO,
-       .mwdma_mask             = ATA_MWDMA2_ONLY,
-};
-
-static int __devinit
-sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
-{
-       unsigned long cmd_base, irqport;
-       unsigned long bar0, cmd_phys_base, ctl;
-       void __iomem *virt_base;
-       struct ide_host *host;
-       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
-       struct ide_port_info d = sgiioc4_port_info;
-       int rc;
-
-       /*  Get the CmdBlk and CtrlBlk Base Registers */
-       bar0 = pci_resource_start(dev, 0);
-       virt_base = ioremap(bar0, pci_resource_len(dev, 0));
-       if (virt_base == NULL) {
-               printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
-                               DRV_NAME, bar0);
-               return -ENOMEM;
-       }
-       cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
-       ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
-       irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
-
-       cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
-       if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
-                              DRV_NAME) == NULL) {
-               printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
-                      "already in use\n", DRV_NAME, pci_name(dev),
-                      cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
-               return -EBUSY;
-       }
-
-       /* 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;
-
-       /* Initializing chipset IRQ Registers */
-       writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
-
-       host = ide_host_alloc(&d, hws);
-       if (host == NULL) {
-               rc = -ENOMEM;
-               goto err;
-       }
-
-       rc = ide_host_register(host, &d, hws);
-       if (rc)
-               goto err_free;
-
-       return 0;
-err_free:
-       ide_host_free(host);
-err:
-       release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
-       iounmap(virt_base);
-       return rc;
-}
-
-static unsigned int __devinit
-pci_init_sgiioc4(struct pci_dev *dev)
-{
-       int ret;
-
-       printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
-                        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",
-                               DRV_NAME, pci_name(dev));
-               ret = -EAGAIN;
-               goto out;
-       }
-       ret = sgiioc4_ide_setup_pci_device(dev);
-out:
-       return ret;
-}
-
-int
-ioc4_ide_attach_one(struct ioc4_driver_data *idd)
-{
-       /* PCI-RT does not bring out IDE connection.
-        * Do not attach to this particular IOC4.
-        */
-       if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
-               return 0;
-
-       return pci_init_sgiioc4(idd->idd_pdev);
-}
-
-static struct ioc4_submodule ioc4_ide_submodule = {
-       .is_name = "IOC4_ide",
-       .is_owner = THIS_MODULE,
-       .is_probe = ioc4_ide_attach_one,
-/*     .is_remove = ioc4_ide_remove_one,       */
-};
-
-static int __init ioc4_ide_init(void)
-{
-       return ioc4_register_submodule(&ioc4_ide_submodule);
-}
-
-late_initcall(ioc4_ide_init); /* Call only after IDE init is done */
-
-MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
-MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
deleted file mode 100644 (file)
index eb4faf9..0000000
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003          Red Hat <alan@redhat.com>
- * Copyright (C) 2007-2008     MontaVista Software, Inc.
- * Copyright (C) 2007-2008     Bartlomiej Zolnierkiewicz
- *
- *  May be copied or modified under the terms of the GNU General Public License
- *
- *  Documentation for CMD680:
- *  http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2
- *
- *  Documentation for SiI 3112:
- *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
- *
- *  Errata and other documentation only available under NDA.
- *
- *
- *  FAQ Items:
- *     If you are using Marvell SATA-IDE adapters with Maxtor drives
- *     ensure the system is set up for ATA100/UDMA5, not UDMA6.
- *
- *     If you are using WD drives with SATA bridges you must set the
- *     drive to "Single". "Master" will hang.
- *
- *     If you have strange problems with nVidia chipset systems please
- *     see the SI support documentation and update your system BIOS
- *     if necessary
- *
- *  The Dell DRAC4 has some interesting features including effectively hot
- *  unplugging/replugging the virtual CD interface when the DRAC is reset.
- *  This often causes drivers/ide/siimage to panic but is ok with the rather
- *  smarter code in libata.
- *
- * TODO:
- * - IORDY fixes
- * - VDMA support
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#define DRV_NAME "siimage"
-
-/**
- *     pdev_is_sata            -       check if device is SATA
- *     @pdev:  PCI device to check
- *
- *     Returns true if this is a SATA controller
- */
-
-static int pdev_is_sata(struct pci_dev *pdev)
-{
-#ifdef CONFIG_BLK_DEV_IDE_SATA
-       switch (pdev->device) {
-       case PCI_DEVICE_ID_SII_3112:
-       case PCI_DEVICE_ID_SII_1210SA:
-               return 1;
-       case PCI_DEVICE_ID_SII_680:
-               return 0;
-       }
-       BUG();
-#endif
-       return 0;
-}
-
-/**
- *     is_sata                 -       check if hwif is SATA
- *     @hwif:  interface to check
- *
- *     Returns true if this is a SATA controller
- */
-
-static inline int is_sata(ide_hwif_t *hwif)
-{
-       return pdev_is_sata(to_pci_dev(hwif->dev));
-}
-
-/**
- *     siimage_selreg          -       return register base
- *     @hwif: interface
- *     @r: config offset
- *
- *     Turn a config register offset into the right address in either
- *     PCI space or MMIO space to access the control register in question
- *     Thankfully this is a configuration operation, so isn't performance
- *     critical.
- */
-
-static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
-{
-       unsigned long base = (unsigned long)hwif->hwif_data;
-
-       base += 0xA0 + r;
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               base += hwif->channel << 6;
-       else
-               base += hwif->channel << 4;
-       return base;
-}
-
-/**
- *     siimage_seldev          -       return register base
- *     @hwif: interface
- *     @r: config offset
- *
- *     Turn a config register offset into the right address in either
- *     PCI space or MMIO space to access the control register in question
- *     including accounting for the unit shift.
- */
-
-static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long base      = (unsigned long)hwif->hwif_data;
-       u8 unit                 = drive->dn & 1;
-
-       base += 0xA0 + r;
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               base += hwif->channel << 6;
-       else
-               base += hwif->channel << 4;
-       base |= unit << unit;
-       return base;
-}
-
-static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       u8 tmp = 0;
-
-       if (host->host_priv)
-               tmp = readb((void __iomem *)addr);
-       else
-               pci_read_config_byte(dev, addr, &tmp);
-
-       return tmp;
-}
-
-static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       u16 tmp = 0;
-
-       if (host->host_priv)
-               tmp = readw((void __iomem *)addr);
-       else
-               pci_read_config_word(dev, addr, &tmp);
-
-       return tmp;
-}
-
-static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-
-       if (host->host_priv)
-               writeb(val, (void __iomem *)addr);
-       else
-               pci_write_config_byte(dev, addr, val);
-}
-
-static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-
-       if (host->host_priv)
-               writew(val, (void __iomem *)addr);
-       else
-               pci_write_config_word(dev, addr, val);
-}
-
-static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-
-       if (host->host_priv)
-               writel(val, (void __iomem *)addr);
-       else
-               pci_write_config_dword(dev, addr, val);
-}
-
-/**
- *     sil_udma_filter         -       compute UDMA mask
- *     @drive: IDE device
- *
- *     Compute the available UDMA speeds for the device on the interface.
- *
- *     For the CMD680 this depends on the clocking mode (scsc), for the
- *     SI3112 SATA controller life is a bit simpler.
- */
-
-static u8 sil_pata_udma_filter(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = drive->hwif;
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       unsigned long base      = (unsigned long)hwif->hwif_data;
-       u8 scsc, mask           = 0;
-
-       base += (hwif->host_flags & IDE_HFLAG_MMIO) ? 0x4A : 0x8A;
-
-       scsc = sil_ioread8(dev, base);
-
-       switch (scsc & 0x30) {
-       case 0x10:      /* 133 */
-               mask = ATA_UDMA6;
-               break;
-       case 0x20:      /* 2xPCI */
-               mask = ATA_UDMA6;
-               break;
-       case 0x00:      /* 100 */
-               mask = ATA_UDMA5;
-               break;
-       default:        /* Disabled ? */
-               BUG();
-       }
-
-       return mask;
-}
-
-static u8 sil_sata_udma_filter(ide_drive_t *drive)
-{
-       char *m = (char *)&drive->id[ATA_ID_PROD];
-
-       return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
-}
-
-/**
- *     sil_set_pio_mode        -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     Load the timing settings for this device mode into the
- *     controller. If we are in PIO mode 3 or 4 turn on IORDY
- *     monitoring (bit 9). The TF timing is bits 31:16
- */
-
-static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
-{
-       static const u16 tf_speed[]   = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
-       static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
-
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       ide_drive_t *pair       = ide_get_pair_dev(drive);
-       u32 speedt              = 0;
-       u16 speedp              = 0;
-       unsigned long addr      = siimage_seldev(drive, 0x04);
-       unsigned long tfaddr    = siimage_selreg(hwif,  0x02);
-       unsigned long base      = (unsigned long)hwif->hwif_data;
-       u8 tf_pio               = pio;
-       u8 mmio                 = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 addr_mask            = hwif->channel ? (mmio ? 0xF4 : 0x84)
-                                               : (mmio ? 0xB4 : 0x80);
-       u8 mode                 = 0;
-       u8 unit                 = drive->dn & 1;
-
-       /* trim *taskfile* PIO to the slowest of the master/slave */
-       if (pair) {
-               u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
-
-               if (pair_pio < tf_pio)
-                       tf_pio = pair_pio;
-       }
-
-       /* cheat for now and use the docs */
-       speedp = data_speed[pio];
-       speedt = tf_speed[tf_pio];
-
-       sil_iowrite16(dev, speedp, addr);
-       sil_iowrite16(dev, speedt, tfaddr);
-
-       /* now set up IORDY */
-       speedp = sil_ioread16(dev, tfaddr - 2);
-       speedp &= ~0x200;
-       if (pio > 2)
-               speedp |= 0x200;
-       sil_iowrite16(dev, speedp, tfaddr - 2);
-
-       mode = sil_ioread8(dev, base + addr_mask);
-       mode &= ~(unit ? 0x30 : 0x03);
-       mode |= unit ? 0x10 : 0x01;
-       sil_iowrite8(dev, mode, base + addr_mask);
-}
-
-/**
- *     sil_set_dma_mode        -       set host controller for DMA mode
- *     @drive: drive
- *     @speed: DMA mode
- *
- *     Tune the SiI chipset for the desired DMA mode.
- */
-
-static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
-       static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
-       static const u16 dma[]   = { 0x2208, 0x10C2, 0x10C1 };
-
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       unsigned long base      = (unsigned long)hwif->hwif_data;
-       u16 ultra = 0, multi    = 0;
-       u8 mode = 0, unit       = drive->dn & 1;
-       u8 mmio                 = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 scsc = 0, addr_mask  = hwif->channel ? (mmio ? 0xF4 : 0x84)
-                                               : (mmio ? 0xB4 : 0x80);
-       unsigned long ma        = siimage_seldev(drive, 0x08);
-       unsigned long ua        = siimage_seldev(drive, 0x0C);
-
-       scsc  = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A));
-       mode  = sil_ioread8 (dev, base + addr_mask);
-       multi = sil_ioread16(dev, ma);
-       ultra = sil_ioread16(dev, ua);
-
-       mode  &= ~(unit ? 0x30 : 0x03);
-       ultra &= ~0x3F;
-       scsc = ((scsc & 0x30) == 0x00) ? 0 : 1;
-
-       scsc = is_sata(hwif) ? 1 : scsc;
-
-       if (speed >= XFER_UDMA_0) {
-               multi  = dma[2];
-               ultra |= scsc ? ultra6[speed - XFER_UDMA_0] :
-                               ultra5[speed - XFER_UDMA_0];
-               mode  |= unit ? 0x30 : 0x03;
-       } else {
-               multi = dma[speed - XFER_MW_DMA_0];
-               mode |= unit ? 0x20 : 0x02;
-       }
-
-       sil_iowrite8 (dev, mode, base + addr_mask);
-       sil_iowrite16(dev, multi, ma);
-       sil_iowrite16(dev, ultra, ua);
-}
-
-/* returns 1 if dma irq issued, 0 otherwise */
-static int siimage_io_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 dma_altstat          = 0;
-       unsigned long addr      = siimage_selreg(hwif, 1);
-
-       /* return 1 if INTR asserted */
-       if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
-               return 1;
-
-       /* return 1 if Device INTR asserted */
-       pci_read_config_byte(dev, addr, &dma_altstat);
-       if (dma_altstat & 8)
-               return 0;       /* return 1; */
-
-       return 0;
-}
-
-/**
- *     siimage_mmio_dma_test_irq       -       check we caused an IRQ
- *     @drive: drive we are testing
- *
- *     Check if we caused an IDE DMA interrupt. We may also have caused
- *     SATA status interrupts, if so we clean them up and continue.
- */
-
-static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long addr      = siimage_selreg(hwif, 0x1);
-       void __iomem *sata_error_addr
-               = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
-
-       if (sata_error_addr) {
-               unsigned long base      = (unsigned long)hwif->hwif_data;
-               u32 ext_stat            = readl((void __iomem *)(base + 0x10));
-               u8 watchdog             = 0;
-
-               if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
-                       u32 sata_error = readl(sata_error_addr);
-
-                       writel(sata_error, sata_error_addr);
-                       watchdog = (sata_error & 0x00680000) ? 1 : 0;
-                       printk(KERN_WARNING "%s: sata_error = 0x%08x, "
-                               "watchdog = %d, %s\n",
-                               drive->name, sata_error, watchdog, __func__);
-               } else
-                       watchdog = (ext_stat & 0x8000) ? 1 : 0;
-
-               ext_stat >>= 16;
-               if (!(ext_stat & 0x0404) && !watchdog)
-                       return 0;
-       }
-
-       /* return 1 if INTR asserted */
-       if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
-               return 1;
-
-       /* return 1 if Device INTR asserted */
-       if (readb((void __iomem *)addr) & 8)
-               return 0;       /* return 1; */
-
-       return 0;
-}
-
-static int siimage_dma_test_irq(ide_drive_t *drive)
-{
-       if (drive->hwif->host_flags & IDE_HFLAG_MMIO)
-               return siimage_mmio_dma_test_irq(drive);
-       else
-               return siimage_io_dma_test_irq(drive);
-}
-
-/**
- *     sil_sata_reset_poll     -       wait for SATA reset
- *     @drive: drive we are resetting
- *
- *     Poll the SATA phy and see whether it has come back from the dead
- *     yet.
- */
-
-static int sil_sata_reset_poll(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       void __iomem *sata_status_addr
-               = (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET];
-
-       if (sata_status_addr) {
-               /* SATA Status is available only when in MMIO mode */
-               u32 sata_stat = readl(sata_status_addr);
-
-               if ((sata_stat & 0x03) != 0x03) {
-                       printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
-                                           hwif->name, sata_stat);
-                       return -ENXIO;
-               }
-       }
-
-       return 0;
-}
-
-/**
- *     sil_sata_pre_reset      -       reset hook
- *     @drive: IDE device being reset
- *
- *     For the SATA devices we need to handle recalibration/geometry
- *     differently
- */
-
-static void sil_sata_pre_reset(ide_drive_t *drive)
-{
-       if (drive->media == ide_disk) {
-               drive->special.b.set_geometry = 0;
-               drive->special.b.recalibrate = 0;
-       }
-}
-
-/**
- *     init_chipset_siimage    -       set up an SI device
- *     @dev: PCI device
- *
- *     Perform the initial PCI set up for this device. Attempt to switch
- *     to 133 MHz clocking if the system isn't already set up to do it.
- */
-
-static unsigned int init_chipset_siimage(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       void __iomem *ioaddr = host->host_priv;
-       unsigned long base, scsc_addr;
-       u8 rev = dev->revision, tmp;
-
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
-
-       if (ioaddr)
-               pci_set_master(dev);
-
-       base = (unsigned long)ioaddr;
-
-       if (ioaddr && pdev_is_sata(dev)) {
-               u32 tmp32, irq_mask;
-
-               /* make sure IDE0/1 interrupts are not masked */
-               irq_mask = (1 << 22) | (1 << 23);
-               tmp32 = readl(ioaddr + 0x48);
-               if (tmp32 & irq_mask) {
-                       tmp32 &= ~irq_mask;
-                       writel(tmp32, ioaddr + 0x48);
-                       readl(ioaddr + 0x48); /* flush */
-               }
-               writel(0, ioaddr + 0x148);
-               writel(0, ioaddr + 0x1C8);
-       }
-
-       sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80);
-       sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84);
-
-       scsc_addr = base ? (base + 0x4A) : 0x8A;
-       tmp = sil_ioread8(dev, scsc_addr);
-
-       switch (tmp & 0x30) {
-       case 0x00:
-               /* On 100 MHz clocking, try and switch to 133 MHz */
-               sil_iowrite8(dev, tmp | 0x10, scsc_addr);
-               break;
-       case 0x30:
-               /* Clocking is disabled, attempt to force 133MHz clocking. */
-               sil_iowrite8(dev, tmp & ~0x20, scsc_addr);
-       case 0x10:
-               /* On 133Mhz clocking. */
-               break;
-       case 0x20:
-               /* On PCIx2 clocking. */
-               break;
-       }
-
-       tmp = sil_ioread8(dev, scsc_addr);
-
-       sil_iowrite8 (dev,       0x72, base + 0xA1);
-       sil_iowrite16(dev,     0x328A, base + 0xA2);
-       sil_iowrite32(dev, 0x62DD62DD, base + 0xA4);
-       sil_iowrite32(dev, 0x43924392, base + 0xA8);
-       sil_iowrite32(dev, 0x40094009, base + 0xAC);
-       sil_iowrite8 (dev,       0x72, base ? (base + 0xE1) : 0xB1);
-       sil_iowrite16(dev,     0x328A, base ? (base + 0xE2) : 0xB2);
-       sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4);
-       sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8);
-       sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC);
-
-       if (base && pdev_is_sata(dev)) {
-               writel(0xFFFF0000, ioaddr + 0x108);
-               writel(0xFFFF0000, ioaddr + 0x188);
-               writel(0x00680000, ioaddr + 0x148);
-               writel(0x00680000, ioaddr + 0x1C8);
-       }
-
-       /* report the clocking mode of the controller */
-       if (!pdev_is_sata(dev)) {
-               static const char *clk_str[] =
-                       { "== 100", "== 133", "== 2X PCI", "DISABLED!" };
-
-               tmp >>= 4;
-               printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n",
-                       pci_name(dev), clk_str[tmp & 3]);
-       }
-
-       return 0;
-}
-
-/**
- *     init_mmio_iops_siimage  -       set up the iops for MMIO
- *     @hwif: interface to set up
- *
- *     The basic setup here is fairly simple, we can use standard MMIO
- *     operations. However we do have to set the taskfile register offsets
- *     by hand as there isn't a standard defined layout for them this time.
- *
- *     The hardware supports buffered taskfiles and also some rather nice
- *     extended PRD tables. For better SI3112 support use the libata driver
- */
-
-static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct ide_host *host   = pci_get_drvdata(dev);
-       void *addr              = host->host_priv;
-       u8 ch                   = hwif->channel;
-       struct ide_io_ports *io_ports = &hwif->io_ports;
-       unsigned long base;
-
-       /*
-        *      Fill in the basic hwif bits
-        */
-       hwif->host_flags |= IDE_HFLAG_MMIO;
-
-       hwif->hwif_data = addr;
-
-       /*
-        *      Now set up the hw. We have to do this ourselves as the
-        *      MMIO layout isn't the same as the standard port based I/O.
-        */
-       memset(io_ports, 0, sizeof(*io_ports));
-
-       base = (unsigned long)addr;
-       if (ch)
-               base += 0xC0;
-       else
-               base += 0x80;
-
-       /*
-        *      The buffered task file doesn't have status/control, so we
-        *      can't currently use it sanely since we want to use LBA48 mode.
-        */
-       io_ports->data_addr     = base;
-       io_ports->error_addr    = base + 1;
-       io_ports->nsect_addr    = base + 2;
-       io_ports->lbal_addr     = base + 3;
-       io_ports->lbam_addr     = base + 4;
-       io_ports->lbah_addr     = base + 5;
-       io_ports->device_addr   = base + 6;
-       io_ports->status_addr   = base + 7;
-       io_ports->ctl_addr      = base + 10;
-
-       if (pdev_is_sata(dev)) {
-               base = (unsigned long)addr;
-               if (ch)
-                       base += 0x80;
-               hwif->sata_scr[SATA_STATUS_OFFSET]      = base + 0x104;
-               hwif->sata_scr[SATA_ERROR_OFFSET]       = base + 0x108;
-               hwif->sata_scr[SATA_CONTROL_OFFSET]     = base + 0x100;
-       }
-
-       hwif->irq = dev->irq;
-
-       hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
-}
-
-static int is_dev_seagate_sata(ide_drive_t *drive)
-{
-       const char *s   = (const char *)&drive->id[ATA_ID_PROD];
-       unsigned len    = strnlen(s, ATA_ID_PROD_LEN);
-
-       if ((len > 4) && (!memcmp(s, "ST", 2)))
-               if ((!memcmp(s + len - 2, "AS", 2)) ||
-                   (!memcmp(s + len - 3, "ASL", 3))) {
-                       printk(KERN_INFO "%s: applying pessimistic Seagate "
-                                        "errata fix\n", drive->name);
-                       return 1;
-               }
-
-       return 0;
-}
-
-/**
- *     sil_quirkproc           -       post probe fixups
- *     @drive: drive
- *
- *     Called after drive probe we use this to decide whether the
- *     Seagate fixup must be applied. This used to be in init_iops but
- *     that can occur before we know what drives are present.
- */
-
-static void sil_quirkproc(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       /* Try and rise the rqsize */
-       if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
-               hwif->rqsize = 128;
-}
-
-/**
- *     init_iops_siimage       -       set up iops
- *     @hwif: interface to set up
- *
- *     Do the basic setup for the SIIMAGE hardware interface
- *     and then do the MMIO setup if we can. This is the first
- *     look in we get for setting up the hwif so that we
- *     can get the iops right before using them.
- */
-
-static void __devinit init_iops_siimage(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct ide_host *host = pci_get_drvdata(dev);
-
-       hwif->hwif_data = NULL;
-
-       /* Pessimal until we finish probing */
-       hwif->rqsize = 15;
-
-       if (host->host_priv)
-               init_mmio_iops_siimage(hwif);
-}
-
-/**
- *     sil_cable_detect        -       cable detection
- *     @hwif: interface to check
- *
- *     Check for the presence of an ATA66 capable cable on the interface.
- */
-
-static u8 sil_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       unsigned long addr      = siimage_selreg(hwif, 0);
-       u8 ata66                = sil_ioread8(dev, addr);
-
-       return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-}
-
-static const struct ide_port_ops sil_pata_port_ops = {
-       .set_pio_mode           = sil_set_pio_mode,
-       .set_dma_mode           = sil_set_dma_mode,
-       .quirkproc              = sil_quirkproc,
-       .udma_filter            = sil_pata_udma_filter,
-       .cable_detect           = sil_cable_detect,
-};
-
-static const struct ide_port_ops sil_sata_port_ops = {
-       .set_pio_mode           = sil_set_pio_mode,
-       .set_dma_mode           = sil_set_dma_mode,
-       .reset_poll             = sil_sata_reset_poll,
-       .pre_reset              = sil_sata_pre_reset,
-       .quirkproc              = sil_quirkproc,
-       .udma_filter            = sil_sata_udma_filter,
-       .cable_detect           = sil_cable_detect,
-};
-
-static const struct ide_dma_ops sil_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           = siimage_dma_test_irq,
-       .dma_timeout            = ide_dma_timeout,
-       .dma_lost_irq           = ide_dma_lost_irq,
-};
-
-#define DECLARE_SII_DEV(p_ops)                         \
-       {                                               \
-               .name           = DRV_NAME,             \
-               .init_chipset   = init_chipset_siimage, \
-               .init_iops      = init_iops_siimage,    \
-               .port_ops       = p_ops,                \
-               .dma_ops        = &sil_dma_ops,         \
-               .pio_mask       = ATA_PIO4,             \
-               .mwdma_mask     = ATA_MWDMA2,           \
-               .udma_mask      = ATA_UDMA6,            \
-       }
-
-static const struct ide_port_info siimage_chipsets[] __devinitdata = {
-       /* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
-       /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
-};
-
-/**
- *     siimage_init_one        -       PCI layer discovery entry
- *     @dev: PCI device
- *     @id: ident table entry
- *
- *     Called by the PCI code when it finds an SiI680 or SiI3112 controller.
- *     We then use the IDE PCI generic helper to do most of the work.
- */
-
-static int __devinit siimage_init_one(struct pci_dev *dev,
-                                     const struct pci_device_id *id)
-{
-       void __iomem *ioaddr = NULL;
-       resource_size_t bar5 = pci_resource_start(dev, 5);
-       unsigned long barsize = pci_resource_len(dev, 5);
-       int rc;
-       struct ide_port_info d;
-       u8 idx = id->driver_data;
-       u8 BA5_EN;
-
-       d = siimage_chipsets[idx];
-
-       if (idx) {
-               static int first = 1;
-
-               if (first) {
-                       printk(KERN_INFO DRV_NAME ": For full SATA support you "
-                               "should use the libata sata_sil module.\n");
-                       first = 0;
-               }
-
-               d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
-       }
-
-       rc = pci_enable_device(dev);
-       if (rc)
-               return rc;
-
-       pci_read_config_byte(dev, 0x8A, &BA5_EN);
-       if ((BA5_EN & 0x01) || bar5) {
-               /*
-               * Drop back to PIO if we can't map the MMIO. Some systems
-               * seem to get terminally confused in the PCI spaces.
-               */
-               if (!request_mem_region(bar5, barsize, d.name)) {
-                       printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
-                               "available\n", pci_name(dev));
-               } else {
-                       ioaddr = ioremap(bar5, barsize);
-                       if (ioaddr == NULL)
-                               release_mem_region(bar5, barsize);
-               }
-       }
-
-       rc = ide_pci_init_one(dev, &d, ioaddr);
-       if (rc) {
-               if (ioaddr) {
-                       iounmap(ioaddr);
-                       release_mem_region(bar5, barsize);
-               }
-               pci_disable_device(dev);
-       }
-
-       return rc;
-}
-
-static void __devexit siimage_remove(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       void __iomem *ioaddr = host->host_priv;
-
-       ide_pci_remove(dev);
-
-       if (ioaddr) {
-               resource_size_t bar5 = pci_resource_start(dev, 5);
-               unsigned long barsize = pci_resource_len(dev, 5);
-
-               iounmap(ioaddr);
-               release_mem_region(bar5, barsize);
-       }
-
-       pci_disable_device(dev);
-}
-
-static const struct pci_device_id siimage_pci_tbl[] = {
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680),    0 },
-#ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112),   1 },
-       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
-#endif
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
-
-static struct pci_driver siimage_pci_driver = {
-       .name           = "SiI_IDE",
-       .id_table       = siimage_pci_tbl,
-       .probe          = siimage_init_one,
-       .remove         = __devexit_p(siimage_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init siimage_ide_init(void)
-{
-       return ide_pci_register_driver(&siimage_pci_driver);
-}
-
-static void __exit siimage_ide_exit(void)
-{
-       pci_unregister_driver(&siimage_pci_driver);
-}
-
-module_init(siimage_ide_init);
-module_exit(siimage_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick, Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for SiI IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
deleted file mode 100644 (file)
index ad32e18..0000000
+++ /dev/null
@@ -1,641 +0,0 @@
-/*
- * Copyright (C) 1999-2000     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2002          Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
- * Copyright (C) 2003          Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
- *
- * May be copied or modified under the terms of the GNU General Public License
- *
- *
- * Thanks :
- *
- * SiS Taiwan          : for direct support and hardware.
- * Daniela Engert      : for initial ATA100 advices and numerous others.
- * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt       :
- *                       for checking code correctness, providing patches.
- *
- *
- * Original tests and design on the SiS620 chipset.
- * ATA100 tests and design on the SiS735 chipset.
- * ATA16/33 support from specs
- * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw>
- * ATA133 961/962/963 fixes by Vojtech Pavlik <vojtech@suse.cz>
- *
- * Documentation:
- *     SiS chipset documentation available under NDA to companies only
- *      (not to individuals).
- */
-
-/*
- * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original
- * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511
- * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip.
- *
- * Later SiS chipsets integrated the 5513 functionality into the NorthBridge,
- * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We
- * can figure out that we have a more modern and more capable 5513 by looking
- * for the respective NorthBridge IDs.
- *
- * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513
- * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI
- * ID, while the now ATA-133 capable 5513 still has the same PCI ID.
- * Fortunately the 5513 can be 'unmasked' by fiddling with some config space
- * bits, changing its device id to the true one - 5517 for 961 and 5518 for
- * 962/963.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#define DRV_NAME "sis5513"
-
-/* registers layout and init values are chipset family dependant */
-
-#define ATA_16         0x01
-#define ATA_33         0x02
-#define ATA_66         0x03
-#define ATA_100a       0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
-#define ATA_100                0x05
-#define ATA_133a       0x06 /* SiS961b with 133 support */
-#define ATA_133                0x07 /* SiS962/963 */
-
-static u8 chipset_family;
-
-/*
- * Devices supported
- */
-static const struct {
-       const char *name;
-       u16 host_id;
-       u8 chipset_family;
-       u8 flags;
-} SiSHostChipInfo[] = {
-       { "SiS968",     PCI_DEVICE_ID_SI_968,   ATA_133  },
-       { "SiS966",     PCI_DEVICE_ID_SI_966,   ATA_133  },
-       { "SiS965",     PCI_DEVICE_ID_SI_965,   ATA_133  },
-       { "SiS745",     PCI_DEVICE_ID_SI_745,   ATA_100  },
-       { "SiS735",     PCI_DEVICE_ID_SI_735,   ATA_100  },
-       { "SiS733",     PCI_DEVICE_ID_SI_733,   ATA_100  },
-       { "SiS635",     PCI_DEVICE_ID_SI_635,   ATA_100  },
-       { "SiS633",     PCI_DEVICE_ID_SI_633,   ATA_100  },
-
-       { "SiS730",     PCI_DEVICE_ID_SI_730,   ATA_100a },
-       { "SiS550",     PCI_DEVICE_ID_SI_550,   ATA_100a },
-
-       { "SiS640",     PCI_DEVICE_ID_SI_640,   ATA_66   },
-       { "SiS630",     PCI_DEVICE_ID_SI_630,   ATA_66   },
-       { "SiS620",     PCI_DEVICE_ID_SI_620,   ATA_66   },
-       { "SiS540",     PCI_DEVICE_ID_SI_540,   ATA_66   },
-       { "SiS530",     PCI_DEVICE_ID_SI_530,   ATA_66   },
-
-       { "SiS5600",    PCI_DEVICE_ID_SI_5600,  ATA_33   },
-       { "SiS5598",    PCI_DEVICE_ID_SI_5598,  ATA_33   },
-       { "SiS5597",    PCI_DEVICE_ID_SI_5597,  ATA_33   },
-       { "SiS5591/2",  PCI_DEVICE_ID_SI_5591,  ATA_33   },
-       { "SiS5582",    PCI_DEVICE_ID_SI_5582,  ATA_33   },
-       { "SiS5581",    PCI_DEVICE_ID_SI_5581,  ATA_33   },
-
-       { "SiS5596",    PCI_DEVICE_ID_SI_5596,  ATA_16   },
-       { "SiS5571",    PCI_DEVICE_ID_SI_5571,  ATA_16   },
-       { "SiS5517",    PCI_DEVICE_ID_SI_5517,  ATA_16   },
-       { "SiS551x",    PCI_DEVICE_ID_SI_5511,  ATA_16   },
-};
-
-/* Cycle time bits and values vary across chip dma capabilities
-   These three arrays hold the register layout and the values to set.
-   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
-
-/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
-static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
-static u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
-static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
-       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
-       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
-       {  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
-       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
-       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
-                                     different cycle_time range and offset */
-       { 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
-       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
-       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
-};
-/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
-   See SiS962 data sheet for more detail */
-static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
-       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
-       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
-       { 2, 1, 1, 0, 0, 0, 0 },
-       { 4, 3, 2, 1, 0, 0, 0 },
-       { 4, 3, 2, 1, 0, 0, 0 },
-       { 6, 4, 3, 1, 1, 1, 0 },
-       { 9, 6, 4, 2, 2, 2, 2 },
-       { 9, 6, 4, 2, 2, 2, 2 },
-};
-/* Initialize time, Active time, Recovery time vary across
-   IDE clock settings. These 3 arrays hold the register value
-   for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
-static u8 ini_time_value[][8] = {
-       { 0, 0, 0, 0, 0, 0, 0, 0 },
-       { 0, 0, 0, 0, 0, 0, 0, 0 },
-       { 2, 1, 0, 0, 0, 1, 0, 0 },
-       { 4, 3, 1, 1, 1, 3, 1, 1 },
-       { 4, 3, 1, 1, 1, 3, 1, 1 },
-       { 6, 4, 2, 2, 2, 4, 2, 2 },
-       { 9, 6, 3, 3, 3, 6, 3, 3 },
-       { 9, 6, 3, 3, 3, 6, 3, 3 },
-};
-static u8 act_time_value[][8] = {
-       {  0,  0,  0,  0, 0,  0,  0, 0 },
-       {  0,  0,  0,  0, 0,  0,  0, 0 },
-       {  9,  9,  9,  2, 2,  7,  2, 2 },
-       { 19, 19, 19,  5, 4, 14,  5, 4 },
-       { 19, 19, 19,  5, 4, 14,  5, 4 },
-       { 28, 28, 28,  7, 6, 21,  7, 6 },
-       { 38, 38, 38, 10, 9, 28, 10, 9 },
-       { 38, 38, 38, 10, 9, 28, 10, 9 },
-};
-static u8 rco_time_value[][8] = {
-       {  0,  0, 0,  0, 0,  0,  0, 0 },
-       {  0,  0, 0,  0, 0,  0,  0, 0 },
-       {  9,  2, 0,  2, 0,  7,  1, 1 },
-       { 19,  5, 1,  5, 2, 16,  3, 2 },
-       { 19,  5, 1,  5, 2, 16,  3, 2 },
-       { 30,  9, 3,  9, 4, 25,  6, 4 },
-       { 40, 12, 4, 12, 5, 34, 12, 5 },
-       { 40, 12, 4, 12, 5, 34, 12, 5 },
-};
-
-/*
- * Printing configuration
- */
-/* Used for chipset type printing at boot time */
-static char *chipset_capability[] = {
-       "ATA", "ATA 16",
-       "ATA 33", "ATA 66",
-       "ATA 100 (1st gen)", "ATA 100 (2nd gen)",
-       "ATA 133 (1st gen)", "ATA 133 (2nd gen)"
-};
-
-/*
- * Configuration functions
- */
-
-static u8 sis_ata133_get_base(ide_drive_t *drive)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u32 reg54 = 0;
-
-       pci_read_config_dword(dev, 0x54, &reg54);
-
-       return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
-}
-
-static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u16 t1 = 0;
-       u8 drive_pci = 0x40 + drive->dn * 2;
-
-       const u16 pio_timings[]   = { 0x000, 0x607, 0x404, 0x303, 0x301 };
-       const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 };
-
-       pci_read_config_word(dev, drive_pci, &t1);
-
-       /* clear active/recovery timings */
-       t1 &= ~0x070f;
-       if (mode >= XFER_MW_DMA_0) {
-               if (chipset_family > ATA_16)
-                       t1 &= ~0x8000;  /* disable UDMA */
-               t1 |= mwdma_timings[mode - XFER_MW_DMA_0];
-       } else
-               t1 |= pio_timings[mode - XFER_PIO_0];
-
-       pci_write_config_word(dev, drive_pci, t1);
-}
-
-static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u8 t1, drive_pci = 0x40 + drive->dn * 2;
-
-       /* timing bits: 7:4 active 3:0 recovery */
-       const u8 pio_timings[]   = { 0x00, 0x67, 0x44, 0x33, 0x31 };
-       const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 };
-
-       if (mode >= XFER_MW_DMA_0) {
-               u8 t2 = 0;
-
-               pci_read_config_byte(dev, drive_pci, &t2);
-               t2 &= ~0x80;    /* disable UDMA */
-               pci_write_config_byte(dev, drive_pci, t2);
-
-               t1 = mwdma_timings[mode - XFER_MW_DMA_0];
-       } else
-               t1 = pio_timings[mode - XFER_PIO_0];
-
-       pci_write_config_byte(dev, drive_pci + 1, t1);
-}
-
-static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u32 t1 = 0;
-       u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
-
-       pci_read_config_dword(dev, drive_pci, &t1);
-
-       t1 &= 0xc0c00fff;
-       clk = (t1 & 0x08) ? ATA_133 : ATA_100;
-       if (mode >= XFER_MW_DMA_0) {
-               t1 &= ~0x04;    /* disable UDMA */
-               idx = mode - XFER_MW_DMA_0 + 5;
-       } else
-               idx = mode - XFER_PIO_0;
-       t1 |= ini_time_value[clk][idx] << 12;
-       t1 |= act_time_value[clk][idx] << 16;
-       t1 |= rco_time_value[clk][idx] << 24;
-
-       pci_write_config_dword(dev, drive_pci, t1);
-}
-
-static void sis_program_timings(ide_drive_t *drive, const u8 mode)
-{
-       if (chipset_family < ATA_100)           /* ATA_16/33/66/100a */
-               sis_ata16_program_timings(drive, mode);
-       else if (chipset_family < ATA_133)      /* ATA_100/133a */
-               sis_ata100_program_timings(drive, mode);
-       else                                    /* ATA_133 */
-               sis_ata133_program_timings(drive, mode);
-}
-
-static void config_drive_art_rwp(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 reg4bh               = 0;
-       u8 rw_prefetch          = 0;
-
-       pci_read_config_byte(dev, 0x4b, &reg4bh);
-
-       if (drive->media == ide_disk)
-               rw_prefetch = 0x11 << drive->dn;
-
-       if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch)
-               pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
-}
-
-static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       config_drive_art_rwp(drive);
-       sis_program_timings(drive, XFER_PIO_0 + pio);
-}
-
-static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u32 regdw = 0;
-       u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
-
-       pci_read_config_dword(dev, drive_pci, &regdw);
-
-       regdw |= 0x04;
-       regdw &= 0xfffff00f;
-       /* check if ATA133 enable */
-       clk = (regdw & 0x08) ? ATA_133 : ATA_100;
-       idx = mode - XFER_UDMA_0;
-       regdw |= cycle_time_value[clk][idx] << 4;
-       regdw |= cvs_time_value[clk][idx] << 8;
-
-       pci_write_config_dword(dev, drive_pci, regdw);
-}
-
-static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
-
-       pci_read_config_byte(dev, drive_pci + 1, &reg);
-
-       /* force the UDMA bit on if we want to use UDMA */
-       reg |= 0x80;
-       /* clean reg cycle time bits */
-       reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
-       /* set reg cycle time bits */
-       reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
-
-       pci_write_config_byte(dev, drive_pci + 1, reg);
-}
-
-static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
-{
-       if (chipset_family >= ATA_133)  /* ATA_133 */
-               sis_ata133_program_udma_timings(drive, mode);
-       else                            /* ATA_33/66/100a/100/133a */
-               sis_ata33_program_udma_timings(drive, mode);
-}
-
-static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       if (speed >= XFER_UDMA_0)
-               sis_program_udma_timings(drive, speed);
-       else
-               sis_program_timings(drive, speed);
-}
-
-static u8 sis_ata133_udma_filter(ide_drive_t *drive)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u32 regdw = 0;
-       u8 drive_pci = sis_ata133_get_base(drive);
-
-       pci_read_config_dword(dev, drive_pci, &regdw);
-
-       /* if ATA133 disable, we should not set speed above UDMA5 */
-       return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
-}
-
-static int __devinit sis_find_family(struct pci_dev *dev)
-{
-       struct pci_dev *host;
-       int i = 0;
-
-       chipset_family = 0;
-
-       for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {
-
-               host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
-
-               if (!host)
-                       continue;
-
-               chipset_family = SiSHostChipInfo[i].chipset_family;
-
-               /* Special case for SiS630 : 630S/ET is ATA_100a */
-               if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
-                       if (host->revision >= 0x30)
-                               chipset_family = ATA_100a;
-               }
-               pci_dev_put(host);
-
-               printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
-                       pci_name(dev), SiSHostChipInfo[i].name,
-                       chipset_capability[chipset_family]);
-       }
-
-       if (!chipset_family) { /* Belongs to pci-quirks */
-
-                       u32 idemisc;
-                       u16 trueid;
-
-                       /* Disable ID masking and register remapping */
-                       pci_read_config_dword(dev, 0x54, &idemisc);
-                       pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));
-                       pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
-                       pci_write_config_dword(dev, 0x54, idemisc);
-
-                       if (trueid == 0x5518) {
-                               printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
-                                       pci_name(dev));
-                               chipset_family = ATA_133;
-
-                               /* Check for 5513 compability mapping
-                                * We must use this, else the port enabled code will fail,
-                                * as it expects the enablebits at 0x4a.
-                                */
-                               if ((idemisc & 0x40000000) == 0) {
-                                       pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
-                                       printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
-                                               pci_name(dev));
-                               }
-                       }
-       }
-
-       if (!chipset_family) { /* Belongs to pci-quirks */
-
-                       struct pci_dev *lpc_bridge;
-                       u16 trueid;
-                       u8 prefctl;
-                       u8 idecfg;
-
-                       pci_read_config_byte(dev, 0x4a, &idecfg);
-                       pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
-                       pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
-                       pci_write_config_byte(dev, 0x4a, idecfg);
-
-                       if (trueid == 0x5517) { /* SiS 961/961B */
-
-                               lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
-                               pci_read_config_byte(dev, 0x49, &prefctl);
-                               pci_dev_put(lpc_bridge);
-
-                               if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
-                                       printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
-                                               pci_name(dev));
-                                       chipset_family = ATA_133a;
-                               } else {
-                                       printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
-                                               pci_name(dev));
-                                       chipset_family = ATA_100;
-                               }
-                       }
-       }
-
-       return chipset_family;
-}
-
-static unsigned int init_chipset_sis5513(struct pci_dev *dev)
-{
-       /* Make general config ops here
-          1/ tell IDE channels to operate in Compatibility mode only
-          2/ tell old chips to allow per drive IDE timings */
-
-       u8 reg;
-       u16 regw;
-
-       switch (chipset_family) {
-       case ATA_133:
-               /* SiS962 operation mode */
-               pci_read_config_word(dev, 0x50, &regw);
-               if (regw & 0x08)
-                       pci_write_config_word(dev, 0x50, regw&0xfff7);
-               pci_read_config_word(dev, 0x52, &regw);
-               if (regw & 0x08)
-                       pci_write_config_word(dev, 0x52, regw&0xfff7);
-               break;
-       case ATA_133a:
-       case ATA_100:
-               /* Fixup latency */
-               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
-               /* Set compatibility bit */
-               pci_read_config_byte(dev, 0x49, &reg);
-               if (!(reg & 0x01))
-                       pci_write_config_byte(dev, 0x49, reg|0x01);
-               break;
-       case ATA_100a:
-       case ATA_66:
-               /* Fixup latency */
-               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
-
-               /* On ATA_66 chips the bit was elsewhere */
-               pci_read_config_byte(dev, 0x52, &reg);
-               if (!(reg & 0x04))
-                       pci_write_config_byte(dev, 0x52, reg|0x04);
-               break;
-       case ATA_33:
-               /* On ATA_33 we didn't have a single bit to set */
-               pci_read_config_byte(dev, 0x09, &reg);
-               if ((reg & 0x0f) != 0x00)
-                       pci_write_config_byte(dev, 0x09, reg&0xf0);
-       case ATA_16:
-               /* force per drive recovery and active timings
-                  needed on ATA_33 and below chips */
-               pci_read_config_byte(dev, 0x52, &reg);
-               if (!(reg & 0x08))
-                       pci_write_config_byte(dev, 0x52, reg|0x08);
-               break;
-       }
-
-       return 0;
-}
-
-struct sis_laptop {
-       u16 device;
-       u16 subvendor;
-       u16 subdevice;
-};
-
-static const struct sis_laptop sis_laptop[] = {
-       /* devid, subvendor, subdev */
-       { 0x5513, 0x1043, 0x1107 },     /* ASUS A6K */
-       { 0x5513, 0x1734, 0x105f },     /* FSC Amilo A1630 */
-       { 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
-       /* end marker */
-       { 0, }
-};
-
-static u8 sis_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       const struct sis_laptop *lap = &sis_laptop[0];
-       u8 ata66 = 0;
-
-       while (lap->device) {
-               if (lap->device == pdev->device &&
-                   lap->subvendor == pdev->subsystem_vendor &&
-                   lap->subdevice == pdev->subsystem_device)
-                       return ATA_CBL_PATA40_SHORT;
-               lap++;
-       }
-
-       if (chipset_family >= ATA_133) {
-               u16 regw = 0;
-               u16 reg_addr = hwif->channel ? 0x52: 0x50;
-               pci_read_config_word(pdev, reg_addr, &regw);
-               ata66 = (regw & 0x8000) ? 0 : 1;
-       } else if (chipset_family >= ATA_66) {
-               u8 reg48h = 0;
-               u8 mask = hwif->channel ? 0x20 : 0x10;
-               pci_read_config_byte(pdev, 0x48, &reg48h);
-               ata66 = (reg48h & mask) ? 0 : 1;
-       }
-
-       return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
-}
-
-static const struct ide_port_ops sis_port_ops = {
-       .set_pio_mode           = sis_set_pio_mode,
-       .set_dma_mode           = sis_set_dma_mode,
-       .cable_detect           = sis_cable_detect,
-};
-
-static const struct ide_port_ops sis_ata133_port_ops = {
-       .set_pio_mode           = sis_set_pio_mode,
-       .set_dma_mode           = sis_set_dma_mode,
-       .udma_filter            = sis_ata133_udma_filter,
-       .cable_detect           = sis_cable_detect,
-};
-
-static const struct ide_port_info sis5513_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_chipset   = init_chipset_sis5513,
-       .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
-       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
-       .pio_mask       = ATA_PIO4,
-       .mwdma_mask     = ATA_MWDMA2,
-};
-
-static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d = sis5513_chipset;
-       u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
-       int rc;
-
-       rc = pci_enable_device(dev);
-       if (rc)
-               return rc;
-
-       if (sis_find_family(dev) == 0)
-               return -ENOTSUPP;
-
-       if (chipset_family >= ATA_133)
-               d.port_ops = &sis_ata133_port_ops;
-       else
-               d.port_ops = &sis_port_ops;
-
-       d.udma_mask = udma_rates[chipset_family];
-
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-static void __devexit sis5513_remove(struct pci_dev *dev)
-{
-       ide_pci_remove(dev);
-       pci_disable_device(dev);
-}
-
-static const struct pci_device_id sis5513_pci_tbl[] = {
-       { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 },
-       { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 },
-       { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
-
-static struct pci_driver sis5513_pci_driver = {
-       .name           = "SIS_IDE",
-       .id_table       = sis5513_pci_tbl,
-       .probe          = sis5513_init_one,
-       .remove         = __devexit_p(sis5513_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init sis5513_ide_init(void)
-{
-       return ide_pci_register_driver(&sis5513_pci_driver);
-}
-
-static void __exit sis5513_ide_exit(void)
-{
-       pci_unregister_driver(&sis5513_pci_driver);
-}
-
-module_init(sis5513_ide_init);
-module_exit(sis5513_ide_exit);
-
-MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
-MODULE_DESCRIPTION("PCI driver module for SIS IDE");
-MODULE_LICENSE("GPL");
-
-/*
- * TODO:
- *     - CLEANUP
- *     - More checks in the config registers (force values instead of
- *       relying on the BIOS setting them correctly).
- *     - Further optimisations ?
- *       . for example ATA66+ regs 0x48 & 0x4A
- */
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
deleted file mode 100644 (file)
index 84dc336..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * SL82C105/Winbond 553 IDE driver
- *
- * Maintainer unknown.
- *
- * Drive tuning added from Rebel.com's kernel sources
- *  -- Russell King (15/11/98) linux@arm.linux.org.uk
- * 
- * Merge in Russell's HW workarounds, fix various problems
- * with the timing registers setup.
- *  -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org
- *
- * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
- * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "sl82c105"
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(arg) printk arg
-#else
-#define DBG(fmt,...)
-#endif
-/*
- * SL82C105 PCI config register 0x40 bits.
- */
-#define CTRL_IDE_IRQB   (1 << 30)
-#define CTRL_IDE_IRQA   (1 << 28)
-#define CTRL_LEGIRQ     (1 << 11)
-#define CTRL_P1F16      (1 << 5)
-#define CTRL_P1EN       (1 << 4)
-#define CTRL_P0F16      (1 << 1)
-#define CTRL_P0EN       (1 << 0)
-
-/*
- * Convert a PIO mode and cycle time to the required on/off times
- * for the interface.  This has protection against runaway timings.
- */
-static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
-{
-       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-       unsigned int cmd_on, cmd_off;
-       u8 iordy = 0;
-
-       cmd_on  = (t->active + 29) / 30;
-       cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30;
-
-       if (cmd_on == 0)
-               cmd_on = 1;
-
-       if (cmd_off == 0)
-               cmd_off = 1;
-
-       if (pio > 2 || ata_id_has_iordy(drive->id))
-               iordy = 0x40;
-
-       return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy;
-}
-
-/*
- * Configure the chipset for PIO mode.
- */
-static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       struct pci_dev *dev     = to_pci_dev(drive->hwif->dev);
-       int reg                 = 0x44 + drive->dn * 4;
-       u16 drv_ctrl;
-
-       drv_ctrl = get_pio_timings(drive, pio);
-
-       /*
-        * Store the PIO timings so that we can restore them
-        * in case DMA will be turned off...
-        */
-       drive->drive_data &= 0xffff0000;
-       drive->drive_data |= drv_ctrl;
-
-       pci_write_config_word(dev, reg,  drv_ctrl);
-       pci_read_config_word (dev, reg, &drv_ctrl);
-
-       printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
-                         ide_xfer_verbose(pio + XFER_PIO_0),
-                         ide_pio_cycle_time(drive, pio), drv_ctrl);
-}
-
-/*
- * Configure the chipset for DMA mode.
- */
-static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
-       u16 drv_ctrl;
-
-       DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
-            drive->name, ide_xfer_verbose(speed)));
-
-       drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
-
-       /*
-        * Store the DMA timings so that we can actually program
-        * them when DMA will be turned on...
-        */
-       drive->drive_data &= 0x0000ffff;
-       drive->drive_data |= (unsigned long)drv_ctrl << 16;
-}
-
-/*
- * The SL82C105 holds off all IDE interrupts while in DMA mode until
- * all DMA activity is completed.  Sometimes this causes problems (eg,
- * when the drive wants to report an error condition).
- *
- * 0x7e is a "chip testing" register.  Bit 2 resets the DMA controller
- * state machine.  We need to kick this to work around various bugs.
- */
-static inline void sl82c105_reset_host(struct pci_dev *dev)
-{
-       u16 val;
-
-       pci_read_config_word(dev, 0x7e, &val);
-       pci_write_config_word(dev, 0x7e, val | (1 << 2));
-       pci_write_config_word(dev, 0x7e, val & ~(1 << 2));
-}
-
-/*
- * If we get an IRQ timeout, it might be that the DMA state machine
- * got confused.  Fix from Todd Inglett.  Details from Winbond.
- *
- * This function is called when the IDE timer expires, the drive
- * indicates that it is READY, and we were waiting for DMA to complete.
- */
-static void sl82c105_dma_lost_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u32 val, mask           = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
-       u8 dma_cmd;
-
-       printk("sl82c105: lost IRQ, resetting host\n");
-
-       /*
-        * Check the raw interrupt from the drive.
-        */
-       pci_read_config_dword(dev, 0x40, &val);
-       if (val & mask)
-               printk("sl82c105: drive was requesting IRQ, but host lost it\n");
-
-       /*
-        * Was DMA enabled?  If so, disable it - we're resetting the
-        * host.  The IDE layer will be handling the drive for us.
-        */
-       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-       if (dma_cmd & 1) {
-               outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
-               printk("sl82c105: DMA was enabled\n");
-       }
-
-       sl82c105_reset_host(dev);
-}
-
-/*
- * ATAPI devices can cause the SL82C105 DMA state machine to go gaga.
- * Winbond recommend that the DMA state machine is reset prior to
- * setting the bus master DMA enable bit.
- *
- * The generic IDE core will have disabled the BMEN bit before this
- * function is called.
- */
-static void sl82c105_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       int reg                 = 0x44 + drive->dn * 4;
-
-       DBG(("%s(drive:%s)\n", __func__, drive->name));
-
-       pci_write_config_word(dev, reg, drive->drive_data >> 16);
-
-       sl82c105_reset_host(dev);
-       ide_dma_start(drive);
-}
-
-static void sl82c105_dma_timeout(ide_drive_t *drive)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-
-       DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
-
-       sl82c105_reset_host(dev);
-       ide_dma_timeout(drive);
-}
-
-static int sl82c105_dma_end(ide_drive_t *drive)
-{
-       struct pci_dev *dev     = to_pci_dev(drive->hwif->dev);
-       int reg                 = 0x44 + drive->dn * 4;
-       int ret;
-
-       DBG(("%s(drive:%s)\n", __func__, drive->name));
-
-       ret = ide_dma_end(drive);
-
-       pci_write_config_word(dev, reg, drive->drive_data);
-
-       return ret;
-}
-
-/*
- * ATA reset will clear the 16 bits mode in the control
- * register, we need to reprogram it
- */
-static void sl82c105_resetproc(ide_drive_t *drive)
-{
-       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       u32 val;
-
-       DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
-
-       pci_read_config_dword(dev, 0x40, &val);
-       val |= (CTRL_P1F16 | CTRL_P0F16);
-       pci_write_config_dword(dev, 0x40, val);
-}
-
-/*
- * Return the revision of the Winbond bridge
- * which this function is part of.
- */
-static u8 sl82c105_bridge_revision(struct pci_dev *dev)
-{
-       struct pci_dev *bridge;
-
-       /*
-        * The bridge should be part of the same device, but function 0.
-        */
-       bridge = pci_get_bus_and_slot(dev->bus->number,
-                              PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
-       if (!bridge)
-               return -1;
-
-       /*
-        * Make sure it is a Winbond 553 and is an ISA bridge.
-        */
-       if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
-           bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
-           bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) {
-               pci_dev_put(bridge);
-               return -1;
-       }
-       /*
-        * We need to find function 0's revision, not function 1
-        */
-       pci_dev_put(bridge);
-
-       return bridge->revision;
-}
-
-/*
- * Enable the PCI device
- * 
- * --BenH: It's arch fixup code that should enable channels that
- * have not been enabled by firmware. I decided we can still enable
- * channel 0 here at least, but channel 1 has to be enabled by
- * firmware or arch code. We still set both to 16 bits mode.
- */
-static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
-{
-       u32 val;
-
-       DBG(("init_chipset_sl82c105()\n"));
-
-       pci_read_config_dword(dev, 0x40, &val);
-       val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
-       pci_write_config_dword(dev, 0x40, val);
-
-       return dev->irq;
-}
-
-static const struct ide_port_ops sl82c105_port_ops = {
-       .set_pio_mode           = sl82c105_set_pio_mode,
-       .set_dma_mode           = sl82c105_set_dma_mode,
-       .resetproc              = sl82c105_resetproc,
-};
-
-static const struct ide_dma_ops sl82c105_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = sl82c105_dma_start,
-       .dma_end                = sl82c105_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_lost_irq           = sl82c105_dma_lost_irq,
-       .dma_timeout            = sl82c105_dma_timeout,
-};
-
-static const struct ide_port_info sl82c105_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_chipset   = init_chipset_sl82c105,
-       .enablebits     = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
-       .port_ops       = &sl82c105_port_ops,
-       .dma_ops        = &sl82c105_dma_ops,
-       .host_flags     = IDE_HFLAG_IO_32BIT |
-                         IDE_HFLAG_UNMASK_IRQS |
-/* FIXME: check for Compatibility mode in generic IDE PCI code */
-#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
-                         IDE_HFLAG_FORCE_LEGACY_IRQS |
-#endif
-                         IDE_HFLAG_SERIALIZE_DMA |
-                         IDE_HFLAG_NO_AUTODMA,
-       .pio_mask       = ATA_PIO5,
-       .mwdma_mask     = ATA_MWDMA2,
-};
-
-static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct ide_port_info d = sl82c105_chipset;
-       u8 rev = sl82c105_bridge_revision(dev);
-
-       if (rev <= 5) {
-               /*
-                * Never ever EVER under any circumstances enable
-                * DMA when the bridge is this old.
-                */
-               printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge "
-                                "revision %d, BM-DMA disabled\n", rev);
-               d.dma_ops = NULL;
-               d.mwdma_mask = 0;
-               d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
-       }
-
-       return ide_pci_init_one(dev, &d, NULL);
-}
-
-static const struct pci_device_id sl82c105_pci_tbl[] = {
-       { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
-
-static struct pci_driver sl82c105_pci_driver = {
-       .name           = "W82C105_IDE",
-       .id_table       = sl82c105_pci_tbl,
-       .probe          = sl82c105_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init sl82c105_ide_init(void)
-{
-       return ide_pci_register_driver(&sl82c105_pci_driver);
-}
-
-static void __exit sl82c105_ide_exit(void)
-{
-       pci_unregister_driver(&sl82c105_pci_driver);
-}
-
-module_init(sl82c105_ide_init);
-module_exit(sl82c105_ide_exit);
-
-MODULE_DESCRIPTION("PCI driver module for W82C105 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
deleted file mode 100644 (file)
index 0f759e4..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *  Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
- *
- * This is a look-alike variation of the ICH0 PIIX4 Ultra-66,
- * but this keeps the ISA-Bridge and slots alive.
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "slc90e66"
-
-static DEFINE_SPINLOCK(slc90e66_lock);
-
-static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       int is_slave            = drive->dn & 1;
-       int master_port         = hwif->channel ? 0x42 : 0x40;
-       int slave_port          = 0x44;
-       unsigned long flags;
-       u16 master_data;
-       u8 slave_data;
-       int control = 0;
-                                    /* ISP  RTC */
-       static const u8 timings[][2] = {
-                                       { 0, 0 },
-                                       { 0, 0 },
-                                       { 1, 0 },
-                                       { 2, 1 },
-                                       { 2, 3 }, };
-
-       spin_lock_irqsave(&slc90e66_lock, flags);
-       pci_read_config_word(dev, master_port, &master_data);
-
-       if (pio > 1)
-               control |= 1;   /* Programmable timing on */
-       if (drive->media == ide_disk)
-               control |= 4;   /* Prefetch, post write */
-       if (pio > 2)
-               control |= 2;   /* IORDY */
-       if (is_slave) {
-               master_data |=  0x4000;
-               master_data &= ~0x0070;
-               if (pio > 1) {
-                       /* Set PPE, IE and TIME */
-                       master_data |= control << 4;
-               }
-               pci_read_config_byte(dev, slave_port, &slave_data);
-               slave_data &= hwif->channel ? 0x0f : 0xf0;
-               slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
-                              (hwif->channel ? 4 : 0);
-       } else {
-               master_data &= ~0x3307;
-               if (pio > 1) {
-                       /* enable PPE, IE and TIME */
-                       master_data |= control;
-               }
-               master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
-       }
-       pci_write_config_word(dev, master_port, master_data);
-       if (is_slave)
-               pci_write_config_byte(dev, slave_port, slave_data);
-       spin_unlock_irqrestore(&slc90e66_lock, flags);
-}
-
-static void slc90e66_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 maslave              = hwif->channel ? 0x42 : 0x40;
-       int sitre = 0, a_speed  = 7 << (drive->dn * 4);
-       int u_speed = 0, u_flag = 1 << drive->dn;
-       u16                     reg4042, reg44, reg48, reg4a;
-
-       pci_read_config_word(dev, maslave, &reg4042);
-       sitre = (reg4042 & 0x4000) ? 1 : 0;
-       pci_read_config_word(dev, 0x44, &reg44);
-       pci_read_config_word(dev, 0x48, &reg48);
-       pci_read_config_word(dev, 0x4a, &reg4a);
-
-       if (speed >= XFER_UDMA_0) {
-               u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
-
-               if (!(reg48 & u_flag))
-                       pci_write_config_word(dev, 0x48, reg48|u_flag);
-               /* FIXME: (reg4a & a_speed) ? */
-               if ((reg4a & u_speed) != u_speed) {
-                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
-                       pci_read_config_word(dev, 0x4a, &reg4a);
-                       pci_write_config_word(dev, 0x4a, reg4a|u_speed);
-               }
-       } else {
-               const u8 mwdma_to_pio[] = { 0, 3, 4 };
-               u8 pio;
-
-               if (reg48 & u_flag)
-                       pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
-               if (reg4a & a_speed)
-                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
-
-               if (speed >= XFER_MW_DMA_0)
-                       pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
-               else
-                       pio = 2; /* only SWDMA2 is allowed */
-
-               slc90e66_set_pio_mode(drive, pio);
-       }
-}
-
-static u8 slc90e66_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02;
-
-       pci_read_config_byte(dev, 0x47, &reg47);
-
-       /* bit[0(1)]: 0:80, 1:40 */
-       return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-}
-
-static const struct ide_port_ops slc90e66_port_ops = {
-       .set_pio_mode           = slc90e66_set_pio_mode,
-       .set_dma_mode           = slc90e66_set_dma_mode,
-       .cable_detect           = slc90e66_cable_detect,
-};
-
-static const struct ide_port_info slc90e66_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
-       .port_ops       = &slc90e66_port_ops,
-       .host_flags     = IDE_HFLAG_LEGACY_IRQS,
-       .pio_mask       = ATA_PIO4,
-       .swdma_mask     = ATA_SWDMA2_ONLY,
-       .mwdma_mask     = ATA_MWDMA12_ONLY,
-       .udma_mask      = ATA_UDMA4,
-};
-
-static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &slc90e66_chipset, NULL);
-}
-
-static const struct pci_device_id slc90e66_pci_tbl[] = {
-       { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
-
-static struct pci_driver slc90e66_pci_driver = {
-       .name           = "SLC90e66_IDE",
-       .id_table       = slc90e66_pci_tbl,
-       .probe          = slc90e66_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init slc90e66_ide_init(void)
-{
-       return ide_pci_register_driver(&slc90e66_pci_driver);
-}
-
-static void __exit slc90e66_ide_exit(void)
-{
-       pci_unregister_driver(&slc90e66_pci_driver);
-}
-
-module_init(slc90e66_ide_init);
-module_exit(slc90e66_ide_exit);
-
-MODULE_AUTHOR("Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
deleted file mode 100644 (file)
index 93e2cce..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2002 Toshiba Corporation
- * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#define DRV_NAME "tc86c001"
-
-static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       unsigned long scr_port  = hwif->config_data + (drive->dn ? 0x02 : 0x00);
-       u16 mode, scr           = inw(scr_port);
-
-       switch (speed) {
-       case XFER_UDMA_4:       mode = 0x00c0; break;
-       case XFER_UDMA_3:       mode = 0x00b0; break;
-       case XFER_UDMA_2:       mode = 0x00a0; break;
-       case XFER_UDMA_1:       mode = 0x0090; break;
-       case XFER_UDMA_0:       mode = 0x0080; break;
-       case XFER_MW_DMA_2:     mode = 0x0070; break;
-       case XFER_MW_DMA_1:     mode = 0x0060; break;
-       case XFER_MW_DMA_0:     mode = 0x0050; break;
-       case XFER_PIO_4:        mode = 0x0400; break;
-       case XFER_PIO_3:        mode = 0x0300; break;
-       case XFER_PIO_2:        mode = 0x0200; break;
-       case XFER_PIO_1:        mode = 0x0100; break;
-       case XFER_PIO_0:
-       default:                mode = 0x0000; break;
-       }
-
-       scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
-       scr |= mode;
-       outw(scr, scr_port);
-}
-
-static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       tc86c001_set_mode(drive, XFER_PIO_0 + pio);
-}
-
-/*
- * HACKITY HACK
- *
- * This is a workaround for the limitation 5 of the TC86C001 IDE controller:
- * if a DMA transfer terminates prematurely, the controller leaves the device's
- * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
- * set the interrupt bit in the DMA status register), thus no PCI interrupt
- * will occur until a DMA transfer has been successfully completed.
- *
- * We work around this by initiating dummy, zero-length DMA transfer on
- * a DMA timeout expiration. I found no better way to do this with the current
- * IDE core than to temporarily replace a higher level driver's timer expiry
- * handler with our own backing up to that handler in case our recovery fails.
- */
-static int tc86c001_timer_expiry(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       ide_expiry_t *expiry    = ide_get_hwifdata(hwif);
-       ide_hwgroup_t *hwgroup  = HWGROUP(drive);
-       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
-
-       /* Restore a higher level driver's expiry handler first. */
-       hwgroup->expiry = expiry;
-
-       if ((dma_stat & 5) == 1) {      /* DMA active and no interrupt */
-               unsigned long sc_base   = hwif->config_data;
-               unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
-               u8 dma_cmd              = inb(hwif->dma_base + ATA_DMA_CMD);
-
-               printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
-                      "attempting recovery...\n", drive->name);
-
-               /* Stop DMA */
-               outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
-
-               /* Setup the dummy DMA transfer */
-               outw(0, sc_base + 0x0a);        /* Sector Count */
-               outw(0, twcr_port);     /* Transfer Word Count 1 or 2 */
-
-               /* Start the dummy DMA transfer */
-
-               /* clear R_OR_WCTR for write */
-               outb(0x00, hwif->dma_base + ATA_DMA_CMD);
-               /* set START_STOPBM */
-               outb(0x01, hwif->dma_base + ATA_DMA_CMD);
-
-               /*
-                * If an interrupt was pending, it should come thru shortly.
-                * If not, a higher level driver's expiry handler should
-                * eventually cause some kind of recovery from the DMA stall.
-                */
-               return WAIT_MIN_SLEEP;
-       }
-
-       /* Chain to the restored expiry handler if DMA wasn't active. */
-       if (likely(expiry != NULL))
-               return expiry(drive);
-
-       /* If there was no handler, "emulate" that for ide_timer_expiry()... */
-       return -1;
-}
-
-static void tc86c001_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       ide_hwgroup_t *hwgroup  = HWGROUP(drive);
-       unsigned long sc_base   = hwif->config_data;
-       unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
-       unsigned long nsectors  = hwgroup->rq->nr_sectors;
-
-       /*
-        * We have to manually load the sector count and size into
-        * the appropriate system control registers for DMA to work
-        * with LBA48 and ATAPI devices...
-        */
-       outw(nsectors, sc_base + 0x0a); /* Sector Count */
-       outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
-
-       /* Install our timeout expiry hook, saving the current handler... */
-       ide_set_hwifdata(hwif, hwgroup->expiry);
-       hwgroup->expiry = &tc86c001_timer_expiry;
-
-       ide_dma_start(drive);
-}
-
-static u8 tc86c001_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       unsigned long sc_base = pci_resource_start(dev, 5);
-       u16 scr1 = inw(sc_base + 0x00);
-
-       /*
-        * System Control  1 Register bit 13 (PDIAGN):
-        * 0=80-pin cable, 1=40-pin cable
-        */
-       return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-}
-
-static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       unsigned long sc_base   = pci_resource_start(dev, 5);
-       u16 scr1                = inw(sc_base + 0x00);
-
-       /* System Control 1 Register bit 15 (Soft Reset) set */
-       outw(scr1 |  0x8000, sc_base + 0x00);
-
-       /* System Control 1 Register bit 14 (FIFO Reset) set */
-       outw(scr1 |  0x4000, sc_base + 0x00);
-
-       /* System Control 1 Register: reset clear */
-       outw(scr1 & ~0xc000, sc_base + 0x00);
-
-       /* Store the system control register base for convenience... */
-       hwif->config_data = sc_base;
-
-       if (!hwif->dma_base)
-               return;
-
-       /*
-        * Sector Count Control Register bits 0 and 1 set:
-        * software sets Sector Count Register for master and slave device
-        */
-       outw(0x0003, sc_base + 0x0c);
-
-       /* Sector Count Register limit */
-       hwif->rqsize     = 0xffff;
-}
-
-static const struct ide_port_ops tc86c001_port_ops = {
-       .set_pio_mode           = tc86c001_set_pio_mode,
-       .set_dma_mode           = tc86c001_set_mode,
-       .cable_detect           = tc86c001_cable_detect,
-};
-
-static const struct ide_dma_ops tc86c001_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = tc86c001_dma_start,
-       .dma_end                = ide_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info tc86c001_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_hwif      = init_hwif_tc86c001,
-       .port_ops       = &tc86c001_port_ops,
-       .dma_ops        = &tc86c001_dma_ops,
-       .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
-       .pio_mask       = ATA_PIO4,
-       .mwdma_mask     = ATA_MWDMA2,
-       .udma_mask      = ATA_UDMA4,
-};
-
-static int __devinit tc86c001_init_one(struct pci_dev *dev,
-                                      const struct pci_device_id *id)
-{
-       int rc;
-
-       rc = pci_enable_device(dev);
-       if (rc)
-               goto out;
-
-       rc = pci_request_region(dev, 5, DRV_NAME);
-       if (rc) {
-               printk(KERN_ERR DRV_NAME ": system control regs already in use");
-               goto out_disable;
-       }
-
-       rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
-       if (rc)
-               goto out_release;
-
-       goto out;
-
-out_release:
-       pci_release_region(dev, 5);
-out_disable:
-       pci_disable_device(dev);
-out:
-       return rc;
-}
-
-static void __devexit tc86c001_remove(struct pci_dev *dev)
-{
-       ide_pci_remove(dev);
-       pci_release_region(dev, 5);
-       pci_disable_device(dev);
-}
-
-static const struct pci_device_id tc86c001_pci_tbl[] = {
-       { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 },
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
-
-static struct pci_driver tc86c001_pci_driver = {
-       .name           = "TC86C001",
-       .id_table       = tc86c001_pci_tbl,
-       .probe          = tc86c001_init_one,
-       .remove         = __devexit_p(tc86c001_remove),
-};
-
-static int __init tc86c001_ide_init(void)
-{
-       return ide_pci_register_driver(&tc86c001_pci_driver);
-}
-
-static void __exit tc86c001_ide_exit(void)
-{
-       pci_unregister_driver(&tc86c001_pci_driver);
-}
-
-module_init(tc86c001_ide_init);
-module_exit(tc86c001_ide_exit);
-
-MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
deleted file mode 100644 (file)
index b6ff403..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * IDE Chipset driver for the Compaq TriFlex IDE controller.
- * 
- * Known to work with the Compaq Workstation 5x00 series.
- *
- * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
- * Author: Torben Mathiasen <torben.mathiasen@hp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Loosely based on the piix & svwks drivers.
- *
- * Documentation:
- *     Not publically available.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define DRV_NAME "triflex"
-
-static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u32 triflex_timings = 0;
-       u16 timing = 0;
-       u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;
-
-       pci_read_config_dword(dev, channel_offset, &triflex_timings);
-
-       switch(speed) {
-               case XFER_MW_DMA_2:
-                       timing = 0x0103; 
-                       break;
-               case XFER_MW_DMA_1:
-                       timing = 0x0203;
-                       break;
-               case XFER_MW_DMA_0:
-                       timing = 0x0808;
-                       break;
-               case XFER_SW_DMA_2:
-               case XFER_SW_DMA_1:
-               case XFER_SW_DMA_0:
-                       timing = 0x0f0f;
-                       break;
-               case XFER_PIO_4:
-                       timing = 0x0202;
-                       break;
-               case XFER_PIO_3:
-                       timing = 0x0204;
-                       break;
-               case XFER_PIO_2:
-                       timing = 0x0404;
-                       break;
-               case XFER_PIO_1:
-                       timing = 0x0508;
-                       break;
-               case XFER_PIO_0:
-                       timing = 0x0808;
-                       break;
-       }
-
-       triflex_timings &= ~(0xFFFF << (16 * unit));
-       triflex_timings |= (timing << (16 * unit));
-       
-       pci_write_config_dword(dev, channel_offset, triflex_timings);
-}
-
-static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       triflex_set_mode(drive, XFER_PIO_0 + pio);
-}
-
-static const struct ide_port_ops triflex_port_ops = {
-       .set_pio_mode           = triflex_set_pio_mode,
-       .set_dma_mode           = triflex_set_mode,
-};
-
-static const struct ide_port_info triflex_device __devinitdata = {
-       .name           = DRV_NAME,
-       .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
-       .port_ops       = &triflex_port_ops,
-       .pio_mask       = ATA_PIO4,
-       .swdma_mask     = ATA_SWDMA2,
-       .mwdma_mask     = ATA_MWDMA2,
-};
-
-static int __devinit triflex_init_one(struct pci_dev *dev, 
-               const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &triflex_device, NULL);
-}
-
-static const struct pci_device_id triflex_pci_tbl[] = {
-       { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
-
-static struct pci_driver triflex_pci_driver = {
-       .name           = "TRIFLEX_IDE",
-       .id_table       = triflex_pci_tbl,
-       .probe          = triflex_init_one,
-       .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init triflex_ide_init(void)
-{
-       return ide_pci_register_driver(&triflex_pci_driver);
-}
-
-static void __exit triflex_ide_exit(void)
-{
-       pci_unregister_driver(&triflex_pci_driver);
-}
-
-module_init(triflex_ide_init);
-module_exit(triflex_ide_exit);
-
-MODULE_AUTHOR("Torben Mathiasen");
-MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
-MODULE_LICENSE("GPL");
-
-
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
deleted file mode 100644 (file)
index 75ea615..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- *  Copyright (c) 1997-1998  Mark Lord
- *  Copyright (c) 2007       MontaVista Software, Inc. <source@mvista.com>
- *
- *  May be copied or modified under the terms of the GNU General Public License
- *
- *  June 22, 2004 - get rid of check_region
- *                   - Jesper Juhl
- *
- */
-
-/*
- * This module provides support for the bus-master IDE DMA function
- * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards,
- * including a "Precision Instruments" board.  The TRM290 pre-dates
- * the sff-8038 standard (ide-dma.c) by a few months, and differs
- * significantly enough to warrant separate routines for some functions,
- * while re-using others from ide-dma.c.
- *
- * EXPERIMENTAL!  It works for me (a sample of one).
- *
- * Works reliably for me in DMA mode (READs only),
- * DMA WRITEs are disabled by default (see #define below);
- *
- * DMA is not enabled automatically for this chipset,
- * but can be turned on manually (with "hdparm -d1") at run time.
- *
- * I need volunteers with "spare" drives for further testing
- * and development, and maybe to help figure out the peculiarities.
- * Even knowing the registers (below), some things behave strangely.
- */
-
-#define TRM290_NO_DMA_WRITES   /* DMA writes seem unreliable sometimes */
-
-/*
- * TRM-290 PCI-IDE2 Bus Master Chip
- * ================================
- * The configuration registers are addressed in normal I/O port space
- * and are used as follows:
- *
- * trm290_base depends on jumper settings, and is probed for by ide-dma.c
- *
- * trm290_base+2 when WRITTEN: chiptest register (byte, write-only)
- *     bit7 must always be written as "1"
- *     bits6-2 undefined
- *     bit1 1=legacy_compatible_mode, 0=native_pci_mode
- *     bit0 1=test_mode, 0=normal(default)
- *
- * trm290_base+2 when READ: status register (byte, read-only)
- *     bits7-2 undefined
- *     bit1 channel0 busmaster interrupt status 0=none, 1=asserted
- *     bit0 channel0 interrupt status 0=none, 1=asserted
- *
- * trm290_base+3 Interrupt mask register
- *     bits7-5 undefined
- *     bit4 legacy_header: 1=present, 0=absent
- *     bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only)
- *     bit2 channel1 interrupt status 0=none, 1=asserted (read only)
- *     bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default)
- *     bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default)
- *
- * trm290_base+1 "CPR" Config Pointer Register (byte)
- *     bit7 1=autoincrement CPR bits 2-0 after each access of CDR
- *     bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state
- *     bit5 0=enabled master burst access (default), 1=disable  (write only)
- *     bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast
- *     bit3 0=primary IDE channel, 1=secondary IDE channel
- *     bits2-0 register index for accesses through CDR port
- *
- * trm290_base+0 "CDR" Config Data Register (word)
- *     two sets of seven config registers,
- *     selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6),
- *     each index defined below:
- *
- * Index-0 Base address register for command block (word)
- *     defaults: 0x1f0 for primary, 0x170 for secondary
- *
- * Index-1 general config register (byte)
- *     bit7 1=DMA enable, 0=DMA disable
- *     bit6 1=activate IDE_RESET, 0=no action (default)
- *     bit5 1=enable IORDY, 0=disable IORDY (default)
- *     bit4 0=16-bit data port(default), 1=8-bit (XT) data port
- *     bit3 interrupt polarity: 1=active_low, 0=active_high(default)
- *     bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only)
- *     bit1 bus_master_mode(?): 1=enable, 0=disable(default)
- *     bit0 enable_io_ports: 1=enable(default), 0=disable
- *
- * Index-2 read-ahead counter preload bits 0-7 (byte, write only)
- *     bits7-0 bits7-0 of readahead count
- *
- * Index-3 read-ahead config register (byte, write only)
- *     bit7 1=enable_readahead, 0=disable_readahead(default)
- *     bit6 1=clear_FIFO, 0=no_action
- *     bit5 undefined
- *     bit4 mode4 timing control: 1=enable, 0=disable(default)
- *     bit3 undefined
- *     bit2 undefined
- *     bits1-0 bits9-8 of read-ahead count
- *
- * Index-4 base address register for control block (word)
- *     defaults: 0x3f6 for primary, 0x376 for secondary
- *
- * Index-5 data port timings (shared by both drives) (byte)
- *     standard PCI "clk" (clock) counts, default value = 0xf5
- *
- *     bits7-6 setup time:  00=1clk, 01=2clk, 10=3clk, 11=4clk
- *     bits5-3 hold time:      000=1clk, 001=2clk, 010=3clk,
- *                             011=4clk, 100=5clk, 101=6clk,
- *                             110=8clk, 111=12clk
- *     bits2-0 active time:    000=2clk, 001=3clk, 010=4clk,
- *                             011=5clk, 100=6clk, 101=8clk,
- *                             110=12clk, 111=16clk
- *
- * Index-6 command/control port timings (shared by both drives) (byte)
- *     same layout as Index-5, default value = 0xde
- *
- * Suggested CDR programming for PIO mode0 (600ns):
- *     0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde  ; primary
- *     0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde  ; secondary
- *
- * Suggested CDR programming for PIO mode3 (180ns):
- *     0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde  ; primary
- *     0x0170,0x21,0xff,0x80,0x0376,0x09,0xde  ; secondary
- *
- * Suggested CDR programming for PIO mode4 (120ns):
- *     0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde  ; primary
- *     0x0170,0x21,0xff,0x80,0x0376,0x00,0xde  ; secondary
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-#define DRV_NAME "trm290"
-
-static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       u16 reg = 0;
-       unsigned long flags;
-
-       /* select PIO or DMA */
-       reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82);
-
-       local_irq_save(flags);
-
-       if (reg != hwif->select_data) {
-               hwif->select_data = reg;
-               /* set PIO/DMA */
-               outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
-               outw(reg & 0xff, hwif->config_data);
-       }
-
-       /* enable IRQ if not probing */
-       if (drive->dev_flags & IDE_DFLAG_PRESENT) {
-               reg = inw(hwif->config_data + 3);
-               reg &= 0x13;
-               reg &= ~(1 << hwif->channel);
-               outw(reg, hwif->config_data + 3);
-       }
-
-       local_irq_restore(flags);
-}
-
-static void trm290_selectproc (ide_drive_t *drive)
-{
-       trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
-}
-
-static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-       ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL);
-}
-
-static int trm290_dma_setup(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = hwif->hwgroup->rq;
-       unsigned int count, rw;
-
-       if (rq_data_dir(rq)) {
-#ifdef TRM290_NO_DMA_WRITES
-               /* always use PIO for writes */
-               trm290_prepare_drive(drive, 0); /* select PIO xfer */
-               return 1;
-#endif
-               rw = 1;
-       } else
-               rw = 2;
-
-       if (!(count = ide_build_dmatable(drive, rq))) {
-               /* try PIO instead of DMA */
-               trm290_prepare_drive(drive, 0); /* select PIO xfer */
-               return 1;
-       }
-       /* select DMA xfer */
-       trm290_prepare_drive(drive, 1);
-       outl(hwif->dmatable_dma | rw, hwif->dma_base);
-       drive->waiting_for_dma = 1;
-       /* start DMA */
-       outw(count * 2 - 1, hwif->dma_base + 2);
-       return 0;
-}
-
-static void trm290_dma_start(ide_drive_t *drive)
-{
-}
-
-static int trm290_dma_end(ide_drive_t *drive)
-{
-       u16 status;
-
-       drive->waiting_for_dma = 0;
-       /* purge DMA mappings */
-       ide_destroy_dmatable(drive);
-       status = inw(HWIF(drive)->dma_base + 2);
-       return status != 0x00ff;
-}
-
-static int trm290_dma_test_irq(ide_drive_t *drive)
-{
-       u16 status;
-
-       status = inw(HWIF(drive)->dma_base + 2);
-       return status == 0x00ff;
-}
-
-static void trm290_dma_host_set(ide_drive_t *drive, int on)
-{
-}
-
-static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       unsigned int  cfg_base  = pci_resource_start(dev, 4);
-       unsigned long flags;
-       u8 reg = 0;
-
-       if ((dev->class & 5) && cfg_base)
-               printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev));
-       else {
-               cfg_base = 0x3df0;
-               printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev));
-       }
-       printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
-       hwif->config_data = cfg_base;
-       hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
-
-       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
-              hwif->name, hwif->dma_base, hwif->dma_base + 3);
-
-       if (ide_allocate_dma_engine(hwif))
-               return;
-
-       local_irq_save(flags);
-       /* put config reg into first byte of hwif->select_data */
-       outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
-       /* select PIO as default */
-       hwif->select_data = 0x21;
-       outb(hwif->select_data, hwif->config_data);
-       /* get IRQ info */
-       reg = inb(hwif->config_data + 3);
-       /* mask IRQs for both ports */
-       reg = (reg & 0x10) | 0x03;
-       outb(reg, hwif->config_data + 3);
-       local_irq_restore(flags);
-
-       if (reg & 0x10)
-               /* legacy mode */
-               hwif->irq = hwif->channel ? 15 : 14;
-       else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-               /* sharing IRQ with mate */
-               hwif->irq = hwif->mate->irq;
-
-#if 1
-       {
-       /*
-        * My trm290-based card doesn't seem to work with all possible values
-        * for the control basereg, so this kludge ensures that we use only
-        * values that are known to work.  Ugh.         -ml
-        */
-               u16 new, old, compat = hwif->channel ? 0x374 : 0x3f4;
-               static u16 next_offset = 0;
-               u8 old_mask;
-
-               outb(0x54 | (hwif->channel << 3), hwif->config_data + 1);
-               old = inw(hwif->config_data);
-               old &= ~1;
-               old_mask = inb(old + 2);
-               if (old != compat && old_mask == 0xff) {
-                       /* leave lower 10 bits untouched */
-                       compat += (next_offset += 0x400);
-                       hwif->io_ports.ctl_addr = compat + 2;
-                       outw(compat | 1, hwif->config_data);
-                       new = inw(hwif->config_data);
-                       printk(KERN_INFO "%s: control basereg workaround: "
-                               "old=0x%04x, new=0x%04x\n",
-                               hwif->name, old, new & ~1);
-               }
-       }
-#endif
-}
-
-static const struct ide_port_ops trm290_port_ops = {
-       .selectproc             = trm290_selectproc,
-};
-
-static struct ide_dma_ops trm290_dma_ops = {
-       .dma_host_set           = trm290_dma_host_set,
-       .dma_setup              = trm290_dma_setup,
-       .dma_exec_cmd           = trm290_dma_exec_cmd,
-       .dma_start              = trm290_dma_start,
-       .dma_end                = trm290_dma_end,
-       .dma_test_irq           = trm290_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_port_info trm290_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_hwif      = init_hwif_trm290,
-       .chipset        = ide_trm290,
-       .port_ops       = &trm290_port_ops,
-       .dma_ops        = &trm290_dma_ops,
-       .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
-#if 0 /* play it safe for now */
-                         IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-#endif
-                         IDE_HFLAG_NO_AUTODMA |
-                         IDE_HFLAG_NO_LBA48,
-};
-
-static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       return ide_pci_init_one(dev, &trm290_chipset, NULL);
-}
-
-static const struct pci_device_id trm290_pci_tbl[] = {
-       { PCI_VDEVICE(TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290), 0 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
-
-static struct pci_driver trm290_pci_driver = {
-       .name           = "TRM290_IDE",
-       .id_table       = trm290_pci_tbl,
-       .probe          = trm290_init_one,
-       .remove         = ide_pci_remove,
-};
-
-static int __init trm290_ide_init(void)
-{
-       return ide_pci_register_driver(&trm290_pci_driver);
-}
-
-static void __exit trm290_ide_exit(void)
-{
-       pci_unregister_driver(&trm290_pci_driver);
-}
-
-module_init(trm290_ide_init);
-module_exit(trm290_ide_exit);
-
-MODULE_AUTHOR("Mark Lord");
-MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
deleted file mode 100644 (file)
index 2a812d3..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * VIA IDE driver for Linux. Supported southbridges:
- *
- *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
- *   vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a,
- *   vt8235, vt8237, vt8237a
- *
- * Copyright (c) 2000-2002 Vojtech Pavlik
- * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
- *
- * Based on the work of:
- *     Michel Aubry
- *     Jeff Garzik
- *     Andre Hedrick
- *
- * Documentation:
- *     Obsolete device documentation publically available from via.com.tw
- *     Current device documentation available under NDA only
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/dmi.h>
-
-#ifdef CONFIG_PPC_CHRP
-#include <asm/processor.h>
-#endif
-
-#define DRV_NAME "via82cxxx"
-
-#define VIA_IDE_ENABLE         0x40
-#define VIA_IDE_CONFIG         0x41
-#define VIA_FIFO_CONFIG                0x43
-#define VIA_MISC_1             0x44
-#define VIA_MISC_2             0x45
-#define VIA_MISC_3             0x46
-#define VIA_DRIVE_TIMING       0x48
-#define VIA_8BIT_TIMING                0x4e
-#define VIA_ADDRESS_SETUP      0x4c
-#define VIA_UDMA_TIMING                0x50
-
-#define VIA_BAD_PREQ           0x01 /* Crashes if PREQ# till DDACK# set */
-#define VIA_BAD_CLK66          0x02 /* 66 MHz clock doesn't work correctly */
-#define VIA_SET_FIFO           0x04 /* Needs to have FIFO split set */
-#define VIA_NO_UNMASK          0x08 /* Doesn't work with IRQ unmasking on */
-#define VIA_BAD_ID             0x10 /* Has wrong vendor ID (0x1107) */
-#define VIA_BAD_AST            0x20 /* Don't touch Address Setup Timing */
-
-/*
- * VIA SouthBridge chips.
- */
-
-static struct via_isa_bridge {
-       char *name;
-       u16 id;
-       u8 rev_min;
-       u8 rev_max;
-       u8 udma_mask;
-       u8 flags;
-} via_isa_bridges[] = {
-       { "vx800",      PCI_DEVICE_ID_VIA_VX800,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "cx700",      PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8237s",    PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt6410",     PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8251",     PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8237",     PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8237a",    PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8235",     PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8233a",    PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-       { "vt8233c",    PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, ATA_UDMA5, },
-       { "vt8233",     PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, ATA_UDMA5, },
-       { "vt8231",     PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, ATA_UDMA5, },
-       { "vt82c686b",  PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, ATA_UDMA5, },
-       { "vt82c686a",  PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, ATA_UDMA4, },
-       { "vt82c686",   PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
-       { "vt82c596b",  PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, ATA_UDMA4, },
-       { "vt82c596a",  PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
-       { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
-       { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
-       { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
-       { "vt82c586a",  PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
-       { "vt82c586",   PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f,      0x00, VIA_SET_FIFO },
-       { "vt82c576",   PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
-       { "vt82c576",   PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
-       { NULL }
-};
-
-static unsigned int via_clock;
-static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
-
-struct via82cxxx_dev
-{
-       struct via_isa_bridge *via_config;
-       unsigned int via_80w;
-};
-
-/**
- *     via_set_speed                   -       write timing registers
- *     @dev: PCI device
- *     @dn: device
- *     @timing: IDE timing data to use
- *
- *     via_set_speed writes timing values to the chipset registers
- */
-
-static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct via82cxxx_dev *vdev = host->host_priv;
-       u8 t;
-
-       if (~vdev->via_config->flags & VIA_BAD_AST) {
-               pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
-               t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
-               pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
-       }
-
-       pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
-               ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
-
-       pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
-               ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
-
-       switch (vdev->via_config->udma_mask) {
-       case ATA_UDMA2: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
-       case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break;
-       case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
-       case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
-       default: return;
-       }
-
-       pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
-}
-
-/**
- *     via_set_drive           -       configure transfer mode
- *     @drive: Drive to set up
- *     @speed: desired speed
- *
- *     via_set_drive() computes timing values configures the chipset to
- *     a desired transfer mode.  It also can be called by upper layers.
- */
-
-static void via_set_drive(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       ide_drive_t *peer = ide_get_pair_dev(drive);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct via82cxxx_dev *vdev = host->host_priv;
-       struct ide_timing t, p;
-       unsigned int T, UT;
-
-       T = 1000000000 / via_clock;
-
-       switch (vdev->via_config->udma_mask) {
-       case ATA_UDMA2: UT = T;   break;
-       case ATA_UDMA4: UT = T/2; break;
-       case ATA_UDMA5: UT = T/3; break;
-       case ATA_UDMA6: UT = T/4; break;
-       default:        UT = T;
-       }
-
-       ide_timing_compute(drive, speed, &t, T, UT);
-
-       if (peer) {
-               ide_timing_compute(peer, peer->current_speed, &p, T, UT);
-               ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
-       }
-
-       via_set_speed(HWIF(drive), drive->dn, &t);
-}
-
-/**
- *     via_set_pio_mode        -       set host controller for PIO mode
- *     @drive: drive
- *     @pio: PIO mode number
- *
- *     A callback from the upper layers for PIO-only tuning.
- */
-
-static void via_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       via_set_drive(drive, XFER_PIO_0 + pio);
-}
-
-static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
-{
-       struct via_isa_bridge *via_config;
-
-       for (via_config = via_isa_bridges; via_config->id; via_config++)
-               if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA +
-                       !!(via_config->flags & VIA_BAD_ID),
-                       via_config->id, NULL))) {
-
-                       if ((*isa)->revision >= via_config->rev_min &&
-                           (*isa)->revision <= via_config->rev_max)
-                               break;
-                       pci_dev_put(*isa);
-               }
-
-       return via_config;
-}
-
-/*
- * Check and handle 80-wire cable presence
- */
-static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
-{
-       int i;
-
-       switch (vdev->via_config->udma_mask) {
-               case ATA_UDMA4:
-                       for (i = 24; i >= 0; i -= 8)
-                               if (((u >> (i & 16)) & 8) &&
-                                   ((u >> i) & 0x20) &&
-                                    (((u >> i) & 7) < 2)) {
-                                       /*
-                                        * 2x PCI clock and
-                                        * UDMA w/ < 3T/cycle
-                                        */
-                                       vdev->via_80w |= (1 << (1 - (i >> 4)));
-                               }
-                       break;
-
-               case ATA_UDMA5:
-                       for (i = 24; i >= 0; i -= 8)
-                               if (((u >> i) & 0x10) ||
-                                   (((u >> i) & 0x20) &&
-                                    (((u >> i) & 7) < 4))) {
-                                       /* BIOS 80-wire bit or
-                                        * UDMA w/ < 60ns/cycle
-                                        */
-                                       vdev->via_80w |= (1 << (1 - (i >> 4)));
-                               }
-                       break;
-
-               case ATA_UDMA6:
-                       for (i = 24; i >= 0; i -= 8)
-                               if (((u >> i) & 0x10) ||
-                                   (((u >> i) & 0x20) &&
-                                    (((u >> i) & 7) < 6))) {
-                                       /* BIOS 80-wire bit or
-                                        * UDMA w/ < 60ns/cycle
-                                        */
-                                       vdev->via_80w |= (1 << (1 - (i >> 4)));
-                               }
-                       break;
-       }
-}
-
-/**
- *     init_chipset_via82cxxx  -       initialization handler
- *     @dev: PCI device
- *
- *     The initialization callback. Here we determine the IDE chip type
- *     and initialize its drive independent registers.
- */
-
-static unsigned int init_chipset_via82cxxx(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct via82cxxx_dev *vdev = host->host_priv;
-       struct via_isa_bridge *via_config = vdev->via_config;
-       u8 t, v;
-       u32 u;
-
-       /*
-        * Detect cable and configure Clk66
-        */
-       pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
-
-       via_cable_detect(vdev, u);
-
-       if (via_config->udma_mask == ATA_UDMA4) {
-               /* Enable Clk66 */
-               pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
-       } else if (via_config->flags & VIA_BAD_CLK66) {
-               /* Would cause trouble on 596a and 686 */
-               pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008);
-       }
-
-       /*
-        * Check whether interfaces are enabled.
-        */
-
-       pci_read_config_byte(dev, VIA_IDE_ENABLE, &v);
-
-       /*
-        * Set up FIFO sizes and thresholds.
-        */
-
-       pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);
-
-       /* Disable PREQ# till DDACK# */
-       if (via_config->flags & VIA_BAD_PREQ) {
-               /* Would crash on 586b rev 41 */
-               t &= 0x7f;
-       }
-
-       /* Fix FIFO split between channels */
-       if (via_config->flags & VIA_SET_FIFO) {
-               t &= (t & 0x9f);
-               switch (v & 3) {
-                       case 2: t |= 0x00; break;       /* 16 on primary */
-                       case 1: t |= 0x60; break;       /* 16 on secondary */
-                       case 3: t |= 0x20; break;       /* 8 pri 8 sec */
-               }
-       }
-
-       pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
-
-       return 0;
-}
-
-/*
- *     Cable special cases
- */
-
-static const struct dmi_system_id cable_dmi_table[] = {
-       {
-               .ident = "Acer Ferrari 3400",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
-                       DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
-               },
-       },
-       { }
-};
-
-static int via_cable_override(struct pci_dev *pdev)
-{
-       /* Systems by DMI */
-       if (dmi_check_system(cable_dmi_table))
-               return 1;
-
-       /* Arima W730-K8/Targa Visionary 811/... */
-       if (pdev->subsystem_vendor == 0x161F &&
-           pdev->subsystem_device == 0x2032)
-               return 1;
-
-       return 0;
-}
-
-static u8 via82cxxx_cable_detect(ide_hwif_t *hwif)
-{
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
-       struct ide_host *host = pci_get_drvdata(pdev);
-       struct via82cxxx_dev *vdev = host->host_priv;
-
-       if (via_cable_override(pdev))
-               return ATA_CBL_PATA40_SHORT;
-
-       if ((vdev->via_80w >> hwif->channel) & 1)
-               return ATA_CBL_PATA80;
-       else
-               return ATA_CBL_PATA40;
-}
-
-static const struct ide_port_ops via_port_ops = {
-       .set_pio_mode           = via_set_pio_mode,
-       .set_dma_mode           = via_set_drive,
-       .cable_detect           = via82cxxx_cable_detect,
-};
-
-static const struct ide_port_info via82cxxx_chipset __devinitdata = {
-       .name           = DRV_NAME,
-       .init_chipset   = init_chipset_via82cxxx,
-       .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
-       .port_ops       = &via_port_ops,
-       .host_flags     = IDE_HFLAG_PIO_NO_BLACKLIST |
-                         IDE_HFLAG_POST_SET_MODE |
-                         IDE_HFLAG_IO_32BIT,
-       .pio_mask       = ATA_PIO5,
-       .swdma_mask     = ATA_SWDMA2,
-       .mwdma_mask     = ATA_MWDMA2,
-};
-
-static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct pci_dev *isa = NULL;
-       struct via_isa_bridge *via_config;
-       struct via82cxxx_dev *vdev;
-       int rc;
-       u8 idx = id->driver_data;
-       struct ide_port_info d;
-
-       d = via82cxxx_chipset;
-
-       /*
-        * Find the ISA bridge and check we know what it is.
-        */
-       via_config = via_config_find(&isa);
-       if (!via_config->id) {
-               printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n",
-                       pci_name(dev));
-               return -ENODEV;
-       }
-
-       /*
-        * Print the boot message.
-        */
-       printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n",
-               pci_name(dev), via_config->name, isa->revision,
-               via_config->udma_mask ? "U" : "MW",
-               via_dma[via_config->udma_mask ?
-                       (fls(via_config->udma_mask) - 1) : 0]);
-
-       pci_dev_put(isa);
-
-       /*
-        * Determine system bus clock.
-        */
-       via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
-
-       switch (via_clock) {
-       case 33000: via_clock = 33333; break;
-       case 37000: via_clock = 37500; break;
-       case 41000: via_clock = 41666; break;
-       }
-
-       if (via_clock < 20000 || via_clock > 50000) {
-               printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
-                       "impossible (%d), using 33 MHz instead.\n", via_clock);
-               printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
-                       "to assume 80-wire cable.\n");
-               via_clock = 33333;
-       }
-
-       if (idx == 0)
-               d.host_flags |= IDE_HFLAG_NO_AUTODMA;
-       else
-               d.enablebits[1].reg = d.enablebits[0].reg = 0;
-
-       if ((via_config->flags & VIA_NO_UNMASK) == 0)
-               d.host_flags |= IDE_HFLAG_UNMASK_IRQS;
-
-#ifdef CONFIG_PPC_CHRP
-       if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos)
-               d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
-#endif
-
-       d.udma_mask = via_config->udma_mask;
-
-       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
-       if (!vdev) {
-               printk(KERN_ERR DRV_NAME " %s: out of memory :(\n",
-                       pci_name(dev));
-               return -ENOMEM;
-       }
-
-       vdev->via_config = via_config;
-
-       rc = ide_pci_init_one(dev, &d, vdev);
-       if (rc)
-               kfree(vdev);
-
-       return rc;
-}
-
-static void __devexit via_remove(struct pci_dev *dev)
-{
-       struct ide_host *host = pci_get_drvdata(dev);
-       struct via82cxxx_dev *vdev = host->host_priv;
-
-       ide_pci_remove(dev);
-       kfree(vdev);
-}
-
-static const struct pci_device_id via_pci_tbl[] = {
-       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1),  0 },
-       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1),  0 },
-       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 },
-       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410),      1 },
-       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 },
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, via_pci_tbl);
-
-static struct pci_driver via_pci_driver = {
-       .name           = "VIA_IDE",
-       .id_table       = via_pci_tbl,
-       .probe          = via_init_one,
-       .remove         = __devexit_p(via_remove),
-       .suspend        = ide_pci_suspend,
-       .resume         = ide_pci_resume,
-};
-
-static int __init via_ide_init(void)
-{
-       return ide_pci_register_driver(&via_pci_driver);
-}
-
-static void __exit via_ide_exit(void)
-{
-       pci_unregister_driver(&via_pci_driver);
-}
-
-module_init(via_ide_init);
-module_exit(via_ide_exit);
-
-MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
-MODULE_DESCRIPTION("PCI driver module for VIA IDE");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
new file mode 100644 (file)
index 0000000..211ae46
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ *  Promise TX2/TX4/TX2000/133 IDE driver
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ *  Split from:
+ *  linux/drivers/ide/pdc202xx.c       Version 0.35    Mar. 30, 2002
+ *  Copyright (C) 1998-2002            Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2005-2007            MontaVista Software, Inc.
+ *  Portions Copyright (C) 1999 Promise Technology, Inc.
+ *  Author: Frank Tiernan (frankt@promise.com)
+ *  Released under terms of General Public License
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+
+#define DRV_NAME "pdc202xx_new"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
+static const char *pdc_quirk_drives[] = {
+       "QUANTUM FIREBALLlct08 08",
+       "QUANTUM FIREBALLP KA6.4",
+       "QUANTUM FIREBALLP KA9.1",
+       "QUANTUM FIREBALLP LM20.4",
+       "QUANTUM FIREBALLP KX13.6",
+       "QUANTUM FIREBALLP KX20.5",
+       "QUANTUM FIREBALLP KX27.3",
+       "QUANTUM FIREBALLP LM20.5",
+       NULL
+};
+
+static u8 max_dma_rate(struct pci_dev *pdev)
+{
+       u8 mode;
+
+       switch(pdev->device) {
+               case PCI_DEVICE_ID_PROMISE_20277:
+               case PCI_DEVICE_ID_PROMISE_20276:
+               case PCI_DEVICE_ID_PROMISE_20275:
+               case PCI_DEVICE_ID_PROMISE_20271:
+               case PCI_DEVICE_ID_PROMISE_20269:
+                       mode = 4;
+                       break;
+               case PCI_DEVICE_ID_PROMISE_20270:
+               case PCI_DEVICE_ID_PROMISE_20268:
+                       mode = 3;
+                       break;
+               default:
+                       return 0;
+       }
+
+       return mode;
+}
+
+/**
+ * get_indexed_reg - Get indexed register
+ * @hwif: for the port address
+ * @index: index of the indexed register
+ */
+static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
+{
+       u8 value;
+
+       outb(index, hwif->dma_base + 1);
+       value = inb(hwif->dma_base + 3);
+
+       DBG("index[%02X] value[%02X]\n", index, value);
+       return value;
+}
+
+/**
+ * set_indexed_reg - Set indexed register
+ * @hwif: for the port address
+ * @index: index of the indexed register
+ */
+static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
+{
+       outb(index, hwif->dma_base + 1);
+       outb(value, hwif->dma_base + 3);
+       DBG("index[%02X] value[%02X]\n", index, value);
+}
+
+/*
+ * ATA Timing Tables based on 133 MHz PLL output clock.
+ *
+ * If the PLL outputs 100 MHz clock, the ASIC hardware will set
+ * the timing registers automatically when "set features" command is
+ * issued to the device. However, if the PLL output clock is 133 MHz,
+ * the following tables must be used.
+ */
+static struct pio_timing {
+       u8 reg0c, reg0d, reg13;
+} pio_timings [] = {
+       { 0xfb, 0x2b, 0xac },   /* PIO mode 0, IORDY off, Prefetch off */
+       { 0x46, 0x29, 0xa4 },   /* PIO mode 1, IORDY off, Prefetch off */
+       { 0x23, 0x26, 0x64 },   /* PIO mode 2, IORDY off, Prefetch off */
+       { 0x27, 0x0d, 0x35 },   /* PIO mode 3, IORDY on,  Prefetch off */
+       { 0x23, 0x09, 0x25 },   /* PIO mode 4, IORDY on,  Prefetch off */
+};
+
+static struct mwdma_timing {
+       u8 reg0e, reg0f;
+} mwdma_timings [] = {
+       { 0xdf, 0x5f },         /* MWDMA mode 0 */
+       { 0x6b, 0x27 },         /* MWDMA mode 1 */
+       { 0x69, 0x25 },         /* MWDMA mode 2 */
+};
+
+static struct udma_timing {
+       u8 reg10, reg11, reg12;
+} udma_timings [] = {
+       { 0x4a, 0x0f, 0xd5 },   /* UDMA mode 0 */
+       { 0x3a, 0x0a, 0xd0 },   /* UDMA mode 1 */
+       { 0x2a, 0x07, 0xcd },   /* UDMA mode 2 */
+       { 0x1a, 0x05, 0xcd },   /* UDMA mode 3 */
+       { 0x1a, 0x03, 0xcd },   /* UDMA mode 4 */
+       { 0x1a, 0x02, 0xcb },   /* UDMA mode 5 */
+       { 0x1a, 0x01, 0xcb },   /* UDMA mode 6 */
+};
+
+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;
+
+       /*
+        * 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.
+        *
+        * 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(dev) == 4) {
+               u8 mode = speed & 0x07;
+
+               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 */
+               u8 tmp = get_indexed_reg(hwif, 0x10 + adj);
+
+               set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
+       }
+}
+
+static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 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)
+{
+       if (get_indexed_reg(hwif, 0x0b) & 0x04)
+               return ATA_CBL_PATA40;
+       else
+               return ATA_CBL_PATA80;
+}
+
+static void pdcnew_quirkproc(ide_drive_t *drive)
+{
+       const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
+
+       for (list = pdc_quirk_drives; *list != NULL; list++)
+               if (strstr(m, *list) != NULL) {
+                       drive->quirk_list = 2;
+                       return;
+               }
+
+       drive->quirk_list = 0;
+}
+
+static void pdcnew_reset(ide_drive_t *drive)
+{
+       /*
+        * Deleted this because it is redundant from the caller.
+        */
+       printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",
+               HWIF(drive)->channel ? "Secondary" : "Primary");
+}
+
+/**
+ * read_counter - Read the byte count registers
+ * @dma_base: for the port address
+ */
+static long read_counter(u32 dma_base)
+{
+       u32  pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
+       u8   cnt0, cnt1, cnt2, cnt3;
+       long count = 0, last;
+       int  retry = 3;
+
+       do {
+               last = count;
+
+               /* Read the current count */
+               outb(0x20, pri_dma_base + 0x01);
+               cnt0 = inb(pri_dma_base + 0x03);
+               outb(0x21, pri_dma_base + 0x01);
+               cnt1 = inb(pri_dma_base + 0x03);
+               outb(0x20, sec_dma_base + 0x01);
+               cnt2 = inb(sec_dma_base + 0x03);
+               outb(0x21, sec_dma_base + 0x01);
+               cnt3 = inb(sec_dma_base + 0x03);
+
+               count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0;
+
+               /*
+                * The 30-bit decrementing counter is read in 4 pieces.
+                * Incorrect value may be read when the most significant bytes
+                * are changing...
+                */
+       } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count));
+
+       DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n",
+                 cnt0, cnt1, cnt2, cnt3);
+
+       return count;
+}
+
+/**
+ * detect_pll_input_clock - Detect the PLL input clock in Hz.
+ * @dma_base: for the port address
+ * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
+ */
+static long detect_pll_input_clock(unsigned long dma_base)
+{
+       struct timeval start_time, end_time;
+       long start_count, end_count;
+       long pll_input, usec_elapsed;
+       u8 scr1;
+
+       start_count = read_counter(dma_base);
+       do_gettimeofday(&start_time);
+
+       /* Start the test mode */
+       outb(0x01, dma_base + 0x01);
+       scr1 = inb(dma_base + 0x03);
+       DBG("scr1[%02X]\n", scr1);
+       outb(scr1 | 0x40, dma_base + 0x03);
+
+       /* Let the counter run for 10 ms. */
+       mdelay(10);
+
+       end_count = read_counter(dma_base);
+       do_gettimeofday(&end_time);
+
+       /* Stop the test mode */
+       outb(0x01, dma_base + 0x01);
+       scr1 = inb(dma_base + 0x03);
+       DBG("scr1[%02X]\n", scr1);
+       outb(scr1 & ~0x40, dma_base + 0x03);
+
+       /*
+        * Calculate the input clock in Hz
+        * (the clock counter is 30 bit wide and counts down)
+        */
+       usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
+               (end_time.tv_usec - start_time.tv_usec);
+       pll_input = ((start_count - end_count) & 0x3fffffff) / 10 *
+               (10000000 / usec_elapsed);
+
+       DBG("start[%ld] end[%ld]\n", start_count, end_count);
+
+       return pll_input;
+}
+
+#ifdef CONFIG_PPC_PMAC
+static void apple_kiwi_init(struct pci_dev *pdev)
+{
+       struct device_node *np = pci_device_to_OF_node(pdev);
+       u8 conf;
+
+       if (np == NULL || !of_device_is_compatible(np, "kiwi-root"))
+               return;
+
+       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));
+       }
+}
+#endif /* CONFIG_PPC_PMAC */
+
+static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
+{
+       const char *name = DRV_NAME;
+       unsigned long dma_base = pci_resource_start(dev, 4);
+       unsigned long sec_dma_base = dma_base + 0x08;
+       long pll_input, pll_output, ratio;
+       int f, r;
+       u8 pll_ctl0, pll_ctl1;
+
+       if (dma_base == 0)
+               return -EFAULT;
+
+#ifdef CONFIG_PPC_PMAC
+       apple_kiwi_init(dev);
+#endif
+
+       /* Calculate the required PLL output frequency */
+       switch(max_dma_rate(dev)) {
+               case 4: /* it's 133 MHz for Ultra133 chips */
+                       pll_output = 133333333;
+                       break;
+               case 3: /* and  100 MHz for Ultra100 chips */
+               default:
+                       pll_output = 100000000;
+                       break;
+       }
+
+       /*
+        * Detect PLL input clock.
+        * On some systems, where PCI bus is running at non-standard clock rate
+        * (e.g. 25 or 40 MHz), we have to adjust the cycle time.
+        * PDC20268 and newer chips employ PLL circuit to help correct timing
+        * registers setting.
+        */
+       pll_input = detect_pll_input_clock(dma_base);
+       printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n",
+               name, pci_name(dev), pll_input / 1000);
+
+       /* Sanity check */
+       if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
+               printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!"
+                       "\n", name, pci_name(dev), pll_input);
+               goto out;
+       }
+
+#ifdef DEBUG
+       DBG("pll_output is %ld Hz\n", pll_output);
+
+       /* Show the current clock value of PLL control register
+        * (maybe already configured by the BIOS)
+        */
+       outb(0x02, sec_dma_base + 0x01);
+       pll_ctl0 = inb(sec_dma_base + 0x03);
+       outb(0x03, sec_dma_base + 0x01);
+       pll_ctl1 = inb(sec_dma_base + 0x03);
+
+       DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+       /*
+        * Calculate the ratio of F, R and NO
+        * POUT = (F + 2) / (( R + 2) * NO)
+        */
+       ratio = pll_output / (pll_input / 1000);
+       if (ratio < 8600L) { /* 8.6x */
+               /* Using NO = 0x01, R = 0x0d */
+               r = 0x0d;
+       } else if (ratio < 12900L) { /* 12.9x */
+               /* Using NO = 0x01, R = 0x08 */
+               r = 0x08;
+       } else if (ratio < 16100L) { /* 16.1x */
+               /* Using NO = 0x01, R = 0x06 */
+               r = 0x06;
+       } else if (ratio < 64000L) { /* 64x */
+               r = 0x00;
+       } else {
+               /* Invalid ratio */
+               printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n",
+                       name, pci_name(dev), ratio);
+               goto out;
+       }
+
+       f = (ratio * (r + 2)) / 1000 - 2;
+
+       DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio);
+
+       if (unlikely(f < 0 || f > 127)) {
+               /* Invalid F */
+               printk(KERN_ERR "%s %s: F[%d] invalid!\n",
+                       name, pci_name(dev), f);
+               goto out;
+       }
+
+       pll_ctl0 = (u8) f;
+       pll_ctl1 = (u8) r;
+
+       DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+
+       outb(0x02,     sec_dma_base + 0x01);
+       outb(pll_ctl0, sec_dma_base + 0x03);
+       outb(0x03,     sec_dma_base + 0x01);
+       outb(pll_ctl1, sec_dma_base + 0x03);
+
+       /* Wait the PLL circuit to be stable */
+       mdelay(30);
+
+#ifdef DEBUG
+       /*
+        *  Show the current clock value of PLL control register
+        */
+       outb(0x02, sec_dma_base + 0x01);
+       pll_ctl0 = inb(sec_dma_base + 0x03);
+       outb(0x03, sec_dma_base + 0x01);
+       pll_ctl1 = inb(sec_dma_base + 0x03);
+
+       DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+ out:
+       return dev->irq;
+}
+
+static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
+{
+       struct pci_dev *dev2;
+
+       dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1,
+                                               PCI_FUNC(dev->devfn)));
+
+       if (dev2 &&
+           dev2->vendor == dev->vendor &&
+           dev2->device == dev->device) {
+
+               if (dev2->irq != dev->irq) {
+                       dev2->irq = dev->irq;
+                       printk(KERN_INFO DRV_NAME " %s: PCI config space "
+                               "interrupt fixed\n", pci_name(dev));
+               }
+
+               return dev2;
+       }
+
+       return NULL;
+}
+
+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,
+};
+
+#define DECLARE_PDCNEW_DEV(udma) \
+       { \
+               .name           = DRV_NAME, \
+               .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, \
+       }
+
+static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
+       /* 0: PDC202{68,70} */          DECLARE_PDCNEW_DEV(ATA_UDMA5),
+       /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
+};
+
+/**
+ *     pdc202new_init_one      -       called when a pdc202xx is found
+ *     @dev: the pdc202new device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
+       struct pci_dev *bridge = dev->bus->self;
+
+       if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && 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_pci_init_two(dev, dev2, d, NULL);
+                       if (ret < 0)
+                               pci_dev_put(dev2);
+                       return ret;
+               }
+       }
+
+       if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge &&
+           bridge->vendor == PCI_VENDOR_ID_INTEL &&
+           (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
+            bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
+               printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller,"
+                       " skipping\n", pci_name(dev));
+               return -ENODEV;
+       }
+
+       return ide_pci_init_one(dev, d, NULL);
+}
+
+static void __devexit pdc202new_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+       ide_pci_remove(dev);
+       pci_dev_put(dev2);
+}
+
+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), 0 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
+
+static struct pci_driver pdc202new_pci_driver = {
+       .name           = "Promise_IDE",
+       .id_table       = pdc202new_pci_tbl,
+       .probe          = pdc202new_init_one,
+       .remove         = __devexit_p(pdc202new_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init pdc202new_ide_init(void)
+{
+       return ide_pci_register_driver(&pdc202new_pci_driver);
+}
+
+static void __exit pdc202new_ide_exit(void)
+{
+       pci_unregister_driver(&pdc202new_pci_driver);
+}
+
+module_init(pdc202new_ide_init);
+module_exit(pdc202new_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
+MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
new file mode 100644 (file)
index 0000000..799557c
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ *  Copyright (C) 1998-2002            Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2006-2007            MontaVista Software, Inc.
+ *  Copyright (C) 2007                 Bartlomiej Zolnierkiewicz
+ *
+ *  Portions Copyright (C) 1999 Promise Technology, Inc.
+ *  Author: Frank Tiernan (frankt@promise.com)
+ *  Released under terms of General Public License
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "pdc202xx_old"
+
+#define PDC202XX_DEBUG_DRIVE_INFO      0
+
+static const char *pdc_quirk_drives[] = {
+       "QUANTUM FIREBALLlct08 08",
+       "QUANTUM FIREBALLP KA6.4",
+       "QUANTUM FIREBALLP KA9.1",
+       "QUANTUM FIREBALLP LM20.4",
+       "QUANTUM FIREBALLP KX13.6",
+       "QUANTUM FIREBALLP KX20.5",
+       "QUANTUM FIREBALLP KX27.3",
+       "QUANTUM FIREBALLP LM20.5",
+       NULL
+};
+
+static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
+
+static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u8 drive_pci            = 0x60 + (drive->dn << 2);
+
+       u8                      AP = 0, BP = 0, CP = 0;
+       u8                      TA = 0, TB = 0, TC = 0;
+
+#if PDC202XX_DEBUG_DRIVE_INFO
+       u32                     drive_conf = 0;
+       pci_read_config_dword(dev, drive_pci, &drive_conf);
+#endif
+
+       /*
+        * TODO: do this once per channel
+        */
+       if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
+               pdc_old_disable_66MHz_clock(hwif);
+
+       pci_read_config_byte(dev, drive_pci,     &AP);
+       pci_read_config_byte(dev, drive_pci + 1, &BP);
+       pci_read_config_byte(dev, drive_pci + 2, &CP);
+
+       switch(speed) {
+               case XFER_UDMA_5:
+               case XFER_UDMA_4:       TB = 0x20; TC = 0x01; break;
+               case XFER_UDMA_2:       TB = 0x20; TC = 0x01; break;
+               case XFER_UDMA_3:
+               case XFER_UDMA_1:       TB = 0x40; TC = 0x02; break;
+               case XFER_UDMA_0:
+               case XFER_MW_DMA_2:     TB = 0x60; TC = 0x03; break;
+               case XFER_MW_DMA_1:     TB = 0x60; TC = 0x04; break;
+               case XFER_MW_DMA_0:     TB = 0xE0; TC = 0x0F; break;
+               case XFER_PIO_4:        TA = 0x01; TB = 0x04; break;
+               case XFER_PIO_3:        TA = 0x02; TB = 0x06; break;
+               case XFER_PIO_2:        TA = 0x03; TB = 0x08; break;
+               case XFER_PIO_1:        TA = 0x05; TB = 0x0C; break;
+               case XFER_PIO_0:
+               default:                TA = 0x09; TB = 0x13; break;
+       }
+
+       if (speed < XFER_SW_DMA_0) {
+               /*
+                * preserve SYNC_INT / ERDDY_EN bits while clearing
+                * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
+                */
+               AP &= ~0x3f;
+               if (ata_id_iordy_disable(drive->id))
+                       AP |= 0x20;     /* set IORDY_EN bit */
+               if (drive->media == ide_disk)
+                       AP |= 0x10;     /* set Prefetch_EN bit */
+               /* clear PB[4:0] bits of register B */
+               BP &= ~0x1f;
+               pci_write_config_byte(dev, drive_pci,     AP | TA);
+               pci_write_config_byte(dev, drive_pci + 1, BP | TB);
+       } else {
+               /* clear MB[2:0] bits of register B */
+               BP &= ~0xe0;
+               /* clear MC[3:0] bits of register C */
+               CP &= ~0x0f;
+               pci_write_config_byte(dev, drive_pci + 1, BP | TB);
+               pci_write_config_byte(dev, drive_pci + 2, CP | TC);
+       }
+
+#if PDC202XX_DEBUG_DRIVE_INFO
+       printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
+               drive->name, ide_xfer_verbose(speed),
+               drive->dn, drive_conf);
+       pci_read_config_dword(dev, drive_pci, &drive_conf);
+       printk("0x%08x\n", drive_conf);
+#endif
+}
+
+static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
+}
+
+static u8 pdc2026x_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
+
+       pci_read_config_word(dev, 0x50, &CIS);
+
+       return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+/*
+ * Set the control register to use the 66MHz system
+ * clock for UDMA 3/4/5 mode operation when necessary.
+ *
+ * FIXME: this register is shared by both channels, some locking is needed
+ *
+ * It may also be possible to leave the 66MHz clock on
+ * and readjust the timing parameters.
+ */
+static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
+{
+       unsigned long clock_reg = hwif->extra_base + 0x01;
+       u8 clock = inb(clock_reg);
+
+       outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
+}
+
+static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
+{
+       unsigned long clock_reg = hwif->extra_base + 0x01;
+       u8 clock = inb(clock_reg);
+
+       outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
+}
+
+static void pdc202xx_quirkproc(ide_drive_t *drive)
+{
+       const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
+
+       for (list = pdc_quirk_drives; *list != NULL; list++)
+               if (strstr(m, *list) != NULL) {
+                       drive->quirk_list = 2;
+                       return;
+               }
+
+       drive->quirk_list = 0;
+}
+
+static void pdc202xx_dma_start(ide_drive_t *drive)
+{
+       if (drive->current_speed > XFER_UDMA_2)
+               pdc_old_enable_66MHz_clock(drive->hwif);
+       if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
+               struct request *rq      = HWGROUP(drive)->rq;
+               ide_hwif_t *hwif        = HWIF(drive);
+               unsigned long high_16   = hwif->extra_base - 16;
+               unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
+               u32 word_count  = 0;
+               u8 clock = inb(high_16 + 0x11);
+
+               outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
+               word_count = (rq->nr_sectors << 8);
+               word_count = (rq_data_dir(rq) == READ) ?
+                                       word_count | 0x05000000 :
+                                       word_count | 0x06000000;
+               outl(word_count, atapi_reg);
+       }
+       ide_dma_start(drive);
+}
+
+static int pdc202xx_dma_end(ide_drive_t *drive)
+{
+       if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
+               ide_hwif_t *hwif        = HWIF(drive);
+               unsigned long high_16   = hwif->extra_base - 16;
+               unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
+               u8 clock                = 0;
+
+               outl(0, atapi_reg); /* zero out extra */
+               clock = inb(high_16 + 0x11);
+               outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
+       }
+       if (drive->current_speed > XFER_UDMA_2)
+               pdc_old_disable_66MHz_clock(drive->hwif);
+       return ide_dma_end(drive);
+}
+
+static int pdc202xx_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       unsigned long high_16   = hwif->extra_base - 16;
+       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
+       u8 sc1d                 = inb(high_16 + 0x001d);
+
+       if (hwif->channel) {
+               /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
+               if ((sc1d & 0x50) == 0x50)
+                       goto somebody_else;
+               else if ((sc1d & 0x40) == 0x40)
+                       return (dma_stat & 4) == 4;
+       } else {
+               /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */
+               if ((sc1d & 0x05) == 0x05)
+                       goto somebody_else;
+               else if ((sc1d & 0x04) == 0x04)
+                       return (dma_stat & 4) == 4;
+       }
+somebody_else:
+       return (dma_stat & 4) == 4;     /* return 1 if INTR asserted */
+}
+
+static void pdc202xx_reset_host (ide_hwif_t *hwif)
+{
+       unsigned long high_16   = hwif->extra_base - 16;
+       u8 udma_speed_flag      = inb(high_16 | 0x001f);
+
+       outb(udma_speed_flag | 0x10, high_16 | 0x001f);
+       mdelay(100);
+       outb(udma_speed_flag & ~0x10, high_16 | 0x001f);
+       mdelay(2000);   /* 2 seconds ?! */
+
+       printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
+               hwif->channel ? "Secondary" : "Primary");
+}
+
+static void pdc202xx_reset (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwif_t *mate        = hwif->mate;
+
+       pdc202xx_reset_host(hwif);
+       pdc202xx_reset_host(mate);
+
+       ide_set_max_pio(drive);
+}
+
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
+{
+       pdc202xx_reset(drive);
+       ide_dma_lost_irq(drive);
+}
+
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
+{
+       pdc202xx_reset(drive);
+       ide_dma_timeout(drive);
+}
+
+static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
+{
+       unsigned long dmabase = pci_resource_start(dev, 4);
+       u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
+
+       if (dmabase == 0)
+               goto out;
+
+       udma_speed_flag = inb(dmabase | 0x1f);
+       primary_mode    = inb(dmabase | 0x1a);
+       secondary_mode  = inb(dmabase | 0x1b);
+       printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
+               "Primary %s Mode " \
+               "Secondary %s Mode.\n", pci_name(dev),
+               (udma_speed_flag & 1) ? "EN" : "DIS",
+               (primary_mode & 1) ? "MASTER" : "PCI",
+               (secondary_mode & 1) ? "MASTER" : "PCI" );
+
+       if (!(udma_speed_flag & 1)) {
+               printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
+                       pci_name(dev), udma_speed_flag,
+                       (udma_speed_flag|1));
+               outb(udma_speed_flag | 1, dmabase | 0x1f);
+               printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
+       }
+out:
+       return dev->irq;
+}
+
+static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+                                          const char *name)
+{
+       if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
+               u8 irq = 0, irq2 = 0;
+               pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+               /* 0xbc */
+               pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);
+               if (irq != irq2) {
+                       pci_write_config_byte(dev,
+                               (PCI_INTERRUPT_LINE)|0x80, irq);     /* 0xbc */
+                       printk(KERN_INFO "%s %s: PCI config space interrupt "
+                               "mirror fixed\n", name, pci_name(dev));
+               }
+       }
+}
+
+#define IDE_HFLAGS_PDC202XX \
+       (IDE_HFLAG_ERROR_STOPS_FIFO | \
+        IDE_HFLAG_OFF_BOARD)
+
+static const struct ide_port_ops pdc20246_port_ops = {
+       .set_pio_mode           = pdc202xx_set_pio_mode,
+       .set_dma_mode           = pdc202xx_set_mode,
+       .quirkproc              = pdc202xx_quirkproc,
+};
+
+static const struct ide_port_ops pdc2026x_port_ops = {
+       .set_pio_mode           = pdc202xx_set_pio_mode,
+       .set_dma_mode           = pdc202xx_set_mode,
+       .quirkproc              = pdc202xx_quirkproc,
+       .resetproc              = pdc202xx_reset,
+       .cable_detect           = pdc2026x_cable_detect,
+};
+
+static const struct ide_dma_ops pdc20246_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           = pdc202xx_dma_test_irq,
+       .dma_lost_irq           = pdc202xx_dma_lost_irq,
+       .dma_timeout            = pdc202xx_dma_timeout,
+};
+
+static const struct ide_dma_ops pdc2026x_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = pdc202xx_dma_start,
+       .dma_end                = pdc202xx_dma_end,
+       .dma_test_irq           = pdc202xx_dma_test_irq,
+       .dma_lost_irq           = pdc202xx_dma_lost_irq,
+       .dma_timeout            = pdc202xx_dma_timeout,
+};
+
+#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
+       { \
+               .name           = DRV_NAME, \
+               .init_chipset   = init_chipset_pdc202xx, \
+               .port_ops       = &pdc2026x_port_ops, \
+               .dma_ops        = &pdc2026x_dma_ops, \
+               .host_flags     = IDE_HFLAGS_PDC202XX | extra_flags, \
+               .pio_mask       = ATA_PIO4, \
+               .mwdma_mask     = ATA_MWDMA2, \
+               .udma_mask      = udma, \
+       }
+
+static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
+       {       /* 0: PDC20246 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_pdc202xx,
+               .port_ops       = &pdc20246_port_ops,
+               .dma_ops        = &pdc20246_dma_ops,
+               .host_flags     = IDE_HFLAGS_PDC202XX,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA2,
+       },
+
+       /* 1: PDC2026{2,3} */
+       DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
+       /* 2: PDC2026{5,7} */
+       DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
+};
+
+/**
+ *     pdc202xx_init_one       -       called when a PDC202xx is found
+ *     @dev: the pdc202xx device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       const struct ide_port_info *d;
+       u8 idx = id->driver_data;
+
+       d = &pdc202xx_chipsets[idx];
+
+       if (idx < 2)
+               pdc202ata4_fixup_irq(dev, d->name);
+
+       if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) {
+               struct pci_dev *bridge = dev->bus->self;
+
+               if (bridge &&
+                   bridge->vendor == PCI_VENDOR_ID_INTEL &&
+                   (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
+                    bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
+                       printk(KERN_INFO DRV_NAME " %s: skipping Promise "
+                               "PDC20265 attached to I2O RAID controller\n",
+                               pci_name(dev));
+                       return -ENODEV;
+               }
+       }
+
+       return ide_pci_init_one(dev, d, NULL);
+}
+
+static const struct pci_device_id pdc202xx_pci_tbl[] = {
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 },
+       { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
+
+static struct pci_driver pdc202xx_pci_driver = {
+       .name           = "Promise_Old_IDE",
+       .id_table       = pdc202xx_pci_tbl,
+       .probe          = pdc202xx_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init pdc202xx_ide_init(void)
+{
+       return ide_pci_register_driver(&pdc202xx_pci_driver);
+}
+
+static void __exit pdc202xx_ide_exit(void)
+{
+       pci_unregister_driver(&pdc202xx_pci_driver);
+}
+
+module_init(pdc202xx_ide_init);
+module_exit(pdc202xx_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
+MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
new file mode 100644 (file)
index 0000000..d63f9fd
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ *
+ * Documentation:
+ *
+ *     Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ *     PIIX4    errata #9      - Only on ultra obscure hw
+ *     ICH3     errata #13     - Not observed to affect real hw
+ *                               by Intel
+ *
+ * Things we must deal with
+ *     PIIX4   errata #10      - BM IDE hang with non UDMA
+ *                               (must stop/start dma to recover)
+ *     440MX   errata #15      - As PIIX4 errata #10
+ *     PIIX4   errata #15      - Must not read control registers
+ *                               during a PIO transfer
+ *     440MX   errata #13      - As PIIX4 errata #15
+ *     ICH2    errata #21      - DMA mode 0 doesn't work right
+ *     ICH0/1  errata #55      - As ICH2 errata #21
+ *     ICH2    spec c #9       - Extra operations needed to handle
+ *                               drive hotswap [NOT YET SUPPORTED]
+ *     ICH2    spec c #20      - IDE PRD must not cross a 64K boundary
+ *                               and must be dword aligned
+ *     ICH2    spec c #24      - UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ *     450NX:  errata #19      - DMA hangs on old 450NX
+ *     450NX:  errata #20      - DMA hangs on old 450NX
+ *     450NX:  errata #25      - Corruption with DMA on old 450NX
+ *     ICH3    errata #15      - IDE deadlock under high load
+ *                               (BIOS must set dev 31 fn 0 bit 23)
+ *     ICH3    errata #18      - Don't use native mode
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "piix"
+
+static int no_piix_dma;
+
+/**
+ *     piix_set_pio_mode       -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Set the interface PIO mode based upon the settings done by AMI BIOS.
+ */
+
+static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       int is_slave            = drive->dn & 1;
+       int master_port         = hwif->channel ? 0x42 : 0x40;
+       int slave_port          = 0x44;
+       unsigned long flags;
+       u16 master_data;
+       u8 slave_data;
+       static DEFINE_SPINLOCK(tune_lock);
+       int control = 0;
+
+                                    /* ISP  RTC */
+       static const u8 timings[][2]= {
+                                       { 0, 0 },
+                                       { 0, 0 },
+                                       { 1, 0 },
+                                       { 2, 1 },
+                                       { 2, 3 }, };
+
+       /*
+        * Master vs slave is synchronized above us but the slave register is
+        * shared by the two hwifs so the corner case of two slave timeouts in
+        * parallel must be locked.
+        */
+       spin_lock_irqsave(&tune_lock, flags);
+       pci_read_config_word(dev, master_port, &master_data);
+
+       if (pio > 1)
+               control |= 1;   /* Programmable timing on */
+       if (drive->media == ide_disk)
+               control |= 4;   /* Prefetch, post write */
+       if (pio > 2)
+               control |= 2;   /* IORDY */
+       if (is_slave) {
+               master_data |=  0x4000;
+               master_data &= ~0x0070;
+               if (pio > 1) {
+                       /* Set PPE, IE and TIME */
+                       master_data |= control << 4;
+               }
+               pci_read_config_byte(dev, slave_port, &slave_data);
+               slave_data &= hwif->channel ? 0x0f : 0xf0;
+               slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
+                              (hwif->channel ? 4 : 0);
+       } else {
+               master_data &= ~0x3307;
+               if (pio > 1) {
+                       /* enable PPE, IE and TIME */
+                       master_data |= control;
+               }
+               master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
+       }
+       pci_write_config_word(dev, master_port, master_data);
+       if (is_slave)
+               pci_write_config_byte(dev, slave_port, slave_data);
+       spin_unlock_irqrestore(&tune_lock, flags);
+}
+
+/**
+ *     piix_set_dma_mode       -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Set a PIIX host controller to the desired DMA mode.  This involves
+ *     programming the right timing data into the PCI configuration space.
+ */
+
+static void piix_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 maslave              = hwif->channel ? 0x42 : 0x40;
+       int a_speed             = 3 << (drive->dn * 4);
+       int u_flag              = 1 << drive->dn;
+       int v_flag              = 0x01 << drive->dn;
+       int w_flag              = 0x10 << drive->dn;
+       int u_speed             = 0;
+       int                     sitre;
+       u16                     reg4042, reg4a;
+       u8                      reg48, reg54, reg55;
+
+       pci_read_config_word(dev, maslave, &reg4042);
+       sitre = (reg4042 & 0x4000) ? 1 : 0;
+       pci_read_config_byte(dev, 0x48, &reg48);
+       pci_read_config_word(dev, 0x4a, &reg4a);
+       pci_read_config_byte(dev, 0x54, &reg54);
+       pci_read_config_byte(dev, 0x55, &reg55);
+
+       if (speed >= XFER_UDMA_0) {
+               u8 udma = speed - XFER_UDMA_0;
+
+               u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
+
+               if (!(reg48 & u_flag))
+                       pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+               if (speed == XFER_UDMA_5) {
+                       pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+               } else {
+                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+               }
+               if ((reg4a & a_speed) != u_speed)
+                       pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+               if (speed > XFER_UDMA_2) {
+                       if (!(reg54 & v_flag))
+                               pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+               } else
+                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+       } else {
+               const u8 mwdma_to_pio[] = { 0, 3, 4 };
+               u8 pio;
+
+               if (reg48 & u_flag)
+                       pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+               if (reg4a & a_speed)
+                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+               if (reg54 & v_flag)
+                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+               if (reg55 & w_flag)
+                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+
+               if (speed >= XFER_MW_DMA_0)
+                       pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+               else
+                       pio = 2; /* only SWDMA2 is allowed */
+
+               piix_set_pio_mode(drive, pio);
+       }
+}
+
+/**
+ *     init_chipset_ich        -       set up the ICH chipset
+ *     @dev: PCI device to set up
+ *
+ *     Initialize the PCI device as required.  For the ICH this turns
+ *     out to be nice and simple.
+ */
+
+static unsigned int init_chipset_ich(struct pci_dev *dev)
+{
+       u32 extra = 0;
+
+       pci_read_config_dword(dev, 0x54, &extra);
+       pci_write_config_dword(dev, 0x54, extra | 0x400);
+
+       return 0;
+}
+
+/**
+ *     ich_clear_irq   -       clear BMDMA status
+ *     @drive: IDE drive
+ *
+ *     ICHx contollers set DMA INTR no matter DMA or PIO.
+ *     BMDMA status might need to be cleared even for
+ *     PIO interrupts to prevent spurious/lost IRQ.
+ */
+static void ich_clear_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u8 dma_stat;
+
+       /*
+        * ide_dma_end() needs BMDMA status for error checking.
+        * So, skip clearing BMDMA status here and leave it
+        * to ide_dma_end() if this is DMA interrupt.
+        */
+       if (drive->waiting_for_dma || hwif->dma_base == 0)
+               return;
+
+       /* clear the INTR & ERROR bits */
+       dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
+       /* Should we force the bit as well ? */
+       outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
+}
+
+struct ich_laptop {
+       u16 device;
+       u16 subvendor;
+       u16 subdevice;
+};
+
+/*
+ *     List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+       /* devid, subvendor, subdev */
+       { 0x27DF, 0x1025, 0x0102 },     /* ICH7 on Acer 5602aWLMi */
+       { 0x27DF, 0x0005, 0x0280 },     /* ICH7 on Acer 5602WLMi */
+       { 0x27DF, 0x1025, 0x0110 },     /* ICH7 on Acer 3682WLMi */
+       { 0x27DF, 0x1043, 0x1267 },     /* ICH7 on Asus W5F */
+       { 0x27DF, 0x103C, 0x30A1 },     /* ICH7 on HP Compaq nc2400 */
+       { 0x27DF, 0x1071, 0xD221 },     /* ICH7 on Hercules EC-900 */
+       { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on Acer Aspire 2023WLMi */
+       { 0x2653, 0x1043, 0x82D8 },     /* ICH6M on Asus Eee 701 */
+       /* end marker */
+       { 0, }
+};
+
+static u8 piix_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       const struct ich_laptop *lap = &ich_laptop[0];
+       u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
+
+       /* check for specials */
+       while (lap->device) {
+               if (lap->device == pdev->device &&
+                   lap->subvendor == pdev->subsystem_vendor &&
+                   lap->subdevice == pdev->subsystem_device) {
+                       return ATA_CBL_PATA40_SHORT;
+               }
+               lap++;
+       }
+
+       pci_read_config_byte(pdev, 0x54, &reg54h);
+
+       return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+}
+
+/**
+ *     init_hwif_piix          -       fill in the hwif for the PIIX
+ *     @hwif: IDE interface
+ *
+ *     Set up the ide_hwif_t for the PIIX interface according to the
+ *     capabilities of the hardware.
+ */
+
+static void __devinit init_hwif_piix(ide_hwif_t *hwif)
+{
+       if (!hwif->dma_base)
+               return;
+
+       if (no_piix_dma)
+               hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+}
+
+static const struct ide_port_ops piix_port_ops = {
+       .set_pio_mode           = piix_set_pio_mode,
+       .set_dma_mode           = piix_set_dma_mode,
+       .cable_detect           = piix_cable_detect,
+};
+
+static const struct ide_port_ops ich_port_ops = {
+       .set_pio_mode           = piix_set_pio_mode,
+       .set_dma_mode           = piix_set_dma_mode,
+       .clear_irq              = ich_clear_irq,
+       .cable_detect           = piix_cable_detect,
+};
+
+#ifndef CONFIG_IA64
+ #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
+#else
+ #define IDE_HFLAGS_PIIX 0
+#endif
+
+#define DECLARE_PIIX_DEV(udma) \
+       {                                               \
+               .name           = DRV_NAME,             \
+               .init_hwif      = init_hwif_piix,       \
+               .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
+               .port_ops       = &piix_port_ops,       \
+               .host_flags     = IDE_HFLAGS_PIIX,      \
+               .pio_mask       = ATA_PIO4,             \
+               .swdma_mask     = ATA_SWDMA2_ONLY,      \
+               .mwdma_mask     = ATA_MWDMA12_ONLY,     \
+               .udma_mask      = udma,                 \
+       }
+
+#define DECLARE_ICH_DEV(udma) \
+       { \
+               .name           = DRV_NAME, \
+               .init_chipset   = init_chipset_ich, \
+               .init_hwif      = init_hwif_piix, \
+               .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
+               .port_ops       = &ich_port_ops, \
+               .host_flags     = IDE_HFLAGS_PIIX, \
+               .pio_mask       = ATA_PIO4, \
+               .swdma_mask     = ATA_SWDMA2_ONLY, \
+               .mwdma_mask     = ATA_MWDMA12_ONLY, \
+               .udma_mask      = udma, \
+       }
+
+static const struct ide_port_info piix_pci_info[] __devinitdata = {
+       /* 0: MPIIX */
+       {       /*
+                * MPIIX actually has only a single IDE channel mapped to
+                * the primary or secondary ports depending on the value
+                * of the bit 14 of the IDETIM register at offset 0x6c
+                */
+               .name           = DRV_NAME,
+               .enablebits     = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
+               .host_flags     = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
+                                 IDE_HFLAGS_PIIX,
+               .pio_mask       = ATA_PIO4,
+               /* This is a painful system best to let it self tune for now */
+       },
+       /* 1: PIIXa/PIIXb/PIIX3 */
+       DECLARE_PIIX_DEV(0x00), /* no udma */
+       /* 2: PIIX4 */
+       DECLARE_PIIX_DEV(ATA_UDMA2),
+       /* 3: ICH0 */
+       DECLARE_ICH_DEV(ATA_UDMA2),
+       /* 4: ICH */
+       DECLARE_ICH_DEV(ATA_UDMA4),
+       /* 5: PIIX4 */
+       DECLARE_PIIX_DEV(ATA_UDMA4),
+       /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+       DECLARE_ICH_DEV(ATA_UDMA5),
+};
+
+/**
+ *     piix_init_one   -       called when a PIIX is found
+ *     @dev: the piix device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL);
+}
+
+/**
+ *     piix_check_450nx        -       Check for problem 450NX setup
+ *     
+ *     Check for the present of 450NX errata #19 and errata #25. If
+ *     they are found, disable use of DMA IDE
+ */
+
+static void __devinit piix_check_450nx(void)
+{
+       struct pci_dev *pdev = NULL;
+       u16 cfg;
+       while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
+       {
+               /* Look for 450NX PXB. Check for problem configurations
+                  A PCI quirk checks bit 6 already */
+               pci_read_config_word(pdev, 0x41, &cfg);
+               /* Only on the original revision: IDE DMA can hang */
+               if (pdev->revision == 0x00)
+                       no_piix_dma = 1;
+               /* On all revisions below 5 PXB bus lock must be disabled for IDE */
+               else if (cfg & (1<<14) && pdev->revision < 5)
+                       no_piix_dma = 2;
+       }
+       if(no_piix_dma)
+               printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n");
+       if(no_piix_dma == 2)
+               printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n");
+}              
+
+static const struct pci_device_id piix_pci_tbl[] = {
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0),  1 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1),  1 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX),    0 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1),  1 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB),    2 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1),  3 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1),  2 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1),  4 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1),  5 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX),    2 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1),  6 },
+#endif
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
+
+static struct pci_driver piix_pci_driver = {
+       .name           = "PIIX_IDE",
+       .id_table       = piix_pci_tbl,
+       .probe          = piix_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init piix_ide_init(void)
+{
+       piix_check_450nx();
+       return ide_pci_register_driver(&piix_pci_driver);
+}
+
+static void __exit piix_ide_exit(void)
+{
+       pci_unregister_driver(&piix_pci_driver);
+}
+
+module_init(piix_ide_init);
+module_exit(piix_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");
+MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
new file mode 100644 (file)
index 0000000..2e19d62
--- /dev/null
@@ -0,0 +1,1736 @@
+/*
+ * Support for IDE interfaces on PowerMacs.
+ *
+ * These IDE interfaces are memory-mapped and have a DBDMA channel
+ * for doing DMA.
+ *
+ *  Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt
+ *  Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ * Some code taken from drivers/ide/ide-dma.c:
+ *
+ *  Copyright (c) 1995-1998  Mark Lord
+ *
+ * TODO: - Use pre-calculated (kauai) timing tables all the time and
+ * get rid of the "rounded" tables used previously, so we have the
+ * same table format for all controllers and can then just have one
+ * big table
+ * 
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/scatterlist.h>
+
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/dbdma.h>
+#include <asm/ide.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/sections.h>
+#include <asm/irq.h>
+
+#ifndef CONFIG_PPC64
+#include <asm/mediabay.h>
+#endif
+
+#define DRV_NAME "ide-pmac"
+
+#undef IDE_PMAC_DEBUG
+
+#define DMA_WAIT_TIMEOUT       50
+
+typedef struct pmac_ide_hwif {
+       unsigned long                   regbase;
+       int                             irq;
+       int                             kind;
+       int                             aapl_bus_id;
+       unsigned                        mediabay : 1;
+       unsigned                        broken_dma : 1;
+       unsigned                        broken_dma_warn : 1;
+       struct device_node*             node;
+       struct macio_dev                *mdev;
+       u32                             timings[4];
+       volatile u32 __iomem *          *kauai_fcr;
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       /* Those fields are duplicating what is in hwif. We currently
+        * can't use the hwif ones because of some assumptions that are
+        * beeing done by the generic code about the kind of dma controller
+        * and format of the dma table. This will have to be fixed though.
+        */
+       volatile struct dbdma_regs __iomem *    dma_regs;
+       struct dbdma_cmd*               dma_table_cpu;
+#endif
+       
+} pmac_ide_hwif_t;
+
+enum {
+       controller_ohare,       /* OHare based */
+       controller_heathrow,    /* Heathrow/Paddington */
+       controller_kl_ata3,     /* KeyLargo ATA-3 */
+       controller_kl_ata4,     /* KeyLargo ATA-4 */
+       controller_un_ata6,     /* UniNorth2 ATA-6 */
+       controller_k2_ata6,     /* K2 ATA-6 */
+       controller_sh_ata6,     /* Shasta ATA-6 */
+};
+
+static const char* model_name[] = {
+       "OHare ATA",            /* OHare based */
+       "Heathrow ATA",         /* Heathrow/Paddington */
+       "KeyLargo ATA-3",       /* KeyLargo ATA-3 (MDMA only) */
+       "KeyLargo ATA-4",       /* KeyLargo ATA-4 (UDMA/66) */
+       "UniNorth ATA-6",       /* UniNorth2 ATA-6 (UDMA/100) */
+       "K2 ATA-6",             /* K2 ATA-6 (UDMA/100) */
+       "Shasta ATA-6",         /* Shasta ATA-6 (UDMA/133) */
+};
+
+/*
+ * Extra registers, both 32-bit little-endian
+ */
+#define IDE_TIMING_CONFIG      0x200
+#define IDE_INTERRUPT          0x300
+
+/* Kauai (U2) ATA has different register setup */
+#define IDE_KAUAI_PIO_CONFIG   0x200
+#define IDE_KAUAI_ULTRA_CONFIG 0x210
+#define IDE_KAUAI_POLL_CONFIG  0x220
+
+/*
+ * Timing configuration register definitions
+ */
+
+/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
+#define SYSCLK_TICKS(t)                (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
+#define SYSCLK_TICKS_66(t)     (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS)
+#define IDE_SYSCLK_NS          30      /* 33Mhz cell */
+#define IDE_SYSCLK_66_NS       15      /* 66Mhz cell */
+
+/* 133Mhz cell, found in shasta.
+ * See comments about 100 Mhz Uninorth 2...
+ * Note that PIO_MASK and MDMA_MASK seem to overlap
+ */
+#define TR_133_PIOREG_PIO_MASK         0xff000fff
+#define TR_133_PIOREG_MDMA_MASK                0x00fff800
+#define TR_133_UDMAREG_UDMA_MASK       0x0003ffff
+#define TR_133_UDMAREG_UDMA_EN         0x00000001
+
+/* 100Mhz cell, found in Uninorth 2. I don't have much infos about
+ * this one yet, it appears as a pci device (106b/0033) on uninorth
+ * internal PCI bus and it's clock is controlled like gem or fw. It
+ * appears to be an evolution of keylargo ATA4 with a timing register
+ * extended to 2 32bits registers and a similar DBDMA channel. Other
+ * registers seem to exist but I can't tell much about them.
+ * 
+ * So far, I'm using pre-calculated tables for this extracted from
+ * the values used by the MacOS X driver.
+ * 
+ * The "PIO" register controls PIO and MDMA timings, the "ULTRA"
+ * register controls the UDMA timings. At least, it seems bit 0
+ * of this one enables UDMA vs. MDMA, and bits 4..7 are the
+ * cycle time in units of 10ns. Bits 8..15 are used by I don't
+ * know their meaning yet
+ */
+#define TR_100_PIOREG_PIO_MASK         0xff000fff
+#define TR_100_PIOREG_MDMA_MASK                0x00fff000
+#define TR_100_UDMAREG_UDMA_MASK       0x0000ffff
+#define TR_100_UDMAREG_UDMA_EN         0x00000001
+
+
+/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on
+ * 40 connector cable and to 4 on 80 connector one.
+ * Clock unit is 15ns (66Mhz)
+ * 
+ * 3 Values can be programmed:
+ *  - Write data setup, which appears to match the cycle time. They
+ *    also call it DIOW setup.
+ *  - Ready to pause time (from spec)
+ *  - Address setup. That one is weird. I don't see where exactly
+ *    it fits in UDMA cycles, I got it's name from an obscure piece
+ *    of commented out code in Darwin. They leave it to 0, we do as
+ *    well, despite a comment that would lead to think it has a
+ *    min value of 45ns.
+ * Apple also add 60ns to the write data setup (or cycle time ?) on
+ * reads.
+ */
+#define TR_66_UDMA_MASK                        0xfff00000
+#define TR_66_UDMA_EN                  0x00100000 /* Enable Ultra mode for DMA */
+#define TR_66_UDMA_ADDRSETUP_MASK      0xe0000000 /* Address setup */
+#define TR_66_UDMA_ADDRSETUP_SHIFT     29
+#define TR_66_UDMA_RDY2PAUS_MASK       0x1e000000 /* Ready 2 pause time */
+#define TR_66_UDMA_RDY2PAUS_SHIFT      25
+#define TR_66_UDMA_WRDATASETUP_MASK    0x01e00000 /* Write data setup time */
+#define TR_66_UDMA_WRDATASETUP_SHIFT   21
+#define TR_66_MDMA_MASK                        0x000ffc00
+#define TR_66_MDMA_RECOVERY_MASK       0x000f8000
+#define TR_66_MDMA_RECOVERY_SHIFT      15
+#define TR_66_MDMA_ACCESS_MASK         0x00007c00
+#define TR_66_MDMA_ACCESS_SHIFT                10
+#define TR_66_PIO_MASK                 0x000003ff
+#define TR_66_PIO_RECOVERY_MASK                0x000003e0
+#define TR_66_PIO_RECOVERY_SHIFT       5
+#define TR_66_PIO_ACCESS_MASK          0x0000001f
+#define TR_66_PIO_ACCESS_SHIFT         0
+
+/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo
+ * Can do pio & mdma modes, clock unit is 30ns (33Mhz)
+ * 
+ * The access time and recovery time can be programmed. Some older
+ * Darwin code base limit OHare to 150ns cycle time. I decided to do
+ * the same here fore safety against broken old hardware ;)
+ * The HalfTick bit, when set, adds half a clock (15ns) to the access
+ * time and removes one from recovery. It's not supported on KeyLargo
+ * implementation afaik. The E bit appears to be set for PIO mode 0 and
+ * is used to reach long timings used in this mode.
+ */
+#define TR_33_MDMA_MASK                        0x003ff800
+#define TR_33_MDMA_RECOVERY_MASK       0x001f0000
+#define TR_33_MDMA_RECOVERY_SHIFT      16
+#define TR_33_MDMA_ACCESS_MASK         0x0000f800
+#define TR_33_MDMA_ACCESS_SHIFT                11
+#define TR_33_MDMA_HALFTICK            0x00200000
+#define TR_33_PIO_MASK                 0x000007ff
+#define TR_33_PIO_E                    0x00000400
+#define TR_33_PIO_RECOVERY_MASK                0x000003e0
+#define TR_33_PIO_RECOVERY_SHIFT       5
+#define TR_33_PIO_ACCESS_MASK          0x0000001f
+#define TR_33_PIO_ACCESS_SHIFT         0
+
+/*
+ * Interrupt register definitions
+ */
+#define IDE_INTR_DMA                   0x80000000
+#define IDE_INTR_DEVICE                        0x40000000
+
+/*
+ * FCR Register on Kauai. Not sure what bit 0x4 is  ...
+ */
+#define KAUAI_FCR_UATA_MAGIC           0x00000004
+#define KAUAI_FCR_UATA_RESET_N         0x00000002
+#define KAUAI_FCR_UATA_ENABLE          0x00000001
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+
+/* Rounded Multiword DMA timings
+ * 
+ * I gave up finding a generic formula for all controller
+ * types and instead, built tables based on timing values
+ * used by Apple in Darwin's implementation.
+ */
+struct mdma_timings_t {
+       int     accessTime;
+       int     recoveryTime;
+       int     cycleTime;
+};
+
+struct mdma_timings_t mdma_timings_33[] =
+{
+    { 240, 240, 480 },
+    { 180, 180, 360 },
+    { 135, 135, 270 },
+    { 120, 120, 240 },
+    { 105, 105, 210 },
+    {  90,  90, 180 },
+    {  75,  75, 150 },
+    {  75,  45, 120 },
+    {   0,   0,   0 }
+};
+
+struct mdma_timings_t mdma_timings_33k[] =
+{
+    { 240, 240, 480 },
+    { 180, 180, 360 },
+    { 150, 150, 300 },
+    { 120, 120, 240 },
+    {  90, 120, 210 },
+    {  90,  90, 180 },
+    {  90,  60, 150 },
+    {  90,  30, 120 },
+    {   0,   0,   0 }
+};
+
+struct mdma_timings_t mdma_timings_66[] =
+{
+    { 240, 240, 480 },
+    { 180, 180, 360 },
+    { 135, 135, 270 },
+    { 120, 120, 240 },
+    { 105, 105, 210 },
+    {  90,  90, 180 },
+    {  90,  75, 165 },
+    {  75,  45, 120 },
+    {   0,   0,   0 }
+};
+
+/* KeyLargo ATA-4 Ultra DMA timings (rounded) */
+struct {
+       int     addrSetup; /* ??? */
+       int     rdy2pause;
+       int     wrDataSetup;
+} kl66_udma_timings[] =
+{
+    {   0, 180,  120 },        /* Mode 0 */
+    {   0, 150,  90 }, /*      1 */
+    {   0, 120,  60 }, /*      2 */
+    {   0, 90,   45 }, /*      3 */
+    {   0, 90,   30 }  /*      4 */
+};
+
+/* UniNorth 2 ATA/100 timings */
+struct kauai_timing {
+       int     cycle_time;
+       u32     timing_reg;
+};
+
+static struct kauai_timing     kauai_pio_timings[] =
+{
+       { 930   , 0x08000fff },
+       { 600   , 0x08000a92 },
+       { 383   , 0x0800060f },
+       { 360   , 0x08000492 },
+       { 330   , 0x0800048f },
+       { 300   , 0x080003cf },
+       { 270   , 0x080003cc },
+       { 240   , 0x0800038b },
+       { 239   , 0x0800030c },
+       { 180   , 0x05000249 },
+       { 120   , 0x04000148 },
+       { 0     , 0 },
+};
+
+static struct kauai_timing     kauai_mdma_timings[] =
+{
+       { 1260  , 0x00fff000 },
+       { 480   , 0x00618000 },
+       { 360   , 0x00492000 },
+       { 270   , 0x0038e000 },
+       { 240   , 0x0030c000 },
+       { 210   , 0x002cb000 },
+       { 180   , 0x00249000 },
+       { 150   , 0x00209000 },
+       { 120   , 0x00148000 },
+       { 0     , 0 },
+};
+
+static struct kauai_timing     kauai_udma_timings[] =
+{
+       { 120   , 0x000070c0 },
+       { 90    , 0x00005d80 },
+       { 60    , 0x00004a60 },
+       { 45    , 0x00003a50 },
+       { 30    , 0x00002a30 },
+       { 20    , 0x00002921 },
+       { 0     , 0 },
+};
+
+static struct kauai_timing     shasta_pio_timings[] =
+{
+       { 930   , 0x08000fff },
+       { 600   , 0x0A000c97 },
+       { 383   , 0x07000712 },
+       { 360   , 0x040003cd },
+       { 330   , 0x040003cd },
+       { 300   , 0x040003cd },
+       { 270   , 0x040003cd },
+       { 240   , 0x040003cd },
+       { 239   , 0x040003cd },
+       { 180   , 0x0400028b },
+       { 120   , 0x0400010a },
+       { 0     , 0 },
+};
+
+static struct kauai_timing     shasta_mdma_timings[] =
+{
+       { 1260  , 0x00fff000 },
+       { 480   , 0x00820800 },
+       { 360   , 0x00820800 },
+       { 270   , 0x00820800 },
+       { 240   , 0x00820800 },
+       { 210   , 0x00820800 },
+       { 180   , 0x00820800 },
+       { 150   , 0x0028b000 },
+       { 120   , 0x001ca000 },
+       { 0     , 0 },
+};
+
+static struct kauai_timing     shasta_udma133_timings[] =
+{
+       { 120   , 0x00035901, },
+       { 90    , 0x000348b1, },
+       { 60    , 0x00033881, },
+       { 45    , 0x00033861, },
+       { 30    , 0x00033841, },
+       { 20    , 0x00033031, },
+       { 15    , 0x00033021, },
+       { 0     , 0 },
+};
+
+
+static inline u32
+kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
+{
+       int i;
+       
+       for (i=0; table[i].cycle_time; i++)
+               if (cycle_time > table[i+1].cycle_time)
+                       return table[i].timing_reg;
+       BUG();
+       return 0;
+}
+
+/* allow up to 256 DBDMA commands per xfer */
+#define MAX_DCMDS              256
+
+/* 
+ * Wait 1s for disk to answer on IDE bus after a hard reset
+ * of the device (via GPIO/FCR).
+ * 
+ * Some devices seem to "pollute" the bus even after dropping
+ * the BSY bit (typically some combo drives slave on the UDMA
+ * bus) after a hard reset. Since we hard reset all drives on
+ * KeyLargo ATA66, we have to keep that delay around. I may end
+ * up not hard resetting anymore on these and keep the delay only
+ * for older interfaces instead (we have to reset when coming
+ * from MacOS...) --BenH. 
+ */
+#define IDE_WAKEUP_DELAY       (1*HZ)
+
+static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *);
+static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
+static void pmac_ide_selectproc(ide_drive_t *drive);
+static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
+
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+#define PMAC_IDE_REG(x) \
+       ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x)))
+
+/*
+ * Apply the timings of the proper unit (master/slave) to the shared
+ * timing register when selecting that unit. This version is for
+ * ASICs with a single timing register
+ */
+static void
+pmac_ide_selectproc(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+       if (drive->dn & 1)
+               writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
+       else
+               writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
+       (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
+}
+
+/*
+ * Apply the timings of the proper unit (master/slave) to the shared
+ * timing register when selecting that unit. This version is for
+ * ASICs with a dual timing register (Kauai)
+ */
+static void
+pmac_ide_kauai_selectproc(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+       if (drive->dn & 1) {
+               writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+               writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
+       } else {
+               writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+               writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
+       }
+       (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+}
+
+/*
+ * Force an update of controller timing values for a given drive
+ */
+static void
+pmac_ide_do_update_timings(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+       if (pmif->kind == controller_sh_ata6 ||
+           pmif->kind == controller_un_ata6 ||
+           pmif->kind == controller_k2_ata6)
+               pmac_ide_kauai_selectproc(drive);
+       else
+               pmac_ide_selectproc(drive);
+}
+
+static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+       writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+       (void)readl((void __iomem *)(hwif->io_ports.data_addr
+                                    + IDE_TIMING_CONFIG));
+}
+
+static void pmac_set_irq(ide_hwif_t *hwif, int on)
+{
+       u8 ctl = ATA_DEVCTL_OBS;
+
+       if (on == 4) { /* hack for SRST */
+               ctl |= 4;
+               on &= ~4;
+       }
+
+       ctl |= on ? 0 : 2;
+
+       writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+       (void)readl((void __iomem *)(hwif->io_ports.data_addr
+                                    + IDE_TIMING_CONFIG));
+}
+
+/*
+ * Old tuning functions (called on hdparm -p), sets up drive PIO timings
+ */
+static void
+pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
+       u32 *timings, t;
+       unsigned accessTicks, recTicks;
+       unsigned accessTime, recTime;
+       unsigned int cycle_time;
+
+       /* which drive is it ? */
+       timings = &pmif->timings[drive->dn & 1];
+       t = *timings;
+
+       cycle_time = ide_pio_cycle_time(drive, pio);
+
+       switch (pmif->kind) {
+       case controller_sh_ata6: {
+               /* 133Mhz cell */
+               u32 tr = kauai_lookup_timing(shasta_pio_timings, cycle_time);
+               t = (t & ~TR_133_PIOREG_PIO_MASK) | tr;
+               break;
+               }
+       case controller_un_ata6:
+       case controller_k2_ata6: {
+               /* 100Mhz cell */
+               u32 tr = kauai_lookup_timing(kauai_pio_timings, cycle_time);
+               t = (t & ~TR_100_PIOREG_PIO_MASK) | tr;
+               break;
+               }
+       case controller_kl_ata4:
+               /* 66Mhz cell */
+               recTime = cycle_time - tim->active - tim->setup;
+               recTime = max(recTime, 150U);
+               accessTime = tim->active;
+               accessTime = max(accessTime, 150U);
+               accessTicks = SYSCLK_TICKS_66(accessTime);
+               accessTicks = min(accessTicks, 0x1fU);
+               recTicks = SYSCLK_TICKS_66(recTime);
+               recTicks = min(recTicks, 0x1fU);
+               t = (t & ~TR_66_PIO_MASK) |
+                       (accessTicks << TR_66_PIO_ACCESS_SHIFT) |
+                       (recTicks << TR_66_PIO_RECOVERY_SHIFT);
+               break;
+       default: {
+               /* 33Mhz cell */
+               int ebit = 0;
+               recTime = cycle_time - tim->active - tim->setup;
+               recTime = max(recTime, 150U);
+               accessTime = tim->active;
+               accessTime = max(accessTime, 150U);
+               accessTicks = SYSCLK_TICKS(accessTime);
+               accessTicks = min(accessTicks, 0x1fU);
+               accessTicks = max(accessTicks, 4U);
+               recTicks = SYSCLK_TICKS(recTime);
+               recTicks = min(recTicks, 0x1fU);
+               recTicks = max(recTicks, 5U) - 4;
+               if (recTicks > 9) {
+                       recTicks--; /* guess, but it's only for PIO0, so... */
+                       ebit = 1;
+               }
+               t = (t & ~TR_33_PIO_MASK) |
+                               (accessTicks << TR_33_PIO_ACCESS_SHIFT) |
+                               (recTicks << TR_33_PIO_RECOVERY_SHIFT);
+               if (ebit)
+                       t |= TR_33_PIO_E;
+               break;
+               }
+       }
+
+#ifdef IDE_PMAC_DEBUG
+       printk(KERN_ERR "%s: Set PIO timing for mode %d, reg: 0x%08x\n",
+               drive->name, pio,  *timings);
+#endif 
+
+       *timings = t;
+       pmac_ide_do_update_timings(drive);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+
+/*
+ * Calculate KeyLargo ATA/66 UDMA timings
+ */
+static int
+set_timings_udma_ata4(u32 *timings, u8 speed)
+{
+       unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
+
+       if (speed > XFER_UDMA_4)
+               return 1;
+
+       rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause);
+       wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup);
+       addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup);
+
+       *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) |
+                       (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | 
+                       (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) |
+                       (addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) |
+                       TR_66_UDMA_EN;
+#ifdef IDE_PMAC_DEBUG
+       printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n",
+               speed & 0xf,  *timings);
+#endif 
+
+       return 0;
+}
+
+/*
+ * Calculate Kauai ATA/100 UDMA timings
+ */
+static int
+set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
+{
+       struct ide_timing *t = ide_timing_find_mode(speed);
+       u32 tr;
+
+       if (speed > XFER_UDMA_5 || t == NULL)
+               return 1;
+       tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma);
+       *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr;
+       *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN;
+
+       return 0;
+}
+
+/*
+ * Calculate Shasta ATA/133 UDMA timings
+ */
+static int
+set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
+{
+       struct ide_timing *t = ide_timing_find_mode(speed);
+       u32 tr;
+
+       if (speed > XFER_UDMA_6 || t == NULL)
+               return 1;
+       tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma);
+       *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr;
+       *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN;
+
+       return 0;
+}
+
+/*
+ * Calculate MDMA timings for all cells
+ */
+static void
+set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
+                       u8 speed)
+{
+       u16 *id = drive->id;
+       int cycleTime, accessTime = 0, recTime = 0;
+       unsigned accessTicks, recTicks;
+       struct mdma_timings_t* tm = NULL;
+       int i;
+
+       /* Get default cycle time for mode */
+       switch(speed & 0xf) {
+               case 0: cycleTime = 480; break;
+               case 1: cycleTime = 150; break;
+               case 2: cycleTime = 120; break;
+               default:
+                       BUG();
+                       break;
+       }
+
+       /* Check if drive provides explicit DMA cycle time */
+       if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME])
+               cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime);
+
+       /* OHare limits according to some old Apple sources */  
+       if ((intf_type == controller_ohare) && (cycleTime < 150))
+               cycleTime = 150;
+       /* Get the proper timing array for this controller */
+       switch(intf_type) {
+               case controller_sh_ata6:
+               case controller_un_ata6:
+               case controller_k2_ata6:
+                       break;
+               case controller_kl_ata4:
+                       tm = mdma_timings_66;
+                       break;
+               case controller_kl_ata3:
+                       tm = mdma_timings_33k;
+                       break;
+               default:
+                       tm = mdma_timings_33;
+                       break;
+       }
+       if (tm != NULL) {
+               /* Lookup matching access & recovery times */
+               i = -1;
+               for (;;) {
+                       if (tm[i+1].cycleTime < cycleTime)
+                               break;
+                       i++;
+               }
+               cycleTime = tm[i].cycleTime;
+               accessTime = tm[i].accessTime;
+               recTime = tm[i].recoveryTime;
+
+#ifdef IDE_PMAC_DEBUG
+               printk(KERN_ERR "%s: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",
+                       drive->name, cycleTime, accessTime, recTime);
+#endif
+       }
+       switch(intf_type) {
+       case controller_sh_ata6: {
+               /* 133Mhz cell */
+               u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime);
+               *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr;
+               *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN;
+               }
+       case controller_un_ata6:
+       case controller_k2_ata6: {
+               /* 100Mhz cell */
+               u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime);
+               *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr;
+               *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN;
+               }
+               break;
+       case controller_kl_ata4:
+               /* 66Mhz cell */
+               accessTicks = SYSCLK_TICKS_66(accessTime);
+               accessTicks = min(accessTicks, 0x1fU);
+               accessTicks = max(accessTicks, 0x1U);
+               recTicks = SYSCLK_TICKS_66(recTime);
+               recTicks = min(recTicks, 0x1fU);
+               recTicks = max(recTicks, 0x3U);
+               /* Clear out mdma bits and disable udma */
+               *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) |
+                       (accessTicks << TR_66_MDMA_ACCESS_SHIFT) |
+                       (recTicks << TR_66_MDMA_RECOVERY_SHIFT);
+               break;
+       case controller_kl_ata3:
+               /* 33Mhz cell on KeyLargo */
+               accessTicks = SYSCLK_TICKS(accessTime);
+               accessTicks = max(accessTicks, 1U);
+               accessTicks = min(accessTicks, 0x1fU);
+               accessTime = accessTicks * IDE_SYSCLK_NS;
+               recTicks = SYSCLK_TICKS(recTime);
+               recTicks = max(recTicks, 1U);
+               recTicks = min(recTicks, 0x1fU);
+               *timings = ((*timings) & ~TR_33_MDMA_MASK) |
+                               (accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
+                               (recTicks << TR_33_MDMA_RECOVERY_SHIFT);
+               break;
+       default: {
+               /* 33Mhz cell on others */
+               int halfTick = 0;
+               int origAccessTime = accessTime;
+               int origRecTime = recTime;
+               
+               accessTicks = SYSCLK_TICKS(accessTime);
+               accessTicks = max(accessTicks, 1U);
+               accessTicks = min(accessTicks, 0x1fU);
+               accessTime = accessTicks * IDE_SYSCLK_NS;
+               recTicks = SYSCLK_TICKS(recTime);
+               recTicks = max(recTicks, 2U) - 1;
+               recTicks = min(recTicks, 0x1fU);
+               recTime = (recTicks + 1) * IDE_SYSCLK_NS;
+               if ((accessTicks > 1) &&
+                   ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
+                   ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) {
+                       halfTick = 1;
+                       accessTicks--;
+               }
+               *timings = ((*timings) & ~TR_33_MDMA_MASK) |
+                               (accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
+                               (recTicks << TR_33_MDMA_RECOVERY_SHIFT);
+               if (halfTick)
+                       *timings |= TR_33_MDMA_HALFTICK;
+               }
+       }
+#ifdef IDE_PMAC_DEBUG
+       printk(KERN_ERR "%s: Set MDMA timing for mode %d, reg: 0x%08x\n",
+               drive->name, speed & 0xf,  *timings);
+#endif 
+}
+#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       int ret = 0;
+       u32 *timings, *timings2, tl[2];
+       u8 unit = drive->dn & 1;
+
+       timings = &pmif->timings[unit];
+       timings2 = &pmif->timings[unit+2];
+
+       /* Copy timings to local image */
+       tl[0] = *timings;
+       tl[1] = *timings2;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       if (speed >= XFER_UDMA_0) {
+               if (pmif->kind == controller_kl_ata4)
+                       ret = set_timings_udma_ata4(&tl[0], speed);
+               else if (pmif->kind == controller_un_ata6
+                        || pmif->kind == controller_k2_ata6)
+                       ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
+               else if (pmif->kind == controller_sh_ata6)
+                       ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
+               else
+                       ret = -1;
+       } else
+               set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+       if (ret)
+               return;
+
+       /* Apply timings to controller */
+       *timings = tl[0];
+       *timings2 = tl[1];
+
+       pmac_ide_do_update_timings(drive);      
+}
+
+/*
+ * Blast some well known "safe" values to the timing registers at init or
+ * wakeup from sleep time, before we do real calculation
+ */
+static void
+sanitize_timings(pmac_ide_hwif_t *pmif)
+{
+       unsigned int value, value2 = 0;
+       
+       switch(pmif->kind) {
+               case controller_sh_ata6:
+                       value = 0x0a820c97;
+                       value2 = 0x00033031;
+                       break;
+               case controller_un_ata6:
+               case controller_k2_ata6:
+                       value = 0x08618a92;
+                       value2 = 0x00002921;
+                       break;
+               case controller_kl_ata4:
+                       value = 0x0008438c;
+                       break;
+               case controller_kl_ata3:
+                       value = 0x00084526;
+                       break;
+               case controller_heathrow:
+               case controller_ohare:
+               default:
+                       value = 0x00074526;
+                       break;
+       }
+       pmif->timings[0] = pmif->timings[1] = value;
+       pmif->timings[2] = pmif->timings[3] = value2;
+}
+
+/* Suspend call back, should be called after the child devices
+ * have actually been suspended
+ */
+static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
+{
+       /* We clear the timings */
+       pmif->timings[0] = 0;
+       pmif->timings[1] = 0;
+       
+       disable_irq(pmif->irq);
+
+       /* The media bay will handle itself just fine */
+       if (pmif->mediabay)
+               return 0;
+       
+       /* Kauai has bus control FCRs directly here */
+       if (pmif->kauai_fcr) {
+               u32 fcr = readl(pmif->kauai_fcr);
+               fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE);
+               writel(fcr, pmif->kauai_fcr);
+       }
+
+       /* Disable the bus on older machines and the cell on kauai */
+       ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id,
+                           0);
+
+       return 0;
+}
+
+/* Resume call back, should be called before the child devices
+ * are resumed
+ */
+static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
+{
+       /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
+       if (!pmif->mediabay) {
+               ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
+               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
+               msleep(10);
+               ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0);
+
+               /* Kauai has it different */
+               if (pmif->kauai_fcr) {
+                       u32 fcr = readl(pmif->kauai_fcr);
+                       fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE;
+                       writel(fcr, pmif->kauai_fcr);
+               }
+
+               msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
+       }
+
+       /* Sanitize drive timings */
+       sanitize_timings(pmif);
+
+       enable_irq(pmif->irq);
+
+       return 0;
+}
+
+static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
+{
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       struct device_node *np = pmif->node;
+       const char *cable = of_get_property(np, "cable-type", NULL);
+
+       /* Get cable type from device-tree. */
+       if (cable && !strncmp(cable, "80-", 3))
+               return ATA_CBL_PATA80;
+
+       /*
+        * G5's seem to have incorrect cable type in device-tree.
+        * Let's assume they have a 80 conductor cable, this seem
+        * to be always the case unless the user mucked around.
+        */
+       if (of_device_is_compatible(np, "K2-UATA") ||
+           of_device_is_compatible(np, "shasta-ata"))
+               return ATA_CBL_PATA80;
+
+       return ATA_CBL_PATA40;
+}
+
+static void pmac_ide_init_dev(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+       if (pmif->mediabay) {
+#ifdef CONFIG_PMAC_MEDIABAY
+               if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+                       drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
+                       return;
+               }
+#endif
+               drive->dev_flags |= IDE_DFLAG_NOPROBE;
+       }
+}
+
+static const struct ide_tp_ops pmac_tp_ops = {
+       .exec_command           = pmac_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = pmac_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
+static const struct ide_port_ops pmac_ide_ata6_port_ops = {
+       .init_dev               = pmac_ide_init_dev,
+       .set_pio_mode           = pmac_ide_set_pio_mode,
+       .set_dma_mode           = pmac_ide_set_dma_mode,
+       .selectproc             = pmac_ide_kauai_selectproc,
+       .cable_detect           = pmac_ide_cable_detect,
+};
+
+static const struct ide_port_ops pmac_ide_ata4_port_ops = {
+       .init_dev               = pmac_ide_init_dev,
+       .set_pio_mode           = pmac_ide_set_pio_mode,
+       .set_dma_mode           = pmac_ide_set_dma_mode,
+       .selectproc             = pmac_ide_selectproc,
+       .cable_detect           = pmac_ide_cable_detect,
+};
+
+static const struct ide_port_ops pmac_ide_port_ops = {
+       .init_dev               = pmac_ide_init_dev,
+       .set_pio_mode           = pmac_ide_set_pio_mode,
+       .set_dma_mode           = pmac_ide_set_dma_mode,
+       .selectproc             = pmac_ide_selectproc,
+};
+
+static const struct ide_dma_ops pmac_dma_ops;
+
+static const struct ide_port_info pmac_port_info = {
+       .name                   = DRV_NAME,
+       .init_dma               = pmac_ide_init_dma,
+       .chipset                = ide_pmac,
+       .tp_ops                 = &pmac_tp_ops,
+       .port_ops               = &pmac_ide_port_ops,
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       .dma_ops                = &pmac_dma_ops,
+#endif
+       .host_flags             = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+                                 IDE_HFLAG_POST_SET_MODE |
+                                 IDE_HFLAG_MMIO |
+                                 IDE_HFLAG_UNMASK_IRQS,
+       .pio_mask               = ATA_PIO4,
+       .mwdma_mask             = ATA_MWDMA2,
+};
+
+/*
+ * Setup, register & probe an IDE channel driven by this driver, this is
+ * called by one of the 2 probe functions (macio or PCI).
+ */
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
+{
+       struct device_node *np = pmif->node;
+       const int *bidp;
+       struct ide_host *host;
+       ide_hwif_t *hwif;
+       hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
+       struct ide_port_info d = pmac_port_info;
+       int rc;
+
+       pmif->broken_dma = pmif->broken_dma_warn = 0;
+       if (of_device_is_compatible(np, "shasta-ata")) {
+               pmif->kind = controller_sh_ata6;
+               d.port_ops = &pmac_ide_ata6_port_ops;
+               d.udma_mask = ATA_UDMA6;
+       } else if (of_device_is_compatible(np, "kauai-ata")) {
+               pmif->kind = controller_un_ata6;
+               d.port_ops = &pmac_ide_ata6_port_ops;
+               d.udma_mask = ATA_UDMA5;
+       } else if (of_device_is_compatible(np, "K2-UATA")) {
+               pmif->kind = controller_k2_ata6;
+               d.port_ops = &pmac_ide_ata6_port_ops;
+               d.udma_mask = ATA_UDMA5;
+       } else if (of_device_is_compatible(np, "keylargo-ata")) {
+               if (strcmp(np->name, "ata-4") == 0) {
+                       pmif->kind = controller_kl_ata4;
+                       d.port_ops = &pmac_ide_ata4_port_ops;
+                       d.udma_mask = ATA_UDMA4;
+               } else
+                       pmif->kind = controller_kl_ata3;
+       } else if (of_device_is_compatible(np, "heathrow-ata")) {
+               pmif->kind = controller_heathrow;
+       } else {
+               pmif->kind = controller_ohare;
+               pmif->broken_dma = 1;
+       }
+
+       bidp = of_get_property(np, "AAPL,bus-id", NULL);
+       pmif->aapl_bus_id =  bidp ? *bidp : 0;
+
+       /* On Kauai-type controllers, we make sure the FCR is correct */
+       if (pmif->kauai_fcr)
+               writel(KAUAI_FCR_UATA_MAGIC |
+                      KAUAI_FCR_UATA_RESET_N |
+                      KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
+
+       pmif->mediabay = 0;
+       
+       /* Make sure we have sane timings */
+       sanitize_timings(pmif);
+
+       host = ide_host_alloc(&d, hws);
+       if (host == NULL)
+               return -ENOMEM;
+       hwif = host->ports[0];
+
+#ifndef CONFIG_PPC64
+       /* XXX FIXME: Media bay stuff need re-organizing */
+       if (np->parent && np->parent->name
+           && strcasecmp(np->parent->name, "media-bay") == 0) {
+#ifdef CONFIG_PMAC_MEDIABAY
+               media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
+                                       hwif);
+#endif /* CONFIG_PMAC_MEDIABAY */
+               pmif->mediabay = 1;
+               if (!bidp)
+                       pmif->aapl_bus_id = 1;
+       } else if (pmif->kind == controller_ohare) {
+               /* The code below is having trouble on some ohare machines
+                * (timing related ?). Until I can put my hand on one of these
+                * units, I keep the old way
+                */
+               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
+       } else
+#endif
+       {
+               /* This is necessary to enable IDE when net-booting */
+               ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
+               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
+               msleep(10);
+               ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);
+               msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
+       }
+
+       printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
+                        "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+                        pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+                        pmif->mediabay ? " (mediabay)" : "", hw->irq);
+
+       rc = ide_host_register(host, &d, hws);
+       if (rc) {
+               ide_host_free(host);
+               return rc;
+       }
+
+       return 0;
+}
+
+static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
+{
+       int i;
+
+       for (i = 0; i < 8; ++i)
+               hw->io_ports_array[i] = base + i * 0x10;
+
+       hw->io_ports.ctl_addr = base + 0x160;
+}
+
+/*
+ * Attach to a macio probed interface
+ */
+static int __devinit
+pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+{
+       void __iomem *base;
+       unsigned long regbase;
+       pmac_ide_hwif_t *pmif;
+       int irq, rc;
+       hw_regs_t hw;
+
+       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
+       if (pmif == NULL)
+               return -ENOMEM;
+
+       if (macio_resource_count(mdev) == 0) {
+               printk(KERN_WARNING "ide-pmac: no address for %s\n",
+                                   mdev->ofdev.node->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
+       }
+
+       /* Request memory resource for IO ports */
+       if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) {
+               printk(KERN_ERR "ide-pmac: can't request MMIO resource for "
+                               "%s!\n", mdev->ofdev.node->full_name);
+               rc = -EBUSY;
+               goto out_free_pmif;
+       }
+                       
+       /* XXX This is bogus. Should be fixed in the registry by checking
+        * the kind of host interrupt controller, a bit like gatwick
+        * fixes in irq.c. That works well enough for the single case
+        * where that happens though...
+        */
+       if (macio_irq_count(mdev) == 0) {
+               printk(KERN_WARNING "ide-pmac: no intrs for device %s, using "
+                                   "13\n", mdev->ofdev.node->full_name);
+               irq = irq_create_mapping(NULL, 13);
+       } else
+               irq = macio_irq(mdev, 0);
+
+       base = ioremap(macio_resource_start(mdev, 0), 0x400);
+       regbase = (unsigned long) base;
+
+       pmif->mdev = mdev;
+       pmif->node = mdev->ofdev.node;
+       pmif->regbase = regbase;
+       pmif->irq = irq;
+       pmif->kauai_fcr = NULL;
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       if (macio_resource_count(mdev) >= 2) {
+               if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
+                       printk(KERN_WARNING "ide-pmac: can't request DMA "
+                                           "resource for %s!\n",
+                                           mdev->ofdev.node->full_name);
+               else
+                       pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
+       } else
+               pmif->dma_regs = NULL;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+       dev_set_drvdata(&mdev->ofdev.dev, pmif);
+
+       memset(&hw, 0, sizeof(hw));
+       pmac_ide_init_ports(&hw, pmif->regbase);
+       hw.irq = irq;
+       hw.dev = &mdev->bus->pdev->dev;
+       hw.parent = &mdev->ofdev.dev;
+
+       rc = pmac_ide_setup_device(pmif, &hw);
+       if (rc != 0) {
+               /* The inteface is released to the common IDE layer */
+               dev_set_drvdata(&mdev->ofdev.dev, NULL);
+               iounmap(base);
+               if (pmif->dma_regs) {
+                       iounmap(pmif->dma_regs);
+                       macio_release_resource(mdev, 1);
+               }
+               macio_release_resource(mdev, 0);
+               kfree(pmif);
+       }
+
+       return rc;
+
+out_free_pmif:
+       kfree(pmif);
+       return rc;
+}
+
+static int
+pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
+{
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+       int rc = 0;
+
+       if (mesg.event != mdev->ofdev.dev.power.power_state.event
+                       && (mesg.event & PM_EVENT_SLEEP)) {
+               rc = pmac_ide_do_suspend(pmif);
+               if (rc == 0)
+                       mdev->ofdev.dev.power.power_state = mesg;
+       }
+
+       return rc;
+}
+
+static int
+pmac_ide_macio_resume(struct macio_dev *mdev)
+{
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+       int rc = 0;
+
+       if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
+               rc = pmac_ide_do_resume(pmif);
+               if (rc == 0)
+                       mdev->ofdev.dev.power.power_state = PMSG_ON;
+       }
+
+       return rc;
+}
+
+/*
+ * Attach to a PCI probed interface
+ */
+static int __devinit
+pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct device_node *np;
+       pmac_ide_hwif_t *pmif;
+       void __iomem *base;
+       unsigned long rbase, rlen;
+       int rc;
+       hw_regs_t hw;
+
+       np = pci_device_to_OF_node(pdev);
+       if (np == NULL) {
+               printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n");
+               return -ENODEV;
+       }
+
+       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
+       if (pmif == NULL)
+               return -ENOMEM;
+
+       if (pci_enable_device(pdev)) {
+               printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
+                                   "%s\n", np->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
+       }
+       pci_set_master(pdev);
+                       
+       if (pci_request_regions(pdev, "Kauai ATA")) {
+               printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for "
+                               "%s\n", np->full_name);
+               rc = -ENXIO;
+               goto out_free_pmif;
+       }
+
+       pmif->mdev = NULL;
+       pmif->node = np;
+
+       rbase = pci_resource_start(pdev, 0);
+       rlen = pci_resource_len(pdev, 0);
+
+       base = ioremap(rbase, rlen);
+       pmif->regbase = (unsigned long) base + 0x2000;
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+       pmif->dma_regs = base + 0x1000;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+       pmif->kauai_fcr = base;
+       pmif->irq = pdev->irq;
+
+       pci_set_drvdata(pdev, pmif);
+
+       memset(&hw, 0, sizeof(hw));
+       pmac_ide_init_ports(&hw, pmif->regbase);
+       hw.irq = pdev->irq;
+       hw.dev = &pdev->dev;
+
+       rc = pmac_ide_setup_device(pmif, &hw);
+       if (rc != 0) {
+               /* The inteface is released to the common IDE layer */
+               pci_set_drvdata(pdev, NULL);
+               iounmap(base);
+               pci_release_regions(pdev);
+               kfree(pmif);
+       }
+
+       return rc;
+
+out_free_pmif:
+       kfree(pmif);
+       return rc;
+}
+
+static int
+pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+       int rc = 0;
+
+       if (mesg.event != pdev->dev.power.power_state.event
+                       && (mesg.event & PM_EVENT_SLEEP)) {
+               rc = pmac_ide_do_suspend(pmif);
+               if (rc == 0)
+                       pdev->dev.power.power_state = mesg;
+       }
+
+       return rc;
+}
+
+static int
+pmac_ide_pci_resume(struct pci_dev *pdev)
+{
+       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+       int rc = 0;
+
+       if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
+               rc = pmac_ide_do_resume(pmif);
+               if (rc == 0)
+                       pdev->dev.power.power_state = PMSG_ON;
+       }
+
+       return rc;
+}
+
+static struct of_device_id pmac_ide_macio_match[] = 
+{
+       {
+       .name           = "IDE",
+       },
+       {
+       .name           = "ATA",
+       },
+       {
+       .type           = "ide",
+       },
+       {
+       .type           = "ata",
+       },
+       {},
+};
+
+static struct macio_driver pmac_ide_macio_driver = 
+{
+       .name           = "ide-pmac",
+       .match_table    = pmac_ide_macio_match,
+       .probe          = pmac_ide_macio_attach,
+       .suspend        = pmac_ide_macio_suspend,
+       .resume         = pmac_ide_macio_resume,
+};
+
+static const struct pci_device_id pmac_ide_pci_match[] = {
+       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA),    0 },
+       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100),  0 },
+       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100),    0 },
+       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA),       0 },
+       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA),    0 },
+       {},
+};
+
+static struct pci_driver pmac_ide_pci_driver = {
+       .name           = "ide-pmac",
+       .id_table       = pmac_ide_pci_match,
+       .probe          = pmac_ide_pci_attach,
+       .suspend        = pmac_ide_pci_suspend,
+       .resume         = pmac_ide_pci_resume,
+};
+MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
+
+int __init pmac_ide_probe(void)
+{
+       int error;
+
+       if (!machine_is(powermac))
+               return -ENODEV;
+
+#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
+       error = pci_register_driver(&pmac_ide_pci_driver);
+       if (error)
+               goto out;
+       error = macio_register_driver(&pmac_ide_macio_driver);
+       if (error) {
+               pci_unregister_driver(&pmac_ide_pci_driver);
+               goto out;
+       }
+#else
+       error = macio_register_driver(&pmac_ide_macio_driver);
+       if (error)
+               goto out;
+       error = pci_register_driver(&pmac_ide_pci_driver);
+       if (error) {
+               macio_unregister_driver(&pmac_ide_macio_driver);
+               goto out;
+       }
+#endif
+out:
+       return error;
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+
+/*
+ * pmac_ide_build_dmatable builds the DBDMA command list
+ * for a transfer and sets the DBDMA channel to point to it.
+ */
+static int
+pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       struct dbdma_cmd *table;
+       int i, count = 0;
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+       struct scatterlist *sg;
+       int wr = (rq_data_dir(rq) == WRITE);
+
+       /* DMA table is already aligned */
+       table = (struct dbdma_cmd *) pmif->dma_table_cpu;
+
+       /* Make sure DMA controller is stopped (necessary ?) */
+       writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control);
+       while (readl(&dma->status) & RUN)
+               udelay(1);
+
+       hwif->sg_nents = i = ide_build_sglist(drive, rq);
+
+       if (!i)
+               return 0;
+
+       /* Build DBDMA commands list */
+       sg = hwif->sg_table;
+       while (i && sg_dma_len(sg)) {
+               u32 cur_addr;
+               u32 cur_len;
+
+               cur_addr = sg_dma_address(sg);
+               cur_len = sg_dma_len(sg);
+
+               if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) {
+                       if (pmif->broken_dma_warn == 0) {
+                               printk(KERN_WARNING "%s: DMA on non aligned address, "
+                                      "switching to PIO on Ohare chipset\n", drive->name);
+                               pmif->broken_dma_warn = 1;
+                       }
+                       goto use_pio_instead;
+               }
+               while (cur_len) {
+                       unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
+
+                       if (count++ >= MAX_DCMDS) {
+                               printk(KERN_WARNING "%s: DMA table too small\n",
+                                      drive->name);
+                               goto use_pio_instead;
+                       }
+                       st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);
+                       st_le16(&table->req_count, tc);
+                       st_le32(&table->phy_addr, cur_addr);
+                       table->cmd_dep = 0;
+                       table->xfer_status = 0;
+                       table->res_count = 0;
+                       cur_addr += tc;
+                       cur_len -= tc;
+                       ++table;
+               }
+               sg = sg_next(sg);
+               i--;
+       }
+
+       /* convert the last command to an input/output last command */
+       if (count) {
+               st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST);
+               /* add the stop command to the end of the list */
+               memset(table, 0, sizeof(struct dbdma_cmd));
+               st_le16(&table->command, DBDMA_STOP);
+               mb();
+               writel(hwif->dmatable_dma, &dma->cmdptr);
+               return 1;
+       }
+
+       printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
+
+use_pio_instead:
+       ide_destroy_dmatable(drive);
+
+       return 0; /* revert to PIO for this request */
+}
+
+/*
+ * Prepare a DMA transfer. We build the DMA table, adjust the timings for
+ * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
+ */
+static int
+pmac_ide_dma_setup(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       struct request *rq = HWGROUP(drive)->rq;
+       u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
+
+       if (!pmac_ide_build_dmatable(drive, rq)) {
+               ide_map_sg(drive, rq);
+               return 1;
+       }
+
+       /* Apple adds 60ns to wrDataSetup on reads */
+       if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
+               writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0),
+                       PMAC_IDE_REG(IDE_TIMING_CONFIG));
+               (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
+       }
+
+       drive->waiting_for_dma = 1;
+
+       return 0;
+}
+
+static void
+pmac_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, NULL);
+}
+
+/*
+ * Kick the DMA controller into life after the DMA command has been issued
+ * to the drive.
+ */
+static void
+pmac_ide_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       volatile struct dbdma_regs __iomem *dma;
+
+       dma = pmif->dma_regs;
+
+       writel((RUN << 16) | RUN, &dma->control);
+       /* Make sure it gets to the controller right now */
+       (void)readl(&dma->control);
+}
+
+/*
+ * After a DMA transfer, make sure the controller is stopped
+ */
+static int
+pmac_ide_dma_end (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+       u32 dstat;
+
+       drive->waiting_for_dma = 0;
+       dstat = readl(&dma->status);
+       writel(((RUN|WAKE|DEAD) << 16), &dma->control);
+
+       ide_destroy_dmatable(drive);
+
+       /* verify good dma status. we don't check for ACTIVE beeing 0. We should...
+        * in theory, but with ATAPI decices doing buffer underruns, that would
+        * cause us to disable DMA, which isn't what we want
+        */
+       return (dstat & (RUN|DEAD)) != RUN;
+}
+
+/*
+ * Check out that the interrupt we got was for us. We can't always know this
+ * for sure with those Apple interfaces (well, we could on the recent ones but
+ * that's not implemented yet), on the other hand, we don't have shared interrupts
+ * so it's not really a problem
+ */
+static int
+pmac_ide_dma_test_irq (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+       unsigned long status, timeout;
+
+       /* We have to things to deal with here:
+        * 
+        * - The dbdma won't stop if the command was started
+        * but completed with an error without transferring all
+        * datas. This happens when bad blocks are met during
+        * a multi-block transfer.
+        * 
+        * - The dbdma fifo hasn't yet finished flushing to
+        * to system memory when the disk interrupt occurs.
+        * 
+        */
+
+       /* If ACTIVE is cleared, the STOP command have passed and
+        * transfer is complete.
+        */
+       status = readl(&dma->status);
+       if (!(status & ACTIVE))
+               return 1;
+
+       /* If dbdma didn't execute the STOP command yet, the
+        * active bit is still set. We consider that we aren't
+        * sharing interrupts (which is hopefully the case with
+        * those controllers) and so we just try to flush the
+        * channel for pending data in the fifo
+        */
+       udelay(1);
+       writel((FLUSH << 16) | FLUSH, &dma->control);
+       timeout = 0;
+       for (;;) {
+               udelay(1);
+               status = readl(&dma->status);
+               if ((status & FLUSH) == 0)
+                       break;
+               if (++timeout > 100) {
+                       printk(KERN_WARNING "ide%d, ide_dma_test_irq \
+                       timeout flushing channel\n", HWIF(drive)->index);
+                       break;
+               }
+       }       
+       return 1;
+}
+
+static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
+{
+}
+
+static void
+pmac_ide_dma_lost_irq (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+       unsigned long status = readl(&dma->status);
+
+       printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
+}
+
+static const struct ide_dma_ops pmac_dma_ops = {
+       .dma_host_set           = pmac_ide_dma_host_set,
+       .dma_setup              = pmac_ide_dma_setup,
+       .dma_exec_cmd           = pmac_ide_dma_exec_cmd,
+       .dma_start              = pmac_ide_dma_start,
+       .dma_end                = pmac_ide_dma_end,
+       .dma_test_irq           = pmac_ide_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = pmac_ide_dma_lost_irq,
+};
+
+/*
+ * Allocate the data structures needed for using DMA with an interface
+ * and fill the proper list of functions pointers
+ */
+static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
+                                      const struct ide_port_info *d)
+{
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       /* We won't need pci_dev if we switch to generic consistent
+        * DMA routines ...
+        */
+       if (dev == NULL || pmif->dma_regs == 0)
+               return -ENODEV;
+       /*
+        * Allocate space for the DBDMA commands.
+        * The +2 is +1 for the stop command and +1 to allow for
+        * aligning the start address to a multiple of 16 bytes.
+        */
+       pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
+               dev,
+               (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
+               &hwif->dmatable_dma);
+       if (pmif->dma_table_cpu == NULL) {
+               printk(KERN_ERR "%s: unable to allocate DMA command list\n",
+                      hwif->name);
+               return -ENOMEM;
+       }
+
+       hwif->sg_max_nents = MAX_DCMDS;
+
+       return 0;
+}
+#else
+static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
+                                      const struct ide_port_info *d)
+{
+       return -EOPNOTSUPP;
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+module_init(pmac_ide_probe);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
deleted file mode 100644 (file)
index 74e52ad..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-obj-$(CONFIG_BLK_DEV_IDE_PMAC)         += pmac.o
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
deleted file mode 100644 (file)
index 2e19d62..0000000
+++ /dev/null
@@ -1,1736 +0,0 @@
-/*
- * Support for IDE interfaces on PowerMacs.
- *
- * These IDE interfaces are memory-mapped and have a DBDMA channel
- * for doing DMA.
- *
- *  Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt
- *  Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- * Some code taken from drivers/ide/ide-dma.c:
- *
- *  Copyright (c) 1995-1998  Mark Lord
- *
- * TODO: - Use pre-calculated (kauai) timing tables all the time and
- * get rid of the "rounded" tables used previously, so we have the
- * same table format for all controllers and can then just have one
- * big table
- * 
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/scatterlist.h>
-
-#include <asm/prom.h>
-#include <asm/io.h>
-#include <asm/dbdma.h>
-#include <asm/ide.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/sections.h>
-#include <asm/irq.h>
-
-#ifndef CONFIG_PPC64
-#include <asm/mediabay.h>
-#endif
-
-#define DRV_NAME "ide-pmac"
-
-#undef IDE_PMAC_DEBUG
-
-#define DMA_WAIT_TIMEOUT       50
-
-typedef struct pmac_ide_hwif {
-       unsigned long                   regbase;
-       int                             irq;
-       int                             kind;
-       int                             aapl_bus_id;
-       unsigned                        mediabay : 1;
-       unsigned                        broken_dma : 1;
-       unsigned                        broken_dma_warn : 1;
-       struct device_node*             node;
-       struct macio_dev                *mdev;
-       u32                             timings[4];
-       volatile u32 __iomem *          *kauai_fcr;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-       /* Those fields are duplicating what is in hwif. We currently
-        * can't use the hwif ones because of some assumptions that are
-        * beeing done by the generic code about the kind of dma controller
-        * and format of the dma table. This will have to be fixed though.
-        */
-       volatile struct dbdma_regs __iomem *    dma_regs;
-       struct dbdma_cmd*               dma_table_cpu;
-#endif
-       
-} pmac_ide_hwif_t;
-
-enum {
-       controller_ohare,       /* OHare based */
-       controller_heathrow,    /* Heathrow/Paddington */
-       controller_kl_ata3,     /* KeyLargo ATA-3 */
-       controller_kl_ata4,     /* KeyLargo ATA-4 */
-       controller_un_ata6,     /* UniNorth2 ATA-6 */
-       controller_k2_ata6,     /* K2 ATA-6 */
-       controller_sh_ata6,     /* Shasta ATA-6 */
-};
-
-static const char* model_name[] = {
-       "OHare ATA",            /* OHare based */
-       "Heathrow ATA",         /* Heathrow/Paddington */
-       "KeyLargo ATA-3",       /* KeyLargo ATA-3 (MDMA only) */
-       "KeyLargo ATA-4",       /* KeyLargo ATA-4 (UDMA/66) */
-       "UniNorth ATA-6",       /* UniNorth2 ATA-6 (UDMA/100) */
-       "K2 ATA-6",             /* K2 ATA-6 (UDMA/100) */
-       "Shasta ATA-6",         /* Shasta ATA-6 (UDMA/133) */
-};
-
-/*
- * Extra registers, both 32-bit little-endian
- */
-#define IDE_TIMING_CONFIG      0x200
-#define IDE_INTERRUPT          0x300
-
-/* Kauai (U2) ATA has different register setup */
-#define IDE_KAUAI_PIO_CONFIG   0x200
-#define IDE_KAUAI_ULTRA_CONFIG 0x210
-#define IDE_KAUAI_POLL_CONFIG  0x220
-
-/*
- * Timing configuration register definitions
- */
-
-/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
-#define SYSCLK_TICKS(t)                (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
-#define SYSCLK_TICKS_66(t)     (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS)
-#define IDE_SYSCLK_NS          30      /* 33Mhz cell */
-#define IDE_SYSCLK_66_NS       15      /* 66Mhz cell */
-
-/* 133Mhz cell, found in shasta.
- * See comments about 100 Mhz Uninorth 2...
- * Note that PIO_MASK and MDMA_MASK seem to overlap
- */
-#define TR_133_PIOREG_PIO_MASK         0xff000fff
-#define TR_133_PIOREG_MDMA_MASK                0x00fff800
-#define TR_133_UDMAREG_UDMA_MASK       0x0003ffff
-#define TR_133_UDMAREG_UDMA_EN         0x00000001
-
-/* 100Mhz cell, found in Uninorth 2. I don't have much infos about
- * this one yet, it appears as a pci device (106b/0033) on uninorth
- * internal PCI bus and it's clock is controlled like gem or fw. It
- * appears to be an evolution of keylargo ATA4 with a timing register
- * extended to 2 32bits registers and a similar DBDMA channel. Other
- * registers seem to exist but I can't tell much about them.
- * 
- * So far, I'm using pre-calculated tables for this extracted from
- * the values used by the MacOS X driver.
- * 
- * The "PIO" register controls PIO and MDMA timings, the "ULTRA"
- * register controls the UDMA timings. At least, it seems bit 0
- * of this one enables UDMA vs. MDMA, and bits 4..7 are the
- * cycle time in units of 10ns. Bits 8..15 are used by I don't
- * know their meaning yet
- */
-#define TR_100_PIOREG_PIO_MASK         0xff000fff
-#define TR_100_PIOREG_MDMA_MASK                0x00fff000
-#define TR_100_UDMAREG_UDMA_MASK       0x0000ffff
-#define TR_100_UDMAREG_UDMA_EN         0x00000001
-
-
-/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on
- * 40 connector cable and to 4 on 80 connector one.
- * Clock unit is 15ns (66Mhz)
- * 
- * 3 Values can be programmed:
- *  - Write data setup, which appears to match the cycle time. They
- *    also call it DIOW setup.
- *  - Ready to pause time (from spec)
- *  - Address setup. That one is weird. I don't see where exactly
- *    it fits in UDMA cycles, I got it's name from an obscure piece
- *    of commented out code in Darwin. They leave it to 0, we do as
- *    well, despite a comment that would lead to think it has a
- *    min value of 45ns.
- * Apple also add 60ns to the write data setup (or cycle time ?) on
- * reads.
- */
-#define TR_66_UDMA_MASK                        0xfff00000
-#define TR_66_UDMA_EN                  0x00100000 /* Enable Ultra mode for DMA */
-#define TR_66_UDMA_ADDRSETUP_MASK      0xe0000000 /* Address setup */
-#define TR_66_UDMA_ADDRSETUP_SHIFT     29
-#define TR_66_UDMA_RDY2PAUS_MASK       0x1e000000 /* Ready 2 pause time */
-#define TR_66_UDMA_RDY2PAUS_SHIFT      25
-#define TR_66_UDMA_WRDATASETUP_MASK    0x01e00000 /* Write data setup time */
-#define TR_66_UDMA_WRDATASETUP_SHIFT   21
-#define TR_66_MDMA_MASK                        0x000ffc00
-#define TR_66_MDMA_RECOVERY_MASK       0x000f8000
-#define TR_66_MDMA_RECOVERY_SHIFT      15
-#define TR_66_MDMA_ACCESS_MASK         0x00007c00
-#define TR_66_MDMA_ACCESS_SHIFT                10
-#define TR_66_PIO_MASK                 0x000003ff
-#define TR_66_PIO_RECOVERY_MASK                0x000003e0
-#define TR_66_PIO_RECOVERY_SHIFT       5
-#define TR_66_PIO_ACCESS_MASK          0x0000001f
-#define TR_66_PIO_ACCESS_SHIFT         0
-
-/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo
- * Can do pio & mdma modes, clock unit is 30ns (33Mhz)
- * 
- * The access time and recovery time can be programmed. Some older
- * Darwin code base limit OHare to 150ns cycle time. I decided to do
- * the same here fore safety against broken old hardware ;)
- * The HalfTick bit, when set, adds half a clock (15ns) to the access
- * time and removes one from recovery. It's not supported on KeyLargo
- * implementation afaik. The E bit appears to be set for PIO mode 0 and
- * is used to reach long timings used in this mode.
- */
-#define TR_33_MDMA_MASK                        0x003ff800
-#define TR_33_MDMA_RECOVERY_MASK       0x001f0000
-#define TR_33_MDMA_RECOVERY_SHIFT      16
-#define TR_33_MDMA_ACCESS_MASK         0x0000f800
-#define TR_33_MDMA_ACCESS_SHIFT                11
-#define TR_33_MDMA_HALFTICK            0x00200000
-#define TR_33_PIO_MASK                 0x000007ff
-#define TR_33_PIO_E                    0x00000400
-#define TR_33_PIO_RECOVERY_MASK                0x000003e0
-#define TR_33_PIO_RECOVERY_SHIFT       5
-#define TR_33_PIO_ACCESS_MASK          0x0000001f
-#define TR_33_PIO_ACCESS_SHIFT         0
-
-/*
- * Interrupt register definitions
- */
-#define IDE_INTR_DMA                   0x80000000
-#define IDE_INTR_DEVICE                        0x40000000
-
-/*
- * FCR Register on Kauai. Not sure what bit 0x4 is  ...
- */
-#define KAUAI_FCR_UATA_MAGIC           0x00000004
-#define KAUAI_FCR_UATA_RESET_N         0x00000002
-#define KAUAI_FCR_UATA_ENABLE          0x00000001
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-
-/* Rounded Multiword DMA timings
- * 
- * I gave up finding a generic formula for all controller
- * types and instead, built tables based on timing values
- * used by Apple in Darwin's implementation.
- */
-struct mdma_timings_t {
-       int     accessTime;
-       int     recoveryTime;
-       int     cycleTime;
-};
-
-struct mdma_timings_t mdma_timings_33[] =
-{
-    { 240, 240, 480 },
-    { 180, 180, 360 },
-    { 135, 135, 270 },
-    { 120, 120, 240 },
-    { 105, 105, 210 },
-    {  90,  90, 180 },
-    {  75,  75, 150 },
-    {  75,  45, 120 },
-    {   0,   0,   0 }
-};
-
-struct mdma_timings_t mdma_timings_33k[] =
-{
-    { 240, 240, 480 },
-    { 180, 180, 360 },
-    { 150, 150, 300 },
-    { 120, 120, 240 },
-    {  90, 120, 210 },
-    {  90,  90, 180 },
-    {  90,  60, 150 },
-    {  90,  30, 120 },
-    {   0,   0,   0 }
-};
-
-struct mdma_timings_t mdma_timings_66[] =
-{
-    { 240, 240, 480 },
-    { 180, 180, 360 },
-    { 135, 135, 270 },
-    { 120, 120, 240 },
-    { 105, 105, 210 },
-    {  90,  90, 180 },
-    {  90,  75, 165 },
-    {  75,  45, 120 },
-    {   0,   0,   0 }
-};
-
-/* KeyLargo ATA-4 Ultra DMA timings (rounded) */
-struct {
-       int     addrSetup; /* ??? */
-       int     rdy2pause;
-       int     wrDataSetup;
-} kl66_udma_timings[] =
-{
-    {   0, 180,  120 },        /* Mode 0 */
-    {   0, 150,  90 }, /*      1 */
-    {   0, 120,  60 }, /*      2 */
-    {   0, 90,   45 }, /*      3 */
-    {   0, 90,   30 }  /*      4 */
-};
-
-/* UniNorth 2 ATA/100 timings */
-struct kauai_timing {
-       int     cycle_time;
-       u32     timing_reg;
-};
-
-static struct kauai_timing     kauai_pio_timings[] =
-{
-       { 930   , 0x08000fff },
-       { 600   , 0x08000a92 },
-       { 383   , 0x0800060f },
-       { 360   , 0x08000492 },
-       { 330   , 0x0800048f },
-       { 300   , 0x080003cf },
-       { 270   , 0x080003cc },
-       { 240   , 0x0800038b },
-       { 239   , 0x0800030c },
-       { 180   , 0x05000249 },
-       { 120   , 0x04000148 },
-       { 0     , 0 },
-};
-
-static struct kauai_timing     kauai_mdma_timings[] =
-{
-       { 1260  , 0x00fff000 },
-       { 480   , 0x00618000 },
-       { 360   , 0x00492000 },
-       { 270   , 0x0038e000 },
-       { 240   , 0x0030c000 },
-       { 210   , 0x002cb000 },
-       { 180   , 0x00249000 },
-       { 150   , 0x00209000 },
-       { 120   , 0x00148000 },
-       { 0     , 0 },
-};
-
-static struct kauai_timing     kauai_udma_timings[] =
-{
-       { 120   , 0x000070c0 },
-       { 90    , 0x00005d80 },
-       { 60    , 0x00004a60 },
-       { 45    , 0x00003a50 },
-       { 30    , 0x00002a30 },
-       { 20    , 0x00002921 },
-       { 0     , 0 },
-};
-
-static struct kauai_timing     shasta_pio_timings[] =
-{
-       { 930   , 0x08000fff },
-       { 600   , 0x0A000c97 },
-       { 383   , 0x07000712 },
-       { 360   , 0x040003cd },
-       { 330   , 0x040003cd },
-       { 300   , 0x040003cd },
-       { 270   , 0x040003cd },
-       { 240   , 0x040003cd },
-       { 239   , 0x040003cd },
-       { 180   , 0x0400028b },
-       { 120   , 0x0400010a },
-       { 0     , 0 },
-};
-
-static struct kauai_timing     shasta_mdma_timings[] =
-{
-       { 1260  , 0x00fff000 },
-       { 480   , 0x00820800 },
-       { 360   , 0x00820800 },
-       { 270   , 0x00820800 },
-       { 240   , 0x00820800 },
-       { 210   , 0x00820800 },
-       { 180   , 0x00820800 },
-       { 150   , 0x0028b000 },
-       { 120   , 0x001ca000 },
-       { 0     , 0 },
-};
-
-static struct kauai_timing     shasta_udma133_timings[] =
-{
-       { 120   , 0x00035901, },
-       { 90    , 0x000348b1, },
-       { 60    , 0x00033881, },
-       { 45    , 0x00033861, },
-       { 30    , 0x00033841, },
-       { 20    , 0x00033031, },
-       { 15    , 0x00033021, },
-       { 0     , 0 },
-};
-
-
-static inline u32
-kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
-{
-       int i;
-       
-       for (i=0; table[i].cycle_time; i++)
-               if (cycle_time > table[i+1].cycle_time)
-                       return table[i].timing_reg;
-       BUG();
-       return 0;
-}
-
-/* allow up to 256 DBDMA commands per xfer */
-#define MAX_DCMDS              256
-
-/* 
- * Wait 1s for disk to answer on IDE bus after a hard reset
- * of the device (via GPIO/FCR).
- * 
- * Some devices seem to "pollute" the bus even after dropping
- * the BSY bit (typically some combo drives slave on the UDMA
- * bus) after a hard reset. Since we hard reset all drives on
- * KeyLargo ATA66, we have to keep that delay around. I may end
- * up not hard resetting anymore on these and keep the delay only
- * for older interfaces instead (we have to reset when coming
- * from MacOS...) --BenH. 
- */
-#define IDE_WAKEUP_DELAY       (1*HZ)
-
-static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *);
-static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
-static void pmac_ide_selectproc(ide_drive_t *drive);
-static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
-
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-
-#define PMAC_IDE_REG(x) \
-       ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x)))
-
-/*
- * Apply the timings of the proper unit (master/slave) to the shared
- * timing register when selecting that unit. This version is for
- * ASICs with a single timing register
- */
-static void
-pmac_ide_selectproc(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-
-       if (drive->dn & 1)
-               writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
-       else
-               writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
-       (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
-}
-
-/*
- * Apply the timings of the proper unit (master/slave) to the shared
- * timing register when selecting that unit. This version is for
- * ASICs with a dual timing register (Kauai)
- */
-static void
-pmac_ide_kauai_selectproc(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-
-       if (drive->dn & 1) {
-               writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
-               writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
-       } else {
-               writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
-               writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
-       }
-       (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
-}
-
-/*
- * Force an update of controller timing values for a given drive
- */
-static void
-pmac_ide_do_update_timings(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-
-       if (pmif->kind == controller_sh_ata6 ||
-           pmif->kind == controller_un_ata6 ||
-           pmif->kind == controller_k2_ata6)
-               pmac_ide_kauai_selectproc(drive);
-       else
-               pmac_ide_selectproc(drive);
-}
-
-static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd)
-{
-       writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
-       (void)readl((void __iomem *)(hwif->io_ports.data_addr
-                                    + IDE_TIMING_CONFIG));
-}
-
-static void pmac_set_irq(ide_hwif_t *hwif, int on)
-{
-       u8 ctl = ATA_DEVCTL_OBS;
-
-       if (on == 4) { /* hack for SRST */
-               ctl |= 4;
-               on &= ~4;
-       }
-
-       ctl |= on ? 0 : 2;
-
-       writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
-       (void)readl((void __iomem *)(hwif->io_ports.data_addr
-                                    + IDE_TIMING_CONFIG));
-}
-
-/*
- * Old tuning functions (called on hdparm -p), sets up drive PIO timings
- */
-static void
-pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
-       u32 *timings, t;
-       unsigned accessTicks, recTicks;
-       unsigned accessTime, recTime;
-       unsigned int cycle_time;
-
-       /* which drive is it ? */
-       timings = &pmif->timings[drive->dn & 1];
-       t = *timings;
-
-       cycle_time = ide_pio_cycle_time(drive, pio);
-
-       switch (pmif->kind) {
-       case controller_sh_ata6: {
-               /* 133Mhz cell */
-               u32 tr = kauai_lookup_timing(shasta_pio_timings, cycle_time);
-               t = (t & ~TR_133_PIOREG_PIO_MASK) | tr;
-               break;
-               }
-       case controller_un_ata6:
-       case controller_k2_ata6: {
-               /* 100Mhz cell */
-               u32 tr = kauai_lookup_timing(kauai_pio_timings, cycle_time);
-               t = (t & ~TR_100_PIOREG_PIO_MASK) | tr;
-               break;
-               }
-       case controller_kl_ata4:
-               /* 66Mhz cell */
-               recTime = cycle_time - tim->active - tim->setup;
-               recTime = max(recTime, 150U);
-               accessTime = tim->active;
-               accessTime = max(accessTime, 150U);
-               accessTicks = SYSCLK_TICKS_66(accessTime);
-               accessTicks = min(accessTicks, 0x1fU);
-               recTicks = SYSCLK_TICKS_66(recTime);
-               recTicks = min(recTicks, 0x1fU);
-               t = (t & ~TR_66_PIO_MASK) |
-                       (accessTicks << TR_66_PIO_ACCESS_SHIFT) |
-                       (recTicks << TR_66_PIO_RECOVERY_SHIFT);
-               break;
-       default: {
-               /* 33Mhz cell */
-               int ebit = 0;
-               recTime = cycle_time - tim->active - tim->setup;
-               recTime = max(recTime, 150U);
-               accessTime = tim->active;
-               accessTime = max(accessTime, 150U);
-               accessTicks = SYSCLK_TICKS(accessTime);
-               accessTicks = min(accessTicks, 0x1fU);
-               accessTicks = max(accessTicks, 4U);
-               recTicks = SYSCLK_TICKS(recTime);
-               recTicks = min(recTicks, 0x1fU);
-               recTicks = max(recTicks, 5U) - 4;
-               if (recTicks > 9) {
-                       recTicks--; /* guess, but it's only for PIO0, so... */
-                       ebit = 1;
-               }
-               t = (t & ~TR_33_PIO_MASK) |
-                               (accessTicks << TR_33_PIO_ACCESS_SHIFT) |
-                               (recTicks << TR_33_PIO_RECOVERY_SHIFT);
-               if (ebit)
-                       t |= TR_33_PIO_E;
-               break;
-               }
-       }
-
-#ifdef IDE_PMAC_DEBUG
-       printk(KERN_ERR "%s: Set PIO timing for mode %d, reg: 0x%08x\n",
-               drive->name, pio,  *timings);
-#endif 
-
-       *timings = t;
-       pmac_ide_do_update_timings(drive);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-
-/*
- * Calculate KeyLargo ATA/66 UDMA timings
- */
-static int
-set_timings_udma_ata4(u32 *timings, u8 speed)
-{
-       unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
-
-       if (speed > XFER_UDMA_4)
-               return 1;
-
-       rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause);
-       wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup);
-       addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup);
-
-       *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) |
-                       (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | 
-                       (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) |
-                       (addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) |
-                       TR_66_UDMA_EN;
-#ifdef IDE_PMAC_DEBUG
-       printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n",
-               speed & 0xf,  *timings);
-#endif 
-
-       return 0;
-}
-
-/*
- * Calculate Kauai ATA/100 UDMA timings
- */
-static int
-set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
-{
-       struct ide_timing *t = ide_timing_find_mode(speed);
-       u32 tr;
-
-       if (speed > XFER_UDMA_5 || t == NULL)
-               return 1;
-       tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma);
-       *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr;
-       *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN;
-
-       return 0;
-}
-
-/*
- * Calculate Shasta ATA/133 UDMA timings
- */
-static int
-set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
-{
-       struct ide_timing *t = ide_timing_find_mode(speed);
-       u32 tr;
-
-       if (speed > XFER_UDMA_6 || t == NULL)
-               return 1;
-       tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma);
-       *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr;
-       *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN;
-
-       return 0;
-}
-
-/*
- * Calculate MDMA timings for all cells
- */
-static void
-set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
-                       u8 speed)
-{
-       u16 *id = drive->id;
-       int cycleTime, accessTime = 0, recTime = 0;
-       unsigned accessTicks, recTicks;
-       struct mdma_timings_t* tm = NULL;
-       int i;
-
-       /* Get default cycle time for mode */
-       switch(speed & 0xf) {
-               case 0: cycleTime = 480; break;
-               case 1: cycleTime = 150; break;
-               case 2: cycleTime = 120; break;
-               default:
-                       BUG();
-                       break;
-       }
-
-       /* Check if drive provides explicit DMA cycle time */
-       if ((id[ATA_ID_FIELD_VALID] & 2) && id[ATA_ID_EIDE_DMA_TIME])
-               cycleTime = max_t(int, id[ATA_ID_EIDE_DMA_TIME], cycleTime);
-
-       /* OHare limits according to some old Apple sources */  
-       if ((intf_type == controller_ohare) && (cycleTime < 150))
-               cycleTime = 150;
-       /* Get the proper timing array for this controller */
-       switch(intf_type) {
-               case controller_sh_ata6:
-               case controller_un_ata6:
-               case controller_k2_ata6:
-                       break;
-               case controller_kl_ata4:
-                       tm = mdma_timings_66;
-                       break;
-               case controller_kl_ata3:
-                       tm = mdma_timings_33k;
-                       break;
-               default:
-                       tm = mdma_timings_33;
-                       break;
-       }
-       if (tm != NULL) {
-               /* Lookup matching access & recovery times */
-               i = -1;
-               for (;;) {
-                       if (tm[i+1].cycleTime < cycleTime)
-                               break;
-                       i++;
-               }
-               cycleTime = tm[i].cycleTime;
-               accessTime = tm[i].accessTime;
-               recTime = tm[i].recoveryTime;
-
-#ifdef IDE_PMAC_DEBUG
-               printk(KERN_ERR "%s: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",
-                       drive->name, cycleTime, accessTime, recTime);
-#endif
-       }
-       switch(intf_type) {
-       case controller_sh_ata6: {
-               /* 133Mhz cell */
-               u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime);
-               *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr;
-               *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN;
-               }
-       case controller_un_ata6:
-       case controller_k2_ata6: {
-               /* 100Mhz cell */
-               u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime);
-               *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr;
-               *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN;
-               }
-               break;
-       case controller_kl_ata4:
-               /* 66Mhz cell */
-               accessTicks = SYSCLK_TICKS_66(accessTime);
-               accessTicks = min(accessTicks, 0x1fU);
-               accessTicks = max(accessTicks, 0x1U);
-               recTicks = SYSCLK_TICKS_66(recTime);
-               recTicks = min(recTicks, 0x1fU);
-               recTicks = max(recTicks, 0x3U);
-               /* Clear out mdma bits and disable udma */
-               *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) |
-                       (accessTicks << TR_66_MDMA_ACCESS_SHIFT) |
-                       (recTicks << TR_66_MDMA_RECOVERY_SHIFT);
-               break;
-       case controller_kl_ata3:
-               /* 33Mhz cell on KeyLargo */
-               accessTicks = SYSCLK_TICKS(accessTime);
-               accessTicks = max(accessTicks, 1U);
-               accessTicks = min(accessTicks, 0x1fU);
-               accessTime = accessTicks * IDE_SYSCLK_NS;
-               recTicks = SYSCLK_TICKS(recTime);
-               recTicks = max(recTicks, 1U);
-               recTicks = min(recTicks, 0x1fU);
-               *timings = ((*timings) & ~TR_33_MDMA_MASK) |
-                               (accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
-                               (recTicks << TR_33_MDMA_RECOVERY_SHIFT);
-               break;
-       default: {
-               /* 33Mhz cell on others */
-               int halfTick = 0;
-               int origAccessTime = accessTime;
-               int origRecTime = recTime;
-               
-               accessTicks = SYSCLK_TICKS(accessTime);
-               accessTicks = max(accessTicks, 1U);
-               accessTicks = min(accessTicks, 0x1fU);
-               accessTime = accessTicks * IDE_SYSCLK_NS;
-               recTicks = SYSCLK_TICKS(recTime);
-               recTicks = max(recTicks, 2U) - 1;
-               recTicks = min(recTicks, 0x1fU);
-               recTime = (recTicks + 1) * IDE_SYSCLK_NS;
-               if ((accessTicks > 1) &&
-                   ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
-                   ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) {
-                       halfTick = 1;
-                       accessTicks--;
-               }
-               *timings = ((*timings) & ~TR_33_MDMA_MASK) |
-                               (accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
-                               (recTicks << TR_33_MDMA_RECOVERY_SHIFT);
-               if (halfTick)
-                       *timings |= TR_33_MDMA_HALFTICK;
-               }
-       }
-#ifdef IDE_PMAC_DEBUG
-       printk(KERN_ERR "%s: Set MDMA timing for mode %d, reg: 0x%08x\n",
-               drive->name, speed & 0xf,  *timings);
-#endif 
-}
-#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
-
-static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       int ret = 0;
-       u32 *timings, *timings2, tl[2];
-       u8 unit = drive->dn & 1;
-
-       timings = &pmif->timings[unit];
-       timings2 = &pmif->timings[unit+2];
-
-       /* Copy timings to local image */
-       tl[0] = *timings;
-       tl[1] = *timings2;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-       if (speed >= XFER_UDMA_0) {
-               if (pmif->kind == controller_kl_ata4)
-                       ret = set_timings_udma_ata4(&tl[0], speed);
-               else if (pmif->kind == controller_un_ata6
-                        || pmif->kind == controller_k2_ata6)
-                       ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
-               else if (pmif->kind == controller_sh_ata6)
-                       ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
-               else
-                       ret = -1;
-       } else
-               set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-       if (ret)
-               return;
-
-       /* Apply timings to controller */
-       *timings = tl[0];
-       *timings2 = tl[1];
-
-       pmac_ide_do_update_timings(drive);      
-}
-
-/*
- * Blast some well known "safe" values to the timing registers at init or
- * wakeup from sleep time, before we do real calculation
- */
-static void
-sanitize_timings(pmac_ide_hwif_t *pmif)
-{
-       unsigned int value, value2 = 0;
-       
-       switch(pmif->kind) {
-               case controller_sh_ata6:
-                       value = 0x0a820c97;
-                       value2 = 0x00033031;
-                       break;
-               case controller_un_ata6:
-               case controller_k2_ata6:
-                       value = 0x08618a92;
-                       value2 = 0x00002921;
-                       break;
-               case controller_kl_ata4:
-                       value = 0x0008438c;
-                       break;
-               case controller_kl_ata3:
-                       value = 0x00084526;
-                       break;
-               case controller_heathrow:
-               case controller_ohare:
-               default:
-                       value = 0x00074526;
-                       break;
-       }
-       pmif->timings[0] = pmif->timings[1] = value;
-       pmif->timings[2] = pmif->timings[3] = value2;
-}
-
-/* Suspend call back, should be called after the child devices
- * have actually been suspended
- */
-static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
-{
-       /* We clear the timings */
-       pmif->timings[0] = 0;
-       pmif->timings[1] = 0;
-       
-       disable_irq(pmif->irq);
-
-       /* The media bay will handle itself just fine */
-       if (pmif->mediabay)
-               return 0;
-       
-       /* Kauai has bus control FCRs directly here */
-       if (pmif->kauai_fcr) {
-               u32 fcr = readl(pmif->kauai_fcr);
-               fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE);
-               writel(fcr, pmif->kauai_fcr);
-       }
-
-       /* Disable the bus on older machines and the cell on kauai */
-       ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id,
-                           0);
-
-       return 0;
-}
-
-/* Resume call back, should be called before the child devices
- * are resumed
- */
-static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
-{
-       /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
-       if (!pmif->mediabay) {
-               ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
-               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
-               msleep(10);
-               ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0);
-
-               /* Kauai has it different */
-               if (pmif->kauai_fcr) {
-                       u32 fcr = readl(pmif->kauai_fcr);
-                       fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE;
-                       writel(fcr, pmif->kauai_fcr);
-               }
-
-               msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
-       }
-
-       /* Sanitize drive timings */
-       sanitize_timings(pmif);
-
-       enable_irq(pmif->irq);
-
-       return 0;
-}
-
-static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
-{
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       struct device_node *np = pmif->node;
-       const char *cable = of_get_property(np, "cable-type", NULL);
-
-       /* Get cable type from device-tree. */
-       if (cable && !strncmp(cable, "80-", 3))
-               return ATA_CBL_PATA80;
-
-       /*
-        * G5's seem to have incorrect cable type in device-tree.
-        * Let's assume they have a 80 conductor cable, this seem
-        * to be always the case unless the user mucked around.
-        */
-       if (of_device_is_compatible(np, "K2-UATA") ||
-           of_device_is_compatible(np, "shasta-ata"))
-               return ATA_CBL_PATA80;
-
-       return ATA_CBL_PATA40;
-}
-
-static void pmac_ide_init_dev(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-
-       if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
-               if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
-                       drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
-                       return;
-               }
-#endif
-               drive->dev_flags |= IDE_DFLAG_NOPROBE;
-       }
-}
-
-static const struct ide_tp_ops pmac_tp_ops = {
-       .exec_command           = pmac_exec_command,
-       .read_status            = ide_read_status,
-       .read_altstatus         = ide_read_altstatus,
-       .read_sff_dma_status    = ide_read_sff_dma_status,
-
-       .set_irq                = pmac_set_irq,
-
-       .tf_load                = ide_tf_load,
-       .tf_read                = ide_tf_read,
-
-       .input_data             = ide_input_data,
-       .output_data            = ide_output_data,
-};
-
-static const struct ide_port_ops pmac_ide_ata6_port_ops = {
-       .init_dev               = pmac_ide_init_dev,
-       .set_pio_mode           = pmac_ide_set_pio_mode,
-       .set_dma_mode           = pmac_ide_set_dma_mode,
-       .selectproc             = pmac_ide_kauai_selectproc,
-       .cable_detect           = pmac_ide_cable_detect,
-};
-
-static const struct ide_port_ops pmac_ide_ata4_port_ops = {
-       .init_dev               = pmac_ide_init_dev,
-       .set_pio_mode           = pmac_ide_set_pio_mode,
-       .set_dma_mode           = pmac_ide_set_dma_mode,
-       .selectproc             = pmac_ide_selectproc,
-       .cable_detect           = pmac_ide_cable_detect,
-};
-
-static const struct ide_port_ops pmac_ide_port_ops = {
-       .init_dev               = pmac_ide_init_dev,
-       .set_pio_mode           = pmac_ide_set_pio_mode,
-       .set_dma_mode           = pmac_ide_set_dma_mode,
-       .selectproc             = pmac_ide_selectproc,
-};
-
-static const struct ide_dma_ops pmac_dma_ops;
-
-static const struct ide_port_info pmac_port_info = {
-       .name                   = DRV_NAME,
-       .init_dma               = pmac_ide_init_dma,
-       .chipset                = ide_pmac,
-       .tp_ops                 = &pmac_tp_ops,
-       .port_ops               = &pmac_ide_port_ops,
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-       .dma_ops                = &pmac_dma_ops,
-#endif
-       .host_flags             = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
-                                 IDE_HFLAG_POST_SET_MODE |
-                                 IDE_HFLAG_MMIO |
-                                 IDE_HFLAG_UNMASK_IRQS,
-       .pio_mask               = ATA_PIO4,
-       .mwdma_mask             = ATA_MWDMA2,
-};
-
-/*
- * Setup, register & probe an IDE channel driven by this driver, this is
- * called by one of the 2 probe functions (macio or PCI).
- */
-static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
-{
-       struct device_node *np = pmif->node;
-       const int *bidp;
-       struct ide_host *host;
-       ide_hwif_t *hwif;
-       hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
-       struct ide_port_info d = pmac_port_info;
-       int rc;
-
-       pmif->broken_dma = pmif->broken_dma_warn = 0;
-       if (of_device_is_compatible(np, "shasta-ata")) {
-               pmif->kind = controller_sh_ata6;
-               d.port_ops = &pmac_ide_ata6_port_ops;
-               d.udma_mask = ATA_UDMA6;
-       } else if (of_device_is_compatible(np, "kauai-ata")) {
-               pmif->kind = controller_un_ata6;
-               d.port_ops = &pmac_ide_ata6_port_ops;
-               d.udma_mask = ATA_UDMA5;
-       } else if (of_device_is_compatible(np, "K2-UATA")) {
-               pmif->kind = controller_k2_ata6;
-               d.port_ops = &pmac_ide_ata6_port_ops;
-               d.udma_mask = ATA_UDMA5;
-       } else if (of_device_is_compatible(np, "keylargo-ata")) {
-               if (strcmp(np->name, "ata-4") == 0) {
-                       pmif->kind = controller_kl_ata4;
-                       d.port_ops = &pmac_ide_ata4_port_ops;
-                       d.udma_mask = ATA_UDMA4;
-               } else
-                       pmif->kind = controller_kl_ata3;
-       } else if (of_device_is_compatible(np, "heathrow-ata")) {
-               pmif->kind = controller_heathrow;
-       } else {
-               pmif->kind = controller_ohare;
-               pmif->broken_dma = 1;
-       }
-
-       bidp = of_get_property(np, "AAPL,bus-id", NULL);
-       pmif->aapl_bus_id =  bidp ? *bidp : 0;
-
-       /* On Kauai-type controllers, we make sure the FCR is correct */
-       if (pmif->kauai_fcr)
-               writel(KAUAI_FCR_UATA_MAGIC |
-                      KAUAI_FCR_UATA_RESET_N |
-                      KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
-
-       pmif->mediabay = 0;
-       
-       /* Make sure we have sane timings */
-       sanitize_timings(pmif);
-
-       host = ide_host_alloc(&d, hws);
-       if (host == NULL)
-               return -ENOMEM;
-       hwif = host->ports[0];
-
-#ifndef CONFIG_PPC64
-       /* XXX FIXME: Media bay stuff need re-organizing */
-       if (np->parent && np->parent->name
-           && strcasecmp(np->parent->name, "media-bay") == 0) {
-#ifdef CONFIG_PMAC_MEDIABAY
-               media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
-                                       hwif);
-#endif /* CONFIG_PMAC_MEDIABAY */
-               pmif->mediabay = 1;
-               if (!bidp)
-                       pmif->aapl_bus_id = 1;
-       } else if (pmif->kind == controller_ohare) {
-               /* The code below is having trouble on some ohare machines
-                * (timing related ?). Until I can put my hand on one of these
-                * units, I keep the old way
-                */
-               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
-       } else
-#endif
-       {
-               /* This is necessary to enable IDE when net-booting */
-               ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
-               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
-               msleep(10);
-               ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);
-               msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
-       }
-
-       printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
-                        "bus ID %d%s, irq %d\n", model_name[pmif->kind],
-                        pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
-                        pmif->mediabay ? " (mediabay)" : "", hw->irq);
-
-       rc = ide_host_register(host, &d, hws);
-       if (rc) {
-               ide_host_free(host);
-               return rc;
-       }
-
-       return 0;
-}
-
-static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
-{
-       int i;
-
-       for (i = 0; i < 8; ++i)
-               hw->io_ports_array[i] = base + i * 0x10;
-
-       hw->io_ports.ctl_addr = base + 0x160;
-}
-
-/*
- * Attach to a macio probed interface
- */
-static int __devinit
-pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
-{
-       void __iomem *base;
-       unsigned long regbase;
-       pmac_ide_hwif_t *pmif;
-       int irq, rc;
-       hw_regs_t hw;
-
-       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
-       if (pmif == NULL)
-               return -ENOMEM;
-
-       if (macio_resource_count(mdev) == 0) {
-               printk(KERN_WARNING "ide-pmac: no address for %s\n",
-                                   mdev->ofdev.node->full_name);
-               rc = -ENXIO;
-               goto out_free_pmif;
-       }
-
-       /* Request memory resource for IO ports */
-       if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) {
-               printk(KERN_ERR "ide-pmac: can't request MMIO resource for "
-                               "%s!\n", mdev->ofdev.node->full_name);
-               rc = -EBUSY;
-               goto out_free_pmif;
-       }
-                       
-       /* XXX This is bogus. Should be fixed in the registry by checking
-        * the kind of host interrupt controller, a bit like gatwick
-        * fixes in irq.c. That works well enough for the single case
-        * where that happens though...
-        */
-       if (macio_irq_count(mdev) == 0) {
-               printk(KERN_WARNING "ide-pmac: no intrs for device %s, using "
-                                   "13\n", mdev->ofdev.node->full_name);
-               irq = irq_create_mapping(NULL, 13);
-       } else
-               irq = macio_irq(mdev, 0);
-
-       base = ioremap(macio_resource_start(mdev, 0), 0x400);
-       regbase = (unsigned long) base;
-
-       pmif->mdev = mdev;
-       pmif->node = mdev->ofdev.node;
-       pmif->regbase = regbase;
-       pmif->irq = irq;
-       pmif->kauai_fcr = NULL;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-       if (macio_resource_count(mdev) >= 2) {
-               if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
-                       printk(KERN_WARNING "ide-pmac: can't request DMA "
-                                           "resource for %s!\n",
-                                           mdev->ofdev.node->full_name);
-               else
-                       pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
-       } else
-               pmif->dma_regs = NULL;
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-       dev_set_drvdata(&mdev->ofdev.dev, pmif);
-
-       memset(&hw, 0, sizeof(hw));
-       pmac_ide_init_ports(&hw, pmif->regbase);
-       hw.irq = irq;
-       hw.dev = &mdev->bus->pdev->dev;
-       hw.parent = &mdev->ofdev.dev;
-
-       rc = pmac_ide_setup_device(pmif, &hw);
-       if (rc != 0) {
-               /* The inteface is released to the common IDE layer */
-               dev_set_drvdata(&mdev->ofdev.dev, NULL);
-               iounmap(base);
-               if (pmif->dma_regs) {
-                       iounmap(pmif->dma_regs);
-                       macio_release_resource(mdev, 1);
-               }
-               macio_release_resource(mdev, 0);
-               kfree(pmif);
-       }
-
-       return rc;
-
-out_free_pmif:
-       kfree(pmif);
-       return rc;
-}
-
-static int
-pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
-{
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
-       int rc = 0;
-
-       if (mesg.event != mdev->ofdev.dev.power.power_state.event
-                       && (mesg.event & PM_EVENT_SLEEP)) {
-               rc = pmac_ide_do_suspend(pmif);
-               if (rc == 0)
-                       mdev->ofdev.dev.power.power_state = mesg;
-       }
-
-       return rc;
-}
-
-static int
-pmac_ide_macio_resume(struct macio_dev *mdev)
-{
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
-       int rc = 0;
-
-       if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
-               rc = pmac_ide_do_resume(pmif);
-               if (rc == 0)
-                       mdev->ofdev.dev.power.power_state = PMSG_ON;
-       }
-
-       return rc;
-}
-
-/*
- * Attach to a PCI probed interface
- */
-static int __devinit
-pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct device_node *np;
-       pmac_ide_hwif_t *pmif;
-       void __iomem *base;
-       unsigned long rbase, rlen;
-       int rc;
-       hw_regs_t hw;
-
-       np = pci_device_to_OF_node(pdev);
-       if (np == NULL) {
-               printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n");
-               return -ENODEV;
-       }
-
-       pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
-       if (pmif == NULL)
-               return -ENOMEM;
-
-       if (pci_enable_device(pdev)) {
-               printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
-                                   "%s\n", np->full_name);
-               rc = -ENXIO;
-               goto out_free_pmif;
-       }
-       pci_set_master(pdev);
-                       
-       if (pci_request_regions(pdev, "Kauai ATA")) {
-               printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for "
-                               "%s\n", np->full_name);
-               rc = -ENXIO;
-               goto out_free_pmif;
-       }
-
-       pmif->mdev = NULL;
-       pmif->node = np;
-
-       rbase = pci_resource_start(pdev, 0);
-       rlen = pci_resource_len(pdev, 0);
-
-       base = ioremap(rbase, rlen);
-       pmif->regbase = (unsigned long) base + 0x2000;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-       pmif->dma_regs = base + 0x1000;
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-       pmif->kauai_fcr = base;
-       pmif->irq = pdev->irq;
-
-       pci_set_drvdata(pdev, pmif);
-
-       memset(&hw, 0, sizeof(hw));
-       pmac_ide_init_ports(&hw, pmif->regbase);
-       hw.irq = pdev->irq;
-       hw.dev = &pdev->dev;
-
-       rc = pmac_ide_setup_device(pmif, &hw);
-       if (rc != 0) {
-               /* The inteface is released to the common IDE layer */
-               pci_set_drvdata(pdev, NULL);
-               iounmap(base);
-               pci_release_regions(pdev);
-               kfree(pmif);
-       }
-
-       return rc;
-
-out_free_pmif:
-       kfree(pmif);
-       return rc;
-}
-
-static int
-pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
-       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
-       int rc = 0;
-
-       if (mesg.event != pdev->dev.power.power_state.event
-                       && (mesg.event & PM_EVENT_SLEEP)) {
-               rc = pmac_ide_do_suspend(pmif);
-               if (rc == 0)
-                       pdev->dev.power.power_state = mesg;
-       }
-
-       return rc;
-}
-
-static int
-pmac_ide_pci_resume(struct pci_dev *pdev)
-{
-       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
-       int rc = 0;
-
-       if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
-               rc = pmac_ide_do_resume(pmif);
-               if (rc == 0)
-                       pdev->dev.power.power_state = PMSG_ON;
-       }
-
-       return rc;
-}
-
-static struct of_device_id pmac_ide_macio_match[] = 
-{
-       {
-       .name           = "IDE",
-       },
-       {
-       .name           = "ATA",
-       },
-       {
-       .type           = "ide",
-       },
-       {
-       .type           = "ata",
-       },
-       {},
-};
-
-static struct macio_driver pmac_ide_macio_driver = 
-{
-       .name           = "ide-pmac",
-       .match_table    = pmac_ide_macio_match,
-       .probe          = pmac_ide_macio_attach,
-       .suspend        = pmac_ide_macio_suspend,
-       .resume         = pmac_ide_macio_resume,
-};
-
-static const struct pci_device_id pmac_ide_pci_match[] = {
-       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA),    0 },
-       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100),  0 },
-       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100),    0 },
-       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA),       0 },
-       { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA),    0 },
-       {},
-};
-
-static struct pci_driver pmac_ide_pci_driver = {
-       .name           = "ide-pmac",
-       .id_table       = pmac_ide_pci_match,
-       .probe          = pmac_ide_pci_attach,
-       .suspend        = pmac_ide_pci_suspend,
-       .resume         = pmac_ide_pci_resume,
-};
-MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
-
-int __init pmac_ide_probe(void)
-{
-       int error;
-
-       if (!machine_is(powermac))
-               return -ENODEV;
-
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
-       error = pci_register_driver(&pmac_ide_pci_driver);
-       if (error)
-               goto out;
-       error = macio_register_driver(&pmac_ide_macio_driver);
-       if (error) {
-               pci_unregister_driver(&pmac_ide_pci_driver);
-               goto out;
-       }
-#else
-       error = macio_register_driver(&pmac_ide_macio_driver);
-       if (error)
-               goto out;
-       error = pci_register_driver(&pmac_ide_pci_driver);
-       if (error) {
-               macio_unregister_driver(&pmac_ide_macio_driver);
-               goto out;
-       }
-#endif
-out:
-       return error;
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-
-/*
- * pmac_ide_build_dmatable builds the DBDMA command list
- * for a transfer and sets the DBDMA channel to point to it.
- */
-static int
-pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       struct dbdma_cmd *table;
-       int i, count = 0;
-       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
-       struct scatterlist *sg;
-       int wr = (rq_data_dir(rq) == WRITE);
-
-       /* DMA table is already aligned */
-       table = (struct dbdma_cmd *) pmif->dma_table_cpu;
-
-       /* Make sure DMA controller is stopped (necessary ?) */
-       writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control);
-       while (readl(&dma->status) & RUN)
-               udelay(1);
-
-       hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-       if (!i)
-               return 0;
-
-       /* Build DBDMA commands list */
-       sg = hwif->sg_table;
-       while (i && sg_dma_len(sg)) {
-               u32 cur_addr;
-               u32 cur_len;
-
-               cur_addr = sg_dma_address(sg);
-               cur_len = sg_dma_len(sg);
-
-               if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) {
-                       if (pmif->broken_dma_warn == 0) {
-                               printk(KERN_WARNING "%s: DMA on non aligned address, "
-                                      "switching to PIO on Ohare chipset\n", drive->name);
-                               pmif->broken_dma_warn = 1;
-                       }
-                       goto use_pio_instead;
-               }
-               while (cur_len) {
-                       unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
-
-                       if (count++ >= MAX_DCMDS) {
-                               printk(KERN_WARNING "%s: DMA table too small\n",
-                                      drive->name);
-                               goto use_pio_instead;
-                       }
-                       st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);
-                       st_le16(&table->req_count, tc);
-                       st_le32(&table->phy_addr, cur_addr);
-                       table->cmd_dep = 0;
-                       table->xfer_status = 0;
-                       table->res_count = 0;
-                       cur_addr += tc;
-                       cur_len -= tc;
-                       ++table;
-               }
-               sg = sg_next(sg);
-               i--;
-       }
-
-       /* convert the last command to an input/output last command */
-       if (count) {
-               st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST);
-               /* add the stop command to the end of the list */
-               memset(table, 0, sizeof(struct dbdma_cmd));
-               st_le16(&table->command, DBDMA_STOP);
-               mb();
-               writel(hwif->dmatable_dma, &dma->cmdptr);
-               return 1;
-       }
-
-       printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
-
-use_pio_instead:
-       ide_destroy_dmatable(drive);
-
-       return 0; /* revert to PIO for this request */
-}
-
-/*
- * Prepare a DMA transfer. We build the DMA table, adjust the timings for
- * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
- */
-static int
-pmac_ide_dma_setup(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       struct request *rq = HWGROUP(drive)->rq;
-       u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
-
-       if (!pmac_ide_build_dmatable(drive, rq)) {
-               ide_map_sg(drive, rq);
-               return 1;
-       }
-
-       /* Apple adds 60ns to wrDataSetup on reads */
-       if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
-               writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0),
-                       PMAC_IDE_REG(IDE_TIMING_CONFIG));
-               (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
-       }
-
-       drive->waiting_for_dma = 1;
-
-       return 0;
-}
-
-static void
-pmac_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, NULL);
-}
-
-/*
- * Kick the DMA controller into life after the DMA command has been issued
- * to the drive.
- */
-static void
-pmac_ide_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma;
-
-       dma = pmif->dma_regs;
-
-       writel((RUN << 16) | RUN, &dma->control);
-       /* Make sure it gets to the controller right now */
-       (void)readl(&dma->control);
-}
-
-/*
- * After a DMA transfer, make sure the controller is stopped
- */
-static int
-pmac_ide_dma_end (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
-       u32 dstat;
-
-       drive->waiting_for_dma = 0;
-       dstat = readl(&dma->status);
-       writel(((RUN|WAKE|DEAD) << 16), &dma->control);
-
-       ide_destroy_dmatable(drive);
-
-       /* verify good dma status. we don't check for ACTIVE beeing 0. We should...
-        * in theory, but with ATAPI decices doing buffer underruns, that would
-        * cause us to disable DMA, which isn't what we want
-        */
-       return (dstat & (RUN|DEAD)) != RUN;
-}
-
-/*
- * Check out that the interrupt we got was for us. We can't always know this
- * for sure with those Apple interfaces (well, we could on the recent ones but
- * that's not implemented yet), on the other hand, we don't have shared interrupts
- * so it's not really a problem
- */
-static int
-pmac_ide_dma_test_irq (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
-       unsigned long status, timeout;
-
-       /* We have to things to deal with here:
-        * 
-        * - The dbdma won't stop if the command was started
-        * but completed with an error without transferring all
-        * datas. This happens when bad blocks are met during
-        * a multi-block transfer.
-        * 
-        * - The dbdma fifo hasn't yet finished flushing to
-        * to system memory when the disk interrupt occurs.
-        * 
-        */
-
-       /* If ACTIVE is cleared, the STOP command have passed and
-        * transfer is complete.
-        */
-       status = readl(&dma->status);
-       if (!(status & ACTIVE))
-               return 1;
-
-       /* If dbdma didn't execute the STOP command yet, the
-        * active bit is still set. We consider that we aren't
-        * sharing interrupts (which is hopefully the case with
-        * those controllers) and so we just try to flush the
-        * channel for pending data in the fifo
-        */
-       udelay(1);
-       writel((FLUSH << 16) | FLUSH, &dma->control);
-       timeout = 0;
-       for (;;) {
-               udelay(1);
-               status = readl(&dma->status);
-               if ((status & FLUSH) == 0)
-                       break;
-               if (++timeout > 100) {
-                       printk(KERN_WARNING "ide%d, ide_dma_test_irq \
-                       timeout flushing channel\n", HWIF(drive)->index);
-                       break;
-               }
-       }       
-       return 1;
-}
-
-static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
-{
-}
-
-static void
-pmac_ide_dma_lost_irq (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
-       unsigned long status = readl(&dma->status);
-
-       printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
-}
-
-static const struct ide_dma_ops pmac_dma_ops = {
-       .dma_host_set           = pmac_ide_dma_host_set,
-       .dma_setup              = pmac_ide_dma_setup,
-       .dma_exec_cmd           = pmac_ide_dma_exec_cmd,
-       .dma_start              = pmac_ide_dma_start,
-       .dma_end                = pmac_ide_dma_end,
-       .dma_test_irq           = pmac_ide_dma_test_irq,
-       .dma_timeout            = ide_dma_timeout,
-       .dma_lost_irq           = pmac_ide_dma_lost_irq,
-};
-
-/*
- * Allocate the data structures needed for using DMA with an interface
- * and fill the proper list of functions pointers
- */
-static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
-                                      const struct ide_port_info *d)
-{
-       pmac_ide_hwif_t *pmif =
-               (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       /* We won't need pci_dev if we switch to generic consistent
-        * DMA routines ...
-        */
-       if (dev == NULL || pmif->dma_regs == 0)
-               return -ENODEV;
-       /*
-        * Allocate space for the DBDMA commands.
-        * The +2 is +1 for the stop command and +1 to allow for
-        * aligning the start address to a multiple of 16 bytes.
-        */
-       pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
-               dev,
-               (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
-               &hwif->dmatable_dma);
-       if (pmif->dma_table_cpu == NULL) {
-               printk(KERN_ERR "%s: unable to allocate DMA command list\n",
-                      hwif->name);
-               return -ENOMEM;
-       }
-
-       hwif->sg_max_nents = MAX_DCMDS;
-
-       return 0;
-}
-#else
-static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
-                                      const struct ide_port_info *d)
-{
-       return -EOPNOTSUPP;
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-
-module_init(pmac_ide_probe);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c
new file mode 100644 (file)
index 0000000..4af4a8c
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ *  Q40 I/O port IDE Driver
+ *
+ *     (c) Richard Zidlicky
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/ide.h>
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define Q40IDE_NUM_HWIFS       2
+
+#define PCIDE_BASE1    0x1f0
+#define PCIDE_BASE2    0x170
+#define PCIDE_BASE3    0x1e8
+#define PCIDE_BASE4    0x168
+#define PCIDE_BASE5    0x1e0
+#define PCIDE_BASE6    0x160
+
+static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
+    PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
+    PCIDE_BASE6 */
+};
+
+static int q40ide_default_irq(unsigned long base)
+{
+           switch (base) {
+                   case 0x1f0: return 14;
+                   case 0x170: return 15;
+                   case 0x1e8: return 11;
+                   default:
+                       return 0;
+          }
+}
+
+
+/*
+ * Addresses are pretranslated for Q40 ISA access.
+ */
+static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base,
+                       ide_ack_intr_t *ack_intr,
+                       int irq)
+{
+       memset(hw, 0, sizeof(hw_regs_t));
+       /* BIG FAT WARNING: 
+          assumption: only DATA port is ever used in 16 bit mode */
+       hw->io_ports.data_addr = Q40_ISA_IO_W(base);
+       hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1);
+       hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2);
+       hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3);
+       hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4);
+       hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5);
+       hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6);
+       hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7);
+       hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
+
+       hw->irq = irq;
+       hw->ack_intr = ack_intr;
+
+       hw->chipset = ide_generic;
+}
+
+static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
+                             void *buf, unsigned int len)
+{
+       unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
+       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+               return insw(data_addr, buf, (len + 1) / 2);
+
+       insw_swapw(data_addr, buf, (len + 1) / 2);
+}
+
+static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
+                              void *buf, unsigned int len)
+{
+       unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
+       if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+               return outsw(data_addr, buf, (len + 1) / 2);
+
+       outsw_swapw(data_addr, buf, (len + 1) / 2);
+}
+
+/* Q40 has a byte-swapped IDE interface */
+static const struct ide_tp_ops q40ide_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = q40ide_input_data,
+       .output_data            = q40ide_output_data,
+};
+
+static const struct ide_port_info q40ide_port_info = {
+       .tp_ops                 = &q40ide_tp_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+};
+
+/* 
+ * the static array is needed to have the name reported in /proc/ioports,
+ * hwif->name unfortunately isn't available yet
+ */
+static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
+       "ide0", "ide1"
+};
+
+/*
+ *  Probe for Q40 IDE interfaces
+ */
+
+static int __init q40ide_init(void)
+{
+    int i;
+    hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
+
+    if (!MACH_IS_Q40)
+      return -ENODEV;
+
+    printk(KERN_INFO "ide: Q40 IDE controller\n");
+
+    for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
+       const char *name = q40_ide_names[i];
+
+       if (!request_region(pcide_bases[i], 8, name)) {
+               printk("could not reserve ports %lx-%lx for %s\n",
+                      pcide_bases[i],pcide_bases[i]+8,name);
+               continue;
+       }
+       if (!request_region(pcide_bases[i]+0x206, 1, name)) {
+               printk("could not reserve port %lx for %s\n",
+                      pcide_bases[i]+0x206,name);
+               release_region(pcide_bases[i], 8);
+               continue;
+       }
+       q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
+                       q40ide_default_irq(pcide_bases[i]));
+
+       hws[i] = &hw[i];
+    }
+
+    return ide_host_add(&q40ide_port_info, hws, NULL);
+}
+
+module_init(q40ide_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
new file mode 100644 (file)
index 0000000..bc27c7a
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
+ */
+
+/*
+ *  Version 0.03       Cleaned auto-tune, added probe
+ *  Version 0.04       Added second channel tuning
+ *  Version 0.05       Enhanced tuning ; added qd6500 support
+ *  Version 0.06       Added dos driver's list
+ *  Version 0.07       Second channel bug fix 
+ *
+ * QDI QD6500/QD6580 EIDE controller fast support
+ *
+ * To activate controller support, use "ide0=qd65xx"
+ */
+
+/*
+ * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
+ * Samuel Thibault <samuel.thibault@fnac.net>
+ */
+
+#include <linux/module.h>
+#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/ide.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#define DRV_NAME "qd65xx"
+
+#include "qd65xx.h"
+
+/*
+ * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580)
+ *            or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580)
+ *     -- qd6500 is a single IDE interface
+ *     -- qd6580 is a dual IDE interface
+ *
+ * More research on qd6580 being done by willmore@cig.mot.com (David)
+ * More Information given by Petr Soucek (petr@ryston.cz)
+ * http://www.ryston.cz/petr/vlb
+ */
+
+/*
+ * base: Timer1
+ *
+ *
+ * base+0x01: Config (R/O)
+ *
+ * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500)
+ * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30
+ * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz
+ * bit 3: qd6500: 1 = disabled, 0 = enabled
+ *        qd6580: 1
+ * upper nibble:
+ *        qd6500: 1100
+ *        qd6580: either 1010 or 0101
+ *
+ *
+ * base+0x02: Timer2 (qd6580 only)
+ *
+ *
+ * base+0x03: Control (qd6580 only)
+ *
+ * bits 0-3 must always be set 1
+ * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock
+ * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb
+ *         0 = Primary and Secondary ports enabled : channel 0 for hda & hdb
+ *                                                   channel 1 for hdc & hdd
+ * bit 1 : 1 = only disks on primary port
+ *         0 = disks & ATAPI devices on primary port
+ * bit 2-4 : always 0
+ * bit 5 : status, but of what ?
+ * bit 6 : always set 1 by dos driver
+ * bit 7 : set 1 for non-ATAPI devices on primary port
+ *     (maybe read-ahead and post-write buffer ?)
+ */
+
+static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
+
+/*
+ * qd65xx_select:
+ *
+ * This routine is invoked to prepare for access to a given drive.
+ */
+
+static void qd65xx_select(ide_drive_t *drive)
+{
+       u8 index = ((   (QD_TIMREG(drive)) & 0x80 ) >> 7) |
+                       (QD_TIMREG(drive) & 0x02);
+
+       if (timings[index] != QD_TIMING(drive))
+               outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
+}
+
+/*
+ * qd6500_compute_timing
+ *
+ * computes the timing value where
+ *     lower nibble represents active time,   in count of VLB clocks
+ *     upper nibble represents recovery time, in count of VLB clocks
+ */
+
+static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
+{
+       int clk = ide_vlb_clk ? ide_vlb_clk : 50;
+       u8 act_cyc, rec_cyc;
+
+       if (clk <= 33) {
+               act_cyc =  9 - IDE_IN(active_time   * clk / 1000 + 1, 2,  9);
+               rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15);
+       } else {
+               act_cyc =  8 - IDE_IN(active_time   * clk / 1000 + 1, 1,  8);
+               rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18);
+       }
+
+       return (rec_cyc << 4) | 0x08 | act_cyc;
+}
+
+/*
+ * qd6580_compute_timing
+ *
+ * idem for qd6580
+ */
+
+static u8 qd6580_compute_timing (int active_time, int recovery_time)
+{
+       int clk = ide_vlb_clk ? ide_vlb_clk : 50;
+       u8 act_cyc, rec_cyc;
+
+       act_cyc = 17 - IDE_IN(active_time   * clk / 1000 + 1, 2, 17);
+       rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15);
+
+       return (rec_cyc << 4) | act_cyc;
+}
+
+/*
+ * qd_find_disk_type
+ *
+ * tries to find timing from dos driver's table
+ */
+
+static int qd_find_disk_type (ide_drive_t *drive,
+               int *active_time, int *recovery_time)
+{
+       struct qd65xx_timing_s *p;
+       char *m = (char *)&drive->id[ATA_ID_PROD];
+       char model[ATA_ID_PROD_LEN];
+
+       if (*m == 0)
+               return 0;
+
+       strncpy(model, m, ATA_ID_PROD_LEN);
+       ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */
+
+       for (p = qd65xx_timing ; p->offset != -1 ; p++) {
+               if (!strncmp(p->model, model+p->offset, 4)) {
+                       printk(KERN_DEBUG "%s: listed !\n", drive->name);
+                       *active_time = p->active;
+                       *recovery_time = p->recovery;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * qd_set_timing:
+ *
+ * records the timing
+ */
+
+static void qd_set_timing (ide_drive_t *drive, u8 timing)
+{
+       drive->drive_data &= 0xff00;
+       drive->drive_data |= timing;
+
+       printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
+}
+
+static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       u16 *id = drive->id;
+       int active_time   = 175;
+       int recovery_time = 415; /* worst case values from the dos driver */
+
+       /*
+        * FIXME: use "pio" value
+        */
+       if (!qd_find_disk_type(drive, &active_time, &recovery_time) &&
+           (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) &&
+           id[ATA_ID_EIDE_PIO] >= 240) {
+               printk(KERN_INFO "%s: PIO mode%d\n", drive->name,
+                       id[ATA_ID_OLD_PIO_MODES] & 0xff);
+               active_time = 110;
+               recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120;
+       }
+
+       qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
+}
+
+static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+       unsigned int cycle_time;
+       int active_time   = 175;
+       int recovery_time = 415; /* worst case values from the dos driver */
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+
+       if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
+               cycle_time = ide_pio_cycle_time(drive, pio);
+
+               switch (pio) {
+                       case 0: break;
+                       case 3:
+                               if (cycle_time >= 110) {
+                                       active_time = 86;
+                                       recovery_time = cycle_time - 102;
+                               } else
+                                       printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
+                               break;
+                       case 4:
+                               if (cycle_time >= 69) {
+                                       active_time = 70;
+                                       recovery_time = cycle_time - 61;
+                               } else
+                                       printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
+                               break;
+                       default:
+                               if (cycle_time >= 180) {
+                                       active_time = 110;
+                                       recovery_time = cycle_time - 120;
+                               } else {
+                                       active_time = t->active;
+                                       recovery_time = cycle_time - active_time;
+                               }
+               }
+               printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio);
+       }
+
+       if (!HWIF(drive)->channel && drive->media != ide_disk) {
+               outb(0x5f, QD_CONTROL_PORT);
+               printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
+                       "and post-write buffer on %s.\n",
+                       drive->name, HWIF(drive)->name);
+       }
+
+       qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
+}
+
+/*
+ * qd_testreg
+ *
+ * tests if the given port is a register
+ */
+
+static int __init qd_testreg(int port)
+{
+       unsigned long flags;
+       u8 savereg, readreg;
+
+       local_irq_save(flags);
+       savereg = inb_p(port);
+       outb_p(QD_TESTVAL, port);       /* safe value */
+       readreg = inb_p(port);
+       outb(savereg, port);
+       local_irq_restore(flags);
+
+       if (savereg == QD_TESTVAL) {
+               printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n");
+               printk(KERN_ERR "Please contact maintainers to tell about your hardware\n");
+               printk(KERN_ERR "Assuming qd65xx is not present.\n");
+               return 1;
+       }
+
+       return (readreg != QD_TESTVAL);
+}
+
+static void __init qd6500_init_dev(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+       u8 config = QD_CONFIG(hwif);
+
+       drive->drive_data = QD6500_DEF_DATA;
+}
+
+static void __init qd6580_init_dev(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u16 t1, t2;
+       u8 base = (hwif->config_data & 0xff00) >> 8;
+       u8 config = QD_CONFIG(hwif);
+
+       if (hwif->host_flags & IDE_HFLAG_SINGLE) {
+               t1 = QD6580_DEF_DATA;
+               t2 = QD6580_DEF_DATA2;
+       } else
+               t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
+
+       drive->drive_data = (drive->dn & 1) ? t2 : t1;
+}
+
+static const struct ide_port_ops qd6500_port_ops = {
+       .init_dev               = qd6500_init_dev,
+       .set_pio_mode           = qd6500_set_pio_mode,
+       .selectproc             = qd65xx_select,
+};
+
+static const struct ide_port_ops qd6580_port_ops = {
+       .init_dev               = qd6580_init_dev,
+       .set_pio_mode           = qd6580_set_pio_mode,
+       .selectproc             = qd65xx_select,
+};
+
+static const struct ide_port_info qd65xx_port_info __initdata = {
+       .name                   = DRV_NAME,
+       .chipset                = ide_qd65xx,
+       .host_flags             = IDE_HFLAG_IO_32BIT |
+                                 IDE_HFLAG_NO_DMA,
+       .pio_mask               = ATA_PIO4,
+};
+
+/*
+ * qd_probe:
+ *
+ * looks at the specified baseport, and if qd found, registers & initialises it
+ * return 1 if another qd may be probed
+ */
+
+static int __init qd_probe(int base)
+{
+       int rc;
+       u8 config, unit, control;
+       struct ide_port_info d = qd65xx_port_info;
+
+       config = inb(QD_CONFIG_PORT);
+
+       if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
+               return -ENODEV;
+
+       unit = ! (config & QD_CONFIG_IDE_BASEPORT);
+
+       if (unit)
+               d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
+
+       switch (config & 0xf0) {
+       case QD_CONFIG_QD6500:
+               if (qd_testreg(base))
+                        return -ENODEV;        /* bad register */
+
+               if (config & QD_CONFIG_DISABLED) {
+                       printk(KERN_WARNING "qd6500 is disabled !\n");
+                       return -ENODEV;
+               }
+
+               printk(KERN_NOTICE "qd6500 at %#x\n", base);
+               printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
+                       config, QD_ID3);
+
+               d.port_ops = &qd6500_port_ops;
+               d.host_flags |= IDE_HFLAG_SINGLE;
+               break;
+       case QD_CONFIG_QD6580_A:
+       case QD_CONFIG_QD6580_B:
+               if (qd_testreg(base) || qd_testreg(base + 0x02))
+                       return -ENODEV; /* bad registers */
+
+               control = inb(QD_CONTROL_PORT);
+
+               printk(KERN_NOTICE "qd6580 at %#x\n", base);
+               printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n",
+                       config, control, QD_ID3);
+
+               outb(QD_DEF_CONTR, QD_CONTROL_PORT);
+
+               d.port_ops = &qd6580_port_ops;
+               if (control & QD_CONTR_SEC_DISABLED)
+                       d.host_flags |= IDE_HFLAG_SINGLE;
+
+               printk(KERN_INFO "qd6580: %s IDE board\n",
+                       (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual");
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       rc = ide_legacy_device_add(&d, (base << 8) | config);
+
+       if (d.host_flags & IDE_HFLAG_SINGLE)
+               return (rc == 0) ? 1 : rc;
+
+       return rc;
+}
+
+static int probe_qd65xx;
+
+module_param_named(probe, probe_qd65xx, bool, 0);
+MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
+
+static int __init qd65xx_init(void)
+{
+       int rc1, rc2 = -ENODEV;
+
+       if (probe_qd65xx == 0)
+               return -ENODEV;
+
+       rc1 = qd_probe(0x30);
+       if (rc1)
+               rc2 = qd_probe(0xb0);
+
+       if (rc1 < 0 && rc2 < 0)
+               return -ENODEV;
+
+       return 0;
+}
+
+module_init(qd65xx_init);
+
+MODULE_AUTHOR("Samuel Thibault");
+MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h
new file mode 100644 (file)
index 0000000..c83dea8
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2000  Linus Torvalds & authors
+ */
+
+/*
+ * Authors:    Petr Soucek <petr@ryston.cz>
+ *             Samuel Thibault <samuel.thibault@fnac.net>
+ */
+
+/* truncates a in [b,c] */
+#define IDE_IN(a,b,c)   ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) )
+
+#define IDE_IMPLY(a,b) ((!(a)) || (b))
+
+#define QD_TIM1_PORT           (base)
+#define QD_CONFIG_PORT         (base+0x01)
+#define QD_TIM2_PORT           (base+0x02)
+#define QD_CONTROL_PORT                (base+0x03)
+
+#define QD_CONFIG_IDE_BASEPORT 0x01
+#define QD_CONFIG_BASEPORT     0x02
+#define QD_CONFIG_ID3          0x04
+#define QD_CONFIG_DISABLED     0x08
+#define QD_CONFIG_QD6500       0xc0
+#define QD_CONFIG_QD6580_A     0xa0
+#define QD_CONFIG_QD6580_B     0x50
+
+#define QD_CONTR_SEC_DISABLED  0x01
+
+#define QD_ID3                 ((config & QD_CONFIG_ID3)!=0)
+
+#define QD_CONFIG(hwif)                ((hwif)->config_data & 0x00ff)
+
+#define QD_TIMING(drive)       (byte)(((drive)->drive_data) & 0x00ff)
+#define QD_TIMREG(drive)       (byte)((((drive)->drive_data) & 0xff00) >> 8)
+
+#define QD6500_DEF_DATA                ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08))
+#define QD6580_DEF_DATA                ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
+#define QD6580_DEF_DATA2       ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
+#define QD_DEF_CONTR           (0x40 | ((control & 0x02) ? 0x9f : 0x1f))
+
+#define QD_TESTVAL             0x19    /* safe value */
+
+/* Drive specific timing taken from DOS driver v3.7 */
+
+static struct qd65xx_timing_s {
+       s8      offset;   /* ofset from the beginning of Model Number" */
+       char    model[4];    /* 4 chars from Model number, no conversion */
+       s16     active;   /* active time */
+       s16     recovery; /* recovery time */
+} qd65xx_timing [] = {
+       { 30, "2040", 110, 225 },  /* Conner CP30204                    */
+       { 30, "2045", 135, 225 },  /* Conner CP30254                    */
+       { 30, "1040", 155, 325 },  /* Conner CP30104                    */
+       { 30, "1047", 135, 265 },  /* Conner CP30174                    */
+       { 30, "5344", 135, 225 },  /* Conner CP3544                     */
+       { 30, "01 4", 175, 405 },  /* Conner CP-3104                    */
+       { 27, "C030", 175, 375 },  /* Conner CP3000                     */
+       {  8, "PL42", 110, 295 },  /* Quantum LP240                     */
+       {  8, "PL21", 110, 315 },  /* Quantum LP120                     */
+       {  8, "PL25", 175, 385 },  /* Quantum LP52                      */
+       {  4, "PA24", 110, 285 },  /* WD Piranha SP4200                 */
+       {  6, "2200", 110, 260 },  /* WD Caviar AC2200                  */
+       {  6, "3204", 110, 235 },  /* WD Caviar AC2340                  */
+       {  6, "1202", 110, 265 },  /* WD Caviar AC2120                  */
+       {  0, "DS3-", 135, 315 },  /* Teac SD340                        */
+       {  8, "KM32", 175, 355 },  /* Toshiba MK234                     */
+       {  2, "53A1", 175, 355 },  /* Seagate ST351A                    */
+       {  2, "4108", 175, 295 },  /* Seagate ST1480A                   */
+       {  2, "1344", 175, 335 },  /* Seagate ST3144A                   */
+       {  6, "7 12", 110, 225 },  /* Maxtor 7213A                      */
+       { 30, "02F4", 145, 295 },  /* Conner 3204F                      */
+       {  2, "1302", 175, 335 },  /* Seagate ST3120A                   */
+       {  2, "2334", 145, 265 },  /* Seagate ST3243A                   */
+       {  2, "2338", 145, 275 },  /* Seagate ST3283A                   */
+       {  2, "3309", 145, 275 },  /* Seagate ST3390A                   */
+       {  2, "5305", 145, 275 },  /* Seagate ST3550A                   */
+       {  2, "4100", 175, 295 },  /* Seagate ST1400A                   */
+       {  2, "4110", 175, 295 },  /* Seagate ST1401A                   */
+       {  2, "6300", 135, 265 },  /* Seagate ST3600A                   */
+       {  2, "5300", 135, 265 },  /* Seagate ST3500A                   */
+       {  6, "7 31", 135, 225 },  /* Maxtor 7131 AT                    */
+       {  6, "7 43", 115, 265 },  /* Maxtor 7345 AT                    */
+       {  6, "7 42", 110, 255 },  /* Maxtor 7245 AT                    */
+       {  6, "3 04", 135, 265 },  /* Maxtor 340 AT                     */
+       {  6, "61 0", 135, 285 },  /* WD AC160                          */
+       {  6, "1107", 135, 235 },  /* WD AC1170                         */
+       {  6, "2101", 110, 220 },  /* WD AC1210                         */
+       {  6, "4202", 135, 245 },  /* WD AC2420                         */
+       {  6, "41 0", 175, 355 },  /* WD Caviar 140                     */
+       {  6, "82 0", 175, 355 },  /* WD Caviar 280                     */
+       {  8, "PL01", 175, 375 },  /* Quantum LP105                     */
+       {  8, "PL25", 110, 295 },  /* Quantum LP525                     */
+       { 10, "4S 2", 175, 385 },  /* Quantum ELS42                     */
+       { 10, "8S 5", 175, 385 },  /* Quantum ELS85                     */
+       { 10, "1S72", 175, 385 },  /* Quantum ELS127                    */
+       { 10, "1S07", 175, 385 },  /* Quantum ELS170                    */
+       {  8, "ZE42", 135, 295 },  /* Quantum EZ240                     */
+       {  8, "ZE21", 175, 385 },  /* Quantum EZ127                     */
+       {  8, "ZE58", 175, 385 },  /* Quantum EZ85                      */
+       {  8, "ZE24", 175, 385 },  /* Quantum EZ42                      */
+       { 27, "C036", 155, 325 },  /* Conner CP30064                    */
+       { 27, "C038", 155, 325 },  /* Conner CP30084                    */
+       {  6, "2205", 110, 255 },  /* WDC AC2250                        */
+       {  2, " CHA", 140, 415 },  /* WDC AH series; WDC AH260, WDC     */
+       {  2, " CLA", 140, 415 },  /* WDC AL series: WDC AL2120, 2170,  */
+       {  4, "UC41", 140, 415 },  /* WDC CU140                         */
+       {  6, "1207", 130, 275 },  /* WDC AC2170                        */
+       {  6, "2107", 130, 275 },  /* WDC AC1270                        */
+       {  6, "5204", 130, 275 },  /* WDC AC2540                        */
+       { 30, "3004", 110, 235 },  /* Conner CP30340                    */
+       { 30, "0345", 135, 255 },  /* Conner CP30544                    */
+       { 12, "12A3", 175, 320 },  /* MAXTOR LXT-213A                   */
+       { 12, "43A0", 145, 240 },  /* MAXTOR LXT-340A                   */
+       {  6, "7 21", 180, 290 },  /* Maxtor 7120 AT                    */
+       {  6, "7 71", 135, 240 },  /* Maxtor 7170 AT                    */
+       { 12, "45\0000", 110, 205 },   /* MAXTOR MXT-540                */
+       {  8, "PL11", 180, 290 },  /* QUANTUM LP110A                    */
+       {  8, "OG21", 150, 275 },  /* QUANTUM GO120                     */
+       { 12, "42A5", 175, 320 },  /* MAXTOR LXT-245A                   */
+       {  2, "2309", 175, 295 },  /* ST3290A                           */
+       {  2, "3358", 180, 310 },  /* ST3385A                           */
+       {  2, "6355", 180, 310 },  /* ST3655A                           */
+       {  2, "1900", 175, 270 },  /* ST9100A                           */
+       {  2, "1954", 175, 270 },  /* ST9145A                           */
+       {  2, "1909", 175, 270 },  /* ST9190AG                          */
+       {  2, "2953", 175, 270 },  /* ST9235A                           */
+       {  2, "1359", 175, 270 },  /* ST3195A                           */
+       { 24, "3R11", 175, 290 },  /* ALPS ELECTRIC Co.,LTD, DR311C     */
+       {  0, "2M26", 175, 215 },  /* M262XT-0Ah                        */
+       {  4, "2253", 175, 300 },  /* HP C2235A                         */
+       {  4, "-32A", 145, 245 },  /* H3133-A2                          */
+       { 30, "0326", 150, 270 },  /* Samsung Electronics 120MB         */
+       { 30, "3044", 110, 195 },  /* Conner CFA340A                    */
+       { 30, "43A0", 110, 195 },  /* Conner CFA340A                    */
+       { -1, "    ", 175, 415 }   /* unknown disk name                 */
+};
diff --git a/drivers/ide/rapide.c b/drivers/ide/rapide.c
new file mode 100644 (file)
index 0000000..78d27d9
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1996-2002 Russell King.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/errno.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/ecard.h>
+
+static struct const ide_port_info rapide_port_info = {
+       .host_flags             = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+};
+
+static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
+                              void __iomem *ctrl, unsigned int sz, int irq)
+{
+       unsigned long port = (unsigned long)base;
+       int i;
+
+       for (i = 0; i <= 7; i++) {
+               hw->io_ports_array[i] = port;
+               port += sz;
+       }
+       hw->io_ports.ctl_addr = (unsigned long)ctrl;
+       hw->irq = irq;
+}
+
+static int __devinit
+rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+       void __iomem *base;
+       struct ide_host *host;
+       int ret;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+
+       ret = ecard_request_resources(ec);
+       if (ret)
+               goto out;
+
+       base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
+       if (!base) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+       rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
+       hw.chipset = ide_generic;
+       hw.dev = &ec->dev;
+
+       ret = ide_host_add(&rapide_port_info, hws, &host);
+       if (ret)
+               goto release;
+
+       ecard_set_drvdata(ec, host);
+       goto out;
+
+ release:
+       ecard_release_resources(ec);
+ out:
+       return ret;
+}
+
+static void __devexit rapide_remove(struct expansion_card *ec)
+{
+       struct ide_host *host = ecard_get_drvdata(ec);
+
+       ecard_set_drvdata(ec, NULL);
+
+       ide_host_remove(host);
+
+       ecard_release_resources(ec);
+}
+
+static struct ecard_id rapide_ids[] = {
+       { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 },
+       { 0xffff, 0xffff }
+};
+
+static struct ecard_driver rapide_driver = {
+       .probe          = rapide_probe,
+       .remove         = __devexit_p(rapide_remove),
+       .id_table       = rapide_ids,
+       .drv = {
+               .name   = "rapide",
+       },
+};
+
+static int __init rapide_init(void)
+{
+       return ecard_register_driver(&rapide_driver);
+}
+
+static void __exit rapide_exit(void)
+{
+       ecard_unregister_driver(&rapide_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Yellowstone RAPIDE driver");
+
+module_init(rapide_init);
+module_exit(rapide_exit);
diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c
new file mode 100644 (file)
index 0000000..7daf013
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  Copyright (C) 1995-1998  Linus Torvalds & author (see below)
+ */
+
+/*
+ *  Principal Author:  mlord@pobox.com (Mark Lord)
+ *
+ *  See linux/MAINTAINERS for address of current maintainer.
+ *
+ *  This file provides support for disabling the buggy read-ahead
+ *  mode of the RZ1000 IDE chipset, commonly used on Intel motherboards.
+ *
+ *  Dunno if this fixes both ports, or only the primary port (?).
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "rz1000"
+
+static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u16 reg;
+
+       if (!pci_read_config_word (dev, 0x40, &reg) &&
+           !pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
+               printk(KERN_INFO "%s: disabled chipset read-ahead "
+                       "(buggy RZ1000/RZ1001)\n", hwif->name);
+       } else {
+               if (hwif->mate)
+                       hwif->mate->serialized = hwif->serialized = 1;
+               hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
+               printk(KERN_INFO "%s: serialized, disabled unmasking "
+                       "(buggy RZ1000/RZ1001)\n", hwif->name);
+       }
+}
+
+static const struct ide_port_info rz1000_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_hwif      = init_hwif_rz1000,
+       .chipset        = ide_rz1000,
+       .host_flags     = IDE_HFLAG_NO_DMA,
+};
+
+static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &rz1000_chipset, NULL);
+}
+
+static const struct pci_device_id rz1000_pci_tbl[] = {
+       { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), 0 },
+       { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
+
+static struct pci_driver rz1000_pci_driver = {
+       .name           = "RZ1000_IDE",
+       .id_table       = rz1000_pci_tbl,
+       .probe          = rz1000_init_one,
+       .remove         = ide_pci_remove,
+};
+
+static int __init rz1000_ide_init(void)
+{
+       return ide_pci_register_driver(&rz1000_pci_driver);
+}
+
+static void __exit rz1000_ide_exit(void)
+{
+       pci_unregister_driver(&rz1000_pci_driver);
+}
+
+module_init(rz1000_ide_init);
+module_exit(rz1000_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c
new file mode 100644 (file)
index 0000000..f1a8758
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2000-2002             Mark Lord <mlord@pobox.com>
+ * Copyright (C)      2007             Bartlomiej Zolnierkiewicz
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Development of this chipset driver was funded
+ * by the nice folks at National Semiconductor.
+ *
+ * Documentation:
+ *     Available from National Semiconductor
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "sc1200"
+
+#define SC1200_REV_A   0x00
+#define SC1200_REV_B1  0x01
+#define SC1200_REV_B3  0x02
+#define SC1200_REV_C1  0x03
+#define SC1200_REV_D1  0x04
+
+#define PCI_CLK_33     0x00
+#define PCI_CLK_48     0x01
+#define PCI_CLK_66     0x02
+#define PCI_CLK_33A    0x03
+
+static unsigned short sc1200_get_pci_clock (void)
+{
+       unsigned char chip_id, silicon_revision;
+       unsigned int pci_clock;
+       /*
+        * Check the silicon revision, as not all versions of the chip
+        * have the register with the fast PCI bus timings.
+        */
+       chip_id = inb (0x903c);
+       silicon_revision = inb (0x903d);
+
+       // Read the fast pci clock frequency
+       if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) {
+               pci_clock = PCI_CLK_33;
+       } else {
+               // check clock generator configuration (cfcc)
+               // the clock is in bits 8 and 9 of this word
+
+               pci_clock = inw (0x901e);
+               pci_clock >>= 8;
+               pci_clock &= 0x03;
+               if (pci_clock == PCI_CLK_33A)
+                       pci_clock = PCI_CLK_33;
+       }
+       return pci_clock;
+}
+
+/*
+ * Here are the standard PIO mode 0-4 timings for each "format".
+ * Format-0 uses fast data reg timings, with slower command reg timings.
+ * Format-1 uses fast timings for all registers, but won't work with all drives.
+ */
+static const unsigned int sc1200_pio_timings[4][5] =
+       {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},  // format0  33Mhz
+        {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},  // format1, 33Mhz
+        {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},  // format1, 48Mhz
+        {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz
+
+/*
+ * After chip reset, the PIO timings are set to 0x00009172, which is not valid.
+ */
+//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
+
+static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
+
+       pci_read_config_dword(pdev, basereg + 4, &format);
+       format = (format >> 31) & 1;
+       if (format)
+               format += sc1200_get_pci_clock();
+       pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3),
+                              sc1200_pio_timings[format][pio]);
+}
+
+/*
+ *     The SC1200 specifies that two drives sharing a cable cannot mix
+ *     UDMA/MDMA.  It has to be one or the other, for the pair, though
+ *     different timings can still be chosen for each drive.  We could
+ *     set the appropriate timing bits on the fly, but that might be
+ *     a bit confusing.  So, for now we statically handle this requirement
+ *     by looking at our mate drive to see what it is capable of, before
+ *     choosing a mode for our own drive.
+ */
+static u8 sc1200_udma_filter(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       ide_drive_t *mate = ide_get_pair_dev(drive);
+       u16 *mateid = mate->id;
+       u8 mask = hwif->ultra_mask;
+
+       if (mate == NULL)
+               goto out;
+
+       if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
+               if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
+                   (mateid[ATA_ID_UDMA_MODES] & 7))
+                       goto out;
+               if ((mateid[ATA_ID_FIELD_VALID] & 2) &&
+                   (mateid[ATA_ID_MWDMA_MODES] & 7))
+                       mask = 0;
+       }
+out:
+       return mask;
+}
+
+static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+       ide_hwif_t              *hwif = HWIF(drive);
+       struct pci_dev          *dev = to_pci_dev(hwif->dev);
+       unsigned int            reg, timings;
+       unsigned short          pci_clock;
+       unsigned int            basereg = hwif->channel ? 0x50 : 0x40;
+
+       static const u32 udma_timing[3][3] = {
+               { 0x00921250, 0x00911140, 0x00911030 },
+               { 0x00932470, 0x00922260, 0x00922140 },
+               { 0x009436a1, 0x00933481, 0x00923261 },
+       };
+
+       static const u32 mwdma_timing[3][3] = {
+               { 0x00077771, 0x00012121, 0x00002020 },
+               { 0x000bbbb2, 0x00024241, 0x00013131 },
+               { 0x000ffff3, 0x00035352, 0x00015151 },
+       };
+
+       pci_clock = sc1200_get_pci_clock();
+
+       /*
+        * Note that each DMA mode has several timings associated with it.
+        * The correct timing depends on the fast PCI clock freq.
+        */
+
+       if (mode >= XFER_UDMA_0)
+               timings =  udma_timing[pci_clock][mode - XFER_UDMA_0];
+       else
+               timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
+
+       if ((drive->dn & 1) == 0) {
+               pci_read_config_dword(dev, basereg + 4, &reg);
+               timings |= reg & 0x80000000;    /* preserve PIO format bit */
+               pci_write_config_dword(dev, basereg + 4, timings);
+       } else
+               pci_write_config_dword(dev, basereg + 12, timings);
+}
+
+/*  Replacement for the standard ide_dma_end action in
+ *  dma_proc.
+ *
+ *  returns 1 on error, 0 otherwise
+ */
+static int sc1200_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       unsigned long dma_base = hwif->dma_base;
+       byte dma_stat;
+
+       dma_stat = inb(dma_base+2);             /* get DMA status */
+
+       if (!(dma_stat & 4))
+               printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n",
+                 dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2));
+
+       outb(dma_stat|0x1b, dma_base+2);        /* clear the INTR & ERROR bits */
+       outb(inb(dma_base)&~1, dma_base);       /* !! DO THIS HERE !! stop DMA */
+
+       drive->waiting_for_dma = 0;
+       ide_destroy_dmatable(drive);            /* purge DMA mappings */
+
+       return (dma_stat & 7) != 4;             /* verify good DMA status */
+}
+
+/*
+ * sc1200_set_pio_mode() handles setting of PIO modes
+ * for both the chipset and drive.
+ *
+ * All existing BIOSs for this chipset guarantee that all drives
+ * will have valid default PIO timings set up before we get here.
+ */
+
+static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t      *hwif = HWIF(drive);
+       int             mode = -1;
+
+       /*
+        * bad abuse of ->set_pio_mode interface
+        */
+       switch (pio) {
+               case 200: mode = XFER_UDMA_0;   break;
+               case 201: mode = XFER_UDMA_1;   break;
+               case 202: mode = XFER_UDMA_2;   break;
+               case 100: mode = XFER_MW_DMA_0; break;
+               case 101: mode = XFER_MW_DMA_1; break;
+               case 102: mode = XFER_MW_DMA_2; break;
+       }
+       if (mode != -1) {
+               printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
+               ide_dma_off_quietly(drive);
+               if (ide_set_dma_mode(drive, mode) == 0 &&
+                   (drive->dev_flags & IDE_DFLAG_USING_DMA))
+                       hwif->dma_ops->dma_host_set(drive, 1);
+               return;
+       }
+
+       sc1200_tunepio(drive, pio);
+}
+
+#ifdef CONFIG_PM
+struct sc1200_saved_state {
+       u32 regs[8];
+};
+
+static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
+{
+       printk("SC1200: suspend(%u)\n", state.event);
+
+       /*
+        * we only save state when going from full power to less
+        */
+       if (state.event == PM_EVENT_ON) {
+               struct ide_host *host = pci_get_drvdata(dev);
+               struct sc1200_saved_state *ss = host->host_priv;
+               unsigned int r;
+
+               /*
+                * save timing registers
+                * (this may be unnecessary if BIOS also does it)
+                */
+               for (r = 0; r < 8; r++)
+                       pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
+       }
+
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+       return 0;
+}
+
+static int sc1200_resume (struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct sc1200_saved_state *ss = host->host_priv;
+       unsigned int r;
+       int i;
+
+       i = pci_enable_device(dev);
+       if (i)
+               return i;
+
+       /*
+        * restore timing registers
+        * (this may be unnecessary if BIOS also does it)
+        */
+       for (r = 0; r < 8; r++)
+               pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
+
+       return 0;
+}
+#endif
+
+static const struct ide_port_ops sc1200_port_ops = {
+       .set_pio_mode           = sc1200_set_pio_mode,
+       .set_dma_mode           = sc1200_set_dma_mode,
+       .udma_filter            = sc1200_udma_filter,
+};
+
+static const struct ide_dma_ops sc1200_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                = sc1200_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info sc1200_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .port_ops       = &sc1200_port_ops,
+       .dma_ops        = &sc1200_dma_ops,
+       .host_flags     = IDE_HFLAG_SERIALIZE |
+                         IDE_HFLAG_POST_SET_MODE |
+                         IDE_HFLAG_ABUSE_DMA_MODES,
+       .pio_mask       = ATA_PIO4,
+       .mwdma_mask     = ATA_MWDMA2,
+       .udma_mask      = ATA_UDMA2,
+};
+
+static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct sc1200_saved_state *ss = NULL;
+       int rc;
+
+#ifdef CONFIG_PM
+       ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+       if (ss == NULL)
+               return -ENOMEM;
+#endif
+       rc = ide_pci_init_one(dev, &sc1200_chipset, ss);
+       if (rc)
+               kfree(ss);
+
+       return rc;
+}
+
+static const struct pci_device_id sc1200_pci_tbl[] = {
+       { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0},
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
+
+static struct pci_driver sc1200_pci_driver = {
+       .name           = "SC1200_IDE",
+       .id_table       = sc1200_pci_tbl,
+       .probe          = sc1200_init_one,
+       .remove         = ide_pci_remove,
+#ifdef CONFIG_PM
+       .suspend        = sc1200_suspend,
+       .resume         = sc1200_resume,
+#endif
+};
+
+static int __init sc1200_ide_init(void)
+{
+       return ide_pci_register_driver(&sc1200_pci_driver);
+}
+
+static void __exit sc1200_ide_exit(void)
+{
+       pci_unregister_driver(&sc1200_pci_driver);
+}
+
+module_init(sc1200_ide_init);
+module_exit(sc1200_ide_exit);
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c
new file mode 100644 (file)
index 0000000..49f163a
--- /dev/null
@@ -0,0 +1,966 @@
+/*
+ * Support for IDE interfaces on Celleb platform
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on drivers/ide/pci/siimage.c:
+ * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003          Red Hat <alan@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA            0x01b4
+
+#define SCC_PATA_NAME           "scc IDE"
+
+#define TDVHSEL_MASTER          0x00000001
+#define TDVHSEL_SLAVE           0x00000004
+
+#define MODE_JCUSFEN            0x00000080
+
+#define CCKCTRL_ATARESET        0x00040000
+#define CCKCTRL_BUFCNT          0x00020000
+#define CCKCTRL_CRST            0x00010000
+#define CCKCTRL_OCLKEN          0x00000100
+#define CCKCTRL_ATACLKOEN       0x00000002
+#define CCKCTRL_LCLKEN          0x00000001
+
+#define QCHCD_IOS_SS           0x00000001
+
+#define QCHSD_STPDIAG          0x00020000
+
+#define INTMASK_MSK             0xD1000012
+#define INTSTS_SERROR          0x80000000
+#define INTSTS_PRERR           0x40000000
+#define INTSTS_RERR            0x10000000
+#define INTSTS_ICERR           0x01000000
+#define INTSTS_BMSINT          0x00000010
+#define INTSTS_BMHE            0x00000008
+#define INTSTS_IOIRQS           0x00000004
+#define INTSTS_INTRQ            0x00000002
+#define INTSTS_ACTEINT          0x00000001
+
+#define ECMODE_VALUE 0x01
+
+static struct scc_ports {
+       unsigned long ctl, dma;
+       struct ide_host *host;  /* for removing port from system */
+} scc_ports[MAX_HWIFS];
+
+/* PIO transfer mode  table */
+/* JCHST */
+static unsigned long JCHSTtbl[2][7] = {
+       {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00},   /* 100MHz */
+       {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00}    /* 133MHz */
+};
+
+/* JCHHT */
+static unsigned long JCHHTtbl[2][7] = {
+       {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00},   /* 100MHz */
+       {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}    /* 133MHz */
+};
+
+/* JCHCT */
+static unsigned long JCHCTtbl[2][7] = {
+       {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00},   /* 100MHz */
+       {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00}    /* 133MHz */
+};
+
+
+/* DMA transfer mode  table */
+/* JCHDCTM/JCHDCTS */
+static unsigned long JCHDCTxtbl[2][7] = {
+       {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00},   /* 100MHz */
+       {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00}    /* 133MHz */
+};
+
+/* JCSTWTM/JCSTWTS  */
+static unsigned long JCSTWTxtbl[2][7] = {
+       {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00},   /* 100MHz */
+       {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
+};
+
+/* JCTSS */
+static unsigned long JCTSStbl[2][7] = {
+       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00},   /* 100MHz */
+       {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05}    /* 133MHz */
+};
+
+/* JCENVT */
+static unsigned long JCENVTtbl[2][7] = {
+       {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00},   /* 100MHz */
+       {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}    /* 133MHz */
+};
+
+/* JCACTSELS/JCACTSELM */
+static unsigned long JCACTSELtbl[2][7] = {
+       {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00},   /* 100MHz */
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}    /* 133MHz */
+};
+
+
+static u8 scc_ide_inb(unsigned long port)
+{
+       u32 data = in_be32((void*)port);
+       return (u8)data;
+}
+
+static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+       out_be32((void *)hwif->io_ports.command_addr, cmd);
+       eieio();
+       in_be32((void *)(hwif->dma_base + 0x01c));
+       eieio();
+}
+
+static u8 scc_read_status(ide_hwif_t *hwif)
+{
+       return (u8)in_be32((void *)hwif->io_ports.status_addr);
+}
+
+static u8 scc_read_altstatus(ide_hwif_t *hwif)
+{
+       return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
+}
+
+static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
+{
+       return (u8)in_be32((void *)(hwif->dma_base + 4));
+}
+
+static void scc_set_irq(ide_hwif_t *hwif, int on)
+{
+       u8 ctl = ATA_DEVCTL_OBS;
+
+       if (on == 4) { /* hack for SRST */
+               ctl |= 4;
+               on &= ~4;
+       }
+
+       ctl |= on ? 0 : 2;
+
+       out_be32((void *)hwif->io_ports.ctl_addr, ctl);
+       eieio();
+       in_be32((void *)(hwif->dma_base + 0x01c));
+       eieio();
+}
+
+static void scc_ide_insw(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               *ptr++ = le16_to_cpu(in_be32((void*)port));
+       }
+}
+
+static void scc_ide_insl(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               *ptr++ = le16_to_cpu(in_be32((void*)port));
+               *ptr++ = le16_to_cpu(in_be32((void*)port));
+       }
+}
+
+static void scc_ide_outb(u8 addr, unsigned long port)
+{
+       out_be32((void*)port, addr);
+}
+
+static void
+scc_ide_outsw(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               out_be32((void*)port, cpu_to_le16(*ptr++));
+       }
+}
+
+static void
+scc_ide_outsl(unsigned long port, void *addr, u32 count)
+{
+       u16 *ptr = (u16 *)addr;
+       while (count--) {
+               out_be32((void*)port, cpu_to_le16(*ptr++));
+               out_be32((void*)port, cpu_to_le16(*ptr++));
+       }
+}
+
+/**
+ *     scc_set_pio_mode        -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller.
+ */
+
+static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct scc_ports *ports = ide_get_hwifdata(hwif);
+       unsigned long ctl_base = ports->ctl;
+       unsigned long cckctrl_port = ctl_base + 0xff0;
+       unsigned long piosht_port = ctl_base + 0x000;
+       unsigned long pioct_port = ctl_base + 0x004;
+       unsigned long reg;
+       int offset;
+
+       reg = in_be32((void __iomem *)cckctrl_port);
+       if (reg & CCKCTRL_ATACLKOEN) {
+               offset = 1; /* 133MHz */
+       } else {
+               offset = 0; /* 100MHz */
+       }
+       reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio];
+       out_be32((void __iomem *)piosht_port, reg);
+       reg = JCHCTtbl[offset][pio];
+       out_be32((void __iomem *)pioct_port, reg);
+}
+
+/**
+ *     scc_set_dma_mode        -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller.
+ */
+
+static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct scc_ports *ports = ide_get_hwifdata(hwif);
+       unsigned long ctl_base = ports->ctl;
+       unsigned long cckctrl_port = ctl_base + 0xff0;
+       unsigned long mdmact_port = ctl_base + 0x008;
+       unsigned long mcrcst_port = ctl_base + 0x00c;
+       unsigned long sdmact_port = ctl_base + 0x010;
+       unsigned long scrcst_port = ctl_base + 0x014;
+       unsigned long udenvt_port = ctl_base + 0x018;
+       unsigned long tdvhsel_port   = ctl_base + 0x020;
+       int is_slave = (&hwif->drives[1] == drive);
+       int offset, idx;
+       unsigned long reg;
+       unsigned long jcactsel;
+
+       reg = in_be32((void __iomem *)cckctrl_port);
+       if (reg & CCKCTRL_ATACLKOEN) {
+               offset = 1; /* 133MHz */
+       } else {
+               offset = 0; /* 100MHz */
+       }
+
+       idx = speed - XFER_UDMA_0;
+
+       jcactsel = JCACTSELtbl[offset][idx];
+       if (is_slave) {
+               out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]);
+               out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]);
+               jcactsel = jcactsel << 2;
+               out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel);
+       } else {
+               out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]);
+               out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]);
+               out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel);
+       }
+       reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
+       out_be32((void __iomem *)udenvt_port, reg);
+}
+
+static void scc_dma_host_set(ide_drive_t *drive, int on)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 unit = drive->dn & 1;
+       u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
+
+       if (on)
+               dma_stat |= (1 << (5 + unit));
+       else
+               dma_stat &= ~(1 << (5 + unit));
+
+       scc_ide_outb(dma_stat, hwif->dma_base + 4);
+}
+
+/**
+ *     scc_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.
+ *
+ *     Returns 0 on success. If a PIO fallback is required then 1
+ *     is returned.
+ */
+
+static int scc_dma_setup(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *rq = HWGROUP(drive)->rq;
+       unsigned int reading;
+       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 */
+       out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
+
+       /* specify r/w */
+       out_be32((void __iomem *)hwif->dma_base, reading);
+
+       /* read DMA status for INTR & ERROR flags */
+       dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
+
+       /* clear INTR & ERROR flags */
+       out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
+       drive->waiting_for_dma = 1;
+       return 0;
+}
+
+static void scc_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 dma_cmd = scc_ide_inb(hwif->dma_base);
+
+       /* start DMA */
+       scc_ide_outb(dma_cmd | 1, hwif->dma_base);
+       wmb();
+}
+
+static int __scc_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 dma_stat, dma_cmd;
+
+       drive->waiting_for_dma = 0;
+       /* get DMA command mode */
+       dma_cmd = scc_ide_inb(hwif->dma_base);
+       /* stop DMA */
+       scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
+       /* get DMA status */
+       dma_stat = scc_ide_inb(hwif->dma_base + 4);
+       /* clear the INTR & ERROR bits */
+       scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
+       /* purge DMA mappings */
+       ide_destroy_dmatable(drive);
+       /* verify good DMA status */
+       wmb();
+       return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
+}
+
+/**
+ *     scc_dma_end     -       Stop DMA
+ *     @drive: IDE drive
+ *
+ *     Check and clear INT Status register.
+ *     Then call __scc_dma_end().
+ */
+
+static int scc_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       void __iomem *dma_base = (void __iomem *)hwif->dma_base;
+       unsigned long intsts_port = hwif->dma_base + 0x014;
+       u32 reg;
+       int dma_stat, data_loss = 0;
+       static int retry = 0;
+
+       /* errata A308 workaround: Step5 (check data loss) */
+       /* We don't check non ide_disk because it is limited to UDMA4 */
+       if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr)
+             & ATA_ERR) &&
+           drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
+               reg = in_be32((void __iomem *)intsts_port);
+               if (!(reg & INTSTS_ACTEINT)) {
+                       printk(KERN_WARNING "%s: operation failed (transfer data loss)\n",
+                              drive->name);
+                       data_loss = 1;
+                       if (retry++) {
+                               struct request *rq = HWGROUP(drive)->rq;
+                               int unit;
+                               /* ERROR_RESET and drive->crc_count are needed
+                                * to reduce DMA transfer mode in retry process.
+                                */
+                               if (rq)
+                                       rq->errors |= ERROR_RESET;
+                               for (unit = 0; unit < MAX_DRIVES; unit++) {
+                                       ide_drive_t *drive = &hwif->drives[unit];
+                                       drive->crc_count++;
+                               }
+                       }
+               }
+       }
+
+       while (1) {
+               reg = in_be32((void __iomem *)intsts_port);
+
+               if (reg & INTSTS_SERROR) {
+                       printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
+
+                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
+                       continue;
+               }
+
+               if (reg & INTSTS_PRERR) {
+                       u32 maea0, maec0;
+                       unsigned long ctl_base = hwif->config_data;
+
+                       maea0 = in_be32((void __iomem *)(ctl_base + 0xF50));
+                       maec0 = in_be32((void __iomem *)(ctl_base + 0xF54));
+
+                       printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0);
+
+                       out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
+
+                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
+                       continue;
+               }
+
+               if (reg & INTSTS_RERR) {
+                       printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
+
+                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
+                       continue;
+               }
+
+               if (reg & INTSTS_ICERR) {
+                       out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
+
+                       printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
+                       continue;
+               }
+
+               if (reg & INTSTS_BMSINT) {
+                       printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME);
+                       out_be32((void __iomem *)intsts_port, INTSTS_BMSINT);
+
+                       ide_do_reset(drive);
+                       continue;
+               }
+
+               if (reg & INTSTS_BMHE) {
+                       out_be32((void __iomem *)intsts_port, INTSTS_BMHE);
+                       continue;
+               }
+
+               if (reg & INTSTS_ACTEINT) {
+                       out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT);
+                       continue;
+               }
+
+               if (reg & INTSTS_IOIRQS) {
+                       out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS);
+                       continue;
+               }
+               break;
+       }
+
+       dma_stat = __scc_dma_end(drive);
+       if (data_loss)
+               dma_stat |= 2; /* emulate DMA error (to retry command) */
+       return dma_stat;
+}
+
+/* returns 1 if dma irq issued, 0 otherwise */
+static int scc_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
+
+       /* SCC errata A252,A308 workaround: Step4 */
+       if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
+            & ATA_ERR) &&
+           (int_stat & INTSTS_INTRQ))
+               return 1;
+
+       /* SCC errata A308 workaround: Step5 (polling IOIRQS) */
+       if (int_stat & INTSTS_IOIRQS)
+               return 1;
+
+       return 0;
+}
+
+static u8 scc_udma_filter(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 mask = hwif->ultra_mask;
+
+       /* errata A308 workaround: limit non ide_disk drive to UDMA4 */
+       if ((drive->media != ide_disk) && (mask & 0xE0)) {
+               printk(KERN_INFO "%s: limit %s to UDMA4\n",
+                      SCC_PATA_NAME, drive->name);
+               mask = ATA_UDMA4;
+       }
+
+       return mask;
+}
+
+/**
+ *     setup_mmio_scc  -       map CTRL/BMID region
+ *     @dev: PCI device we are configuring
+ *     @name: device name
+ *
+ */
+
+static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+{
+       unsigned long ctl_base = pci_resource_start(dev, 0);
+       unsigned long dma_base = pci_resource_start(dev, 1);
+       unsigned long ctl_size = pci_resource_len(dev, 0);
+       unsigned long dma_size = pci_resource_len(dev, 1);
+       void __iomem *ctl_addr;
+       void __iomem *dma_addr;
+       int i, ret;
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               if (scc_ports[i].ctl == 0)
+                       break;
+       }
+       if (i >= MAX_HWIFS)
+               return -ENOMEM;
+
+       ret = pci_request_selected_regions(dev, (1 << 2) - 1, name);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: can't reserve resources\n", name);
+               return ret;
+       }
+
+       if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
+               goto fail_0;
+
+       if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
+               goto fail_1;
+
+       pci_set_master(dev);
+       scc_ports[i].ctl = (unsigned long)ctl_addr;
+       scc_ports[i].dma = (unsigned long)dma_addr;
+       pci_set_drvdata(dev, (void *) &scc_ports[i]);
+
+       return 1;
+
+ fail_1:
+       iounmap(ctl_addr);
+ fail_0:
+       return -ENOMEM;
+}
+
+static int scc_ide_setup_pci_device(struct pci_dev *dev,
+                                   const struct ide_port_info *d)
+{
+       struct scc_ports *ports = pci_get_drvdata(dev);
+       struct ide_host *host;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+       int i, rc;
+
+       memset(&hw, 0, sizeof(hw));
+       for (i = 0; i <= 8; i++)
+               hw.io_ports_array[i] = ports->dma + 0x20 + i * 4;
+       hw.irq = dev->irq;
+       hw.dev = &dev->dev;
+       hw.chipset = ide_pci;
+
+       rc = ide_host_add(d, hws, &host);
+       if (rc)
+               return rc;
+
+       ports->host = host;
+
+       return 0;
+}
+
+/**
+ *     init_setup_scc  -       set up an SCC PATA Controller
+ *     @dev: PCI device
+ *     @d: IDE port info
+ *
+ *     Perform the initial set up for this device.
+ */
+
+static int __devinit init_setup_scc(struct pci_dev *dev,
+                                   const struct ide_port_info *d)
+{
+       unsigned long ctl_base;
+       unsigned long dma_base;
+       unsigned long cckctrl_port;
+       unsigned long intmask_port;
+       unsigned long mode_port;
+       unsigned long ecmode_port;
+       u32 reg = 0;
+       struct scc_ports *ports;
+       int rc;
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               goto end;
+
+       rc = setup_mmio_scc(dev, d->name);
+       if (rc < 0)
+               goto end;
+
+       ports = pci_get_drvdata(dev);
+       ctl_base = ports->ctl;
+       dma_base = ports->dma;
+       cckctrl_port = ctl_base + 0xff0;
+       intmask_port = dma_base + 0x010;
+       mode_port = ctl_base + 0x024;
+       ecmode_port = ctl_base + 0xf00;
+
+       /* controller initialization */
+       reg = 0;
+       out_be32((void*)cckctrl_port, reg);
+       reg |= CCKCTRL_ATACLKOEN;
+       out_be32((void*)cckctrl_port, reg);
+       reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
+       out_be32((void*)cckctrl_port, reg);
+       reg |= CCKCTRL_CRST;
+       out_be32((void*)cckctrl_port, reg);
+
+       for (;;) {
+               reg = in_be32((void*)cckctrl_port);
+               if (reg & CCKCTRL_CRST)
+                       break;
+               udelay(5000);
+       }
+
+       reg |= CCKCTRL_ATARESET;
+       out_be32((void*)cckctrl_port, reg);
+
+       out_be32((void*)ecmode_port, ECMODE_VALUE);
+       out_be32((void*)mode_port, MODE_JCUSFEN);
+       out_be32((void*)intmask_port, INTMASK_MSK);
+
+       rc = scc_ide_setup_pci_device(dev, d);
+
+ end:
+       return rc;
+}
+
+static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+       u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+       if (task->tf_flags & IDE_TFLAG_FLAGGED)
+               HIHI = 0xFF;
+
+       if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+               out_be32((void *)io_ports->data_addr,
+                        (tf->hob_data << 8) | tf->data);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+               scc_ide_outb(tf->hob_feature, io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+               scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+               scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+               scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+               scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+               scc_ide_outb(tf->feature, io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+               scc_ide_outb(tf->nsect, io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+               scc_ide_outb(tf->lbal, io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+               scc_ide_outb(tf->lbam, io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+               scc_ide_outb(tf->lbah, io_ports->lbah_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+               scc_ide_outb((tf->device & HIHI) | drive->select,
+                            io_ports->device_addr);
+}
+
+static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+       struct ide_io_ports *io_ports = &drive->hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+
+       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+               u16 data = (u16)in_be32((void *)io_ports->data_addr);
+
+               tf->data = data & 0xff;
+               tf->hob_data = (data >> 8) & 0xff;
+       }
+
+       /* be sure we're looking at the low order bits */
+       scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+               tf->feature = scc_ide_inb(io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+               tf->nsect  = scc_ide_inb(io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+               tf->lbal   = scc_ide_inb(io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+               tf->lbam   = scc_ide_inb(io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+               tf->lbah   = scc_ide_inb(io_ports->lbah_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+               tf->device = scc_ide_inb(io_ports->device_addr);
+
+       if (task->tf_flags & IDE_TFLAG_LBA48) {
+               scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+                       tf->hob_feature = scc_ide_inb(io_ports->feature_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+                       tf->hob_nsect   = scc_ide_inb(io_ports->nsect_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+                       tf->hob_lbal    = scc_ide_inb(io_ports->lbal_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+                       tf->hob_lbam    = scc_ide_inb(io_ports->lbam_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+                       tf->hob_lbah    = scc_ide_inb(io_ports->lbah_addr);
+       }
+}
+
+static void scc_input_data(ide_drive_t *drive, struct request *rq,
+                          void *buf, unsigned int len)
+{
+       unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
+       len++;
+
+       if (drive->io_32bit) {
+               scc_ide_insl(data_addr, buf, len / 4);
+
+               if ((len & 3) >= 2)
+                       scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1);
+       } else
+               scc_ide_insw(data_addr, buf, len / 2);
+}
+
+static void scc_output_data(ide_drive_t *drive,  struct request *rq,
+                           void *buf, unsigned int len)
+{
+       unsigned long data_addr = drive->hwif->io_ports.data_addr;
+
+       len++;
+
+       if (drive->io_32bit) {
+               scc_ide_outsl(data_addr, buf, len / 4);
+
+               if ((len & 3) >= 2)
+                       scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1);
+       } else
+               scc_ide_outsw(data_addr, buf, len / 2);
+}
+
+/**
+ *     init_mmio_iops_scc      -       set up the iops for MMIO
+ *     @hwif: interface to set up
+ *
+ */
+
+static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct scc_ports *ports = pci_get_drvdata(dev);
+       unsigned long dma_base = ports->dma;
+
+       ide_set_hwifdata(hwif, ports);
+
+       hwif->dma_base = dma_base;
+       hwif->config_data = ports->ctl;
+}
+
+/**
+ *     init_iops_scc   -       set up iops
+ *     @hwif: interface to set up
+ *
+ *     Do the basic setup for the SCC hardware interface
+ *     and then do the MMIO setup.
+ */
+
+static void __devinit init_iops_scc(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       hwif->hwif_data = NULL;
+       if (pci_get_drvdata(dev) == NULL)
+               return;
+       init_mmio_iops_scc(hwif);
+}
+
+static int __devinit scc_init_dma(ide_hwif_t *hwif,
+                                 const struct ide_port_info *d)
+{
+       return ide_allocate_dma_engine(hwif);
+}
+
+static u8 scc_cable_detect(ide_hwif_t *hwif)
+{
+       return ATA_CBL_PATA80;
+}
+
+/**
+ *     init_hwif_scc   -       set up hwif
+ *     @hwif: interface to set up
+ *
+ *     We do the basic set up of the interface structure. The SCC
+ *     requires several custom handlers so we override the default
+ *     ide DMA handlers appropriately.
+ */
+
+static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+{
+       /* PTERADD */
+       out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
+
+       if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
+               hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
+       else
+               hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
+}
+
+static const struct ide_tp_ops scc_tp_ops = {
+       .exec_command           = scc_exec_command,
+       .read_status            = scc_read_status,
+       .read_altstatus         = scc_read_altstatus,
+       .read_sff_dma_status    = scc_read_sff_dma_status,
+
+       .set_irq                = scc_set_irq,
+
+       .tf_load                = scc_tf_load,
+       .tf_read                = scc_tf_read,
+
+       .input_data             = scc_input_data,
+       .output_data            = scc_output_data,
+};
+
+static const struct ide_port_ops scc_port_ops = {
+       .set_pio_mode           = scc_set_pio_mode,
+       .set_dma_mode           = scc_set_dma_mode,
+       .udma_filter            = scc_udma_filter,
+       .cable_detect           = scc_cable_detect,
+};
+
+static const struct ide_dma_ops scc_dma_ops = {
+       .dma_host_set           = scc_dma_host_set,
+       .dma_setup              = scc_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = scc_dma_start,
+       .dma_end                = scc_dma_end,
+       .dma_test_irq           = scc_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+#define DECLARE_SCC_DEV(name_str)                      \
+  {                                                    \
+      .name            = name_str,                     \
+      .init_iops       = init_iops_scc,                \
+      .init_dma                = scc_init_dma,                 \
+      .init_hwif       = init_hwif_scc,                \
+      .tp_ops          = &scc_tp_ops,          \
+      .port_ops                = &scc_port_ops,                \
+      .dma_ops         = &scc_dma_ops,                 \
+      .host_flags      = IDE_HFLAG_SINGLE,             \
+      .pio_mask                = ATA_PIO4,                     \
+  }
+
+static const struct ide_port_info scc_chipsets[] __devinitdata = {
+       /* 0 */ DECLARE_SCC_DEV("sccIDE"),
+};
+
+/**
+ *     scc_init_one    -       pci layer discovery entry
+ *     @dev: PCI device
+ *     @id: ident table entry
+ *
+ *     Called by the PCI code when it finds an SCC PATA controller.
+ *     We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return init_setup_scc(dev, &scc_chipsets[id->driver_data]);
+}
+
+/**
+ *     scc_remove      -       pci layer remove entry
+ *     @dev: PCI device
+ *
+ *     Called by the PCI code when it removes an SCC PATA controller.
+ */
+
+static void __devexit scc_remove(struct pci_dev *dev)
+{
+       struct scc_ports *ports = pci_get_drvdata(dev);
+       struct ide_host *host = ports->host;
+
+       ide_host_remove(host);
+
+       iounmap((void*)ports->dma);
+       iounmap((void*)ports->ctl);
+       pci_release_selected_regions(dev, (1 << 2) - 1);
+       memset(ports, 0, sizeof(*ports));
+}
+
+static const struct pci_device_id scc_pci_tbl[] = {
+       { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
+
+static struct pci_driver scc_pci_driver = {
+       .name = "SCC IDE",
+       .id_table = scc_pci_tbl,
+       .probe = scc_init_one,
+       .remove = __devexit_p(scc_remove),
+};
+
+static int scc_ide_init(void)
+{
+       return ide_pci_register_driver(&scc_pci_driver);
+}
+
+module_init(scc_ide_init);
+/* -- No exit code?
+static void scc_ide_exit(void)
+{
+       ide_pci_unregister_driver(&scc_pci_driver);
+}
+module_exit(scc_ide_exit);
+ */
+
+
+MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
new file mode 100644 (file)
index 0000000..437bc91
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 1998-2000 Michel Aubry
+ * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
+ * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
+ * Portions copyright (c) 2001 Sun Microsystems
+ *
+ *
+ * RCC/ServerWorks IDE driver for Linux
+ *
+ *   OSB4: `Open South Bridge' IDE Interface (fn 1)
+ *         supports UDMA mode 2 (33 MB/s)
+ *
+ *   CSB5: `Champion South Bridge' IDE Interface (fn 1)
+ *         all revisions support UDMA mode 4 (66 MB/s)
+ *         revision A2.0 and up support UDMA mode 5 (100 MB/s)
+ *
+ *         *** The CSB5 does not provide ANY register ***
+ *         *** to detect 80-conductor cable presence. ***
+ *
+ *   CSB6: `Champion South Bridge' IDE Interface (optional: third channel)
+ *
+ *   HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE
+ *   controller same as the CSB6. Single channel ATA100 only.
+ *
+ * Documentation:
+ *     Available under NDA only. Errata info very hard to get.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "serverworks"
+
+#define SVWKS_CSB5_REVISION_NEW        0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
+#define SVWKS_CSB6_REVISION    0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
+
+/* Seagate Barracuda ATA IV Family drives in UDMA mode 5
+ * can overrun their FIFOs when used with the CSB5 */
+static const char *svwks_bad_ata100[] = {
+       "ST320011A",
+       "ST340016A",
+       "ST360021A",
+       "ST380021A",
+       NULL
+};
+
+static struct pci_dev *isa_dev;
+
+static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+{
+       char *m = (char *)&drive->id[ATA_ID_PROD];
+
+       while (*list)
+               if (!strcmp(*list++, m))
+                       return 1;
+       return 0;
+}
+
+static u8 svwks_udma_filter(ide_drive_t *drive)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u8 mask = 0;
+
+       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
+               return 0x1f;
+       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+               u32 reg = 0;
+               if (isa_dev)
+                       pci_read_config_dword(isa_dev, 0x64, &reg);
+                       
+               /*
+                *      Don't enable UDMA on disk devices for the moment
+                */
+               if(drive->media == ide_disk)
+                       return 0;
+               /* Check the OSB4 DMA33 enable bit */
+               return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
+       } else if (dev->revision < SVWKS_CSB5_REVISION_NEW) {
+               return 0x07;
+       } else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) {
+               u8 btr = 0, mode;
+               pci_read_config_byte(dev, 0x5A, &btr);
+               mode = btr & 0x3;
+
+               /* If someone decides to do UDMA133 on CSB5 the same
+                  issue will bite so be inclusive */
+               if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100))
+                       mode = 2;
+
+               switch(mode) {
+               case 3:  mask = 0x3f; break;
+               case 2:  mask = 0x1f; break;
+               case 1:  mask = 0x07; break;
+               default: mask = 0x00; break;
+               }
+       }
+       if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
+            (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
+           (!(PCI_FUNC(dev->devfn) & 1)))
+               mask = 0x1f;
+
+       return mask;
+}
+
+static u8 svwks_csb_check (struct pci_dev *dev)
+{
+       switch (dev->device) {
+               case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+               case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+               case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+               case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
+                       return 1;
+               default:
+                       break;
+       }
+       return 0;
+}
+
+static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+       static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
+
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+
+       pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
+
+       if (svwks_csb_check(dev)) {
+               u16 csb_pio = 0;
+
+               pci_read_config_word(dev, 0x4a, &csb_pio);
+
+               csb_pio &= ~(0x0f << (4 * drive->dn));
+               csb_pio |= (pio << (4 * drive->dn));
+
+               pci_write_config_word(dev, 0x4a, csb_pio);
+       }
+}
+
+static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       static const u8 udma_modes[]            = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+       static const u8 dma_modes[]             = { 0x77, 0x21, 0x20 };
+       static const u8 drive_pci2[]            = { 0x45, 0x44, 0x47, 0x46 };
+
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u8 unit                 = drive->dn & 1;
+
+       u8 ultra_enable  = 0, ultra_timing = 0, dma_timing = 0;
+
+       pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
+       pci_read_config_byte(dev, 0x54, &ultra_enable);
+
+       ultra_timing    &= ~(0x0F << (4*unit));
+       ultra_enable    &= ~(0x01 << drive->dn);
+
+       if (speed >= XFER_UDMA_0) {
+               dma_timing   |= dma_modes[2];
+               ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit));
+               ultra_enable |= (0x01 << drive->dn);
+       } else if (speed >= XFER_MW_DMA_0)
+               dma_timing   |= dma_modes[speed - XFER_MW_DMA_0];
+
+       pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
+       pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
+       pci_write_config_byte(dev, 0x54, ultra_enable);
+}
+
+static unsigned int init_chipset_svwks(struct pci_dev *dev)
+{
+       unsigned int reg;
+       u8 btr;
+
+       /* force Master Latency Timer value to 64 PCICLKs */
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
+
+       /* OSB4 : South Bridge and IDE */
+       if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+               isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
+                         PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
+               if (isa_dev) {
+                       pci_read_config_dword(isa_dev, 0x64, &reg);
+                       reg &= ~0x00002000; /* disable 600ns interrupt mask */
+                       if(!(reg & 0x00004000))
+                               printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS "
+                                       "enabled.\n", pci_name(dev));
+                       reg |=  0x00004000; /* enable UDMA/33 support */
+                       pci_write_config_dword(isa_dev, 0x64, reg);
+               }
+       }
+
+       /* setup CSB5/CSB6 : South Bridge and IDE option RAID */
+       else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ||
+                (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
+                (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
+
+               /* Third Channel Test */
+               if (!(PCI_FUNC(dev->devfn) & 1)) {
+                       struct pci_dev * findev = NULL;
+                       u32 reg4c = 0;
+                       findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
+                               PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
+                       if (findev) {
+                               pci_read_config_dword(findev, 0x4C, &reg4c);
+                               reg4c &= ~0x000007FF;
+                               reg4c |=  0x00000040;
+                               reg4c |=  0x00000020;
+                               pci_write_config_dword(findev, 0x4C, reg4c);
+                               pci_dev_put(findev);
+                       }
+                       outb_p(0x06, 0x0c00);
+                       dev->irq = inb_p(0x0c01);
+               } else {
+                       struct pci_dev * findev = NULL;
+                       u8 reg41 = 0;
+
+                       findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
+                                       PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL);
+                       if (findev) {
+                               pci_read_config_byte(findev, 0x41, &reg41);
+                               reg41 &= ~0x40;
+                               pci_write_config_byte(findev, 0x41, reg41);
+                               pci_dev_put(findev);
+                       }
+                       /*
+                        * This is a device pin issue on CSB6.
+                        * Since there will be a future raid mode,
+                        * early versions of the chipset require the
+                        * interrupt pin to be set, and it is a compatibility
+                        * mode issue.
+                        */
+                       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
+                               dev->irq = 0;
+               }
+//             pci_read_config_dword(dev, 0x40, &pioreg)
+//             pci_write_config_dword(dev, 0x40, 0x99999999);
+//             pci_read_config_dword(dev, 0x44, &dmareg);
+//             pci_write_config_dword(dev, 0x44, 0xFFFFFFFF);
+               /* setup the UDMA Control register
+                *
+                * 1. clear bit 6 to enable DMA
+                * 2. enable DMA modes with bits 0-1
+                *      00 : legacy
+                *      01 : udma2
+                *      10 : udma2/udma4
+                *      11 : udma2/udma4/udma5
+                */
+               pci_read_config_byte(dev, 0x5A, &btr);
+               btr &= ~0x40;
+               if (!(PCI_FUNC(dev->devfn) & 1))
+                       btr |= 0x2;
+               else
+                       btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+               pci_write_config_byte(dev, 0x5A, btr);
+       }
+       /* Setup HT1000 SouthBridge Controller - Single Channel Only */
+       else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) {
+               pci_read_config_byte(dev, 0x5A, &btr);
+               btr &= ~0x40;
+               btr |= 0x3;
+               pci_write_config_byte(dev, 0x5A, btr);
+       }
+
+       return dev->irq;
+}
+
+static u8 ata66_svwks_svwks(ide_hwif_t *hwif)
+{
+       return ATA_CBL_PATA80;
+}
+
+/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
+ * of the subsystem device ID indicate presence of an 80-pin cable.
+ * Bit 15 clear = secondary IDE channel does not have 80-pin cable.
+ * Bit 15 set   = secondary IDE channel has 80-pin cable.
+ * Bit 14 clear = primary IDE channel does not have 80-pin cable.
+ * Bit 14 set   = primary IDE channel has 80-pin cable.
+ */
+static u8 ata66_svwks_dell(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+           dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
+           (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
+            dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
+               return ((1 << (hwif->channel + 14)) &
+                       dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+       return ATA_CBL_PATA40;
+}
+
+/* Sun Cobalt Alpine hardware avoids the 80-pin cable
+ * detect issue by attaching the drives directly to the board.
+ * This check follows the Dell precedent (how scary is that?!)
+ *
+ * WARNING: this only works on Alpine hardware!
+ */
+static u8 ata66_svwks_cobalt(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
+           dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
+           dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
+               return ((1 << (hwif->channel + 14)) &
+                       dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+       return ATA_CBL_PATA40;
+}
+
+static u8 svwks_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+
+       /* Server Works */
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
+               return ata66_svwks_svwks (hwif);
+       
+       /* Dell PowerEdge */
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL)
+               return ata66_svwks_dell (hwif);
+
+       /* Cobalt Alpine */
+       if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN)
+               return ata66_svwks_cobalt (hwif);
+
+       /* Per Specified Design by OEM, and ASIC Architect */
+       if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
+           (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
+               return ATA_CBL_PATA80;
+
+       return ATA_CBL_PATA40;
+}
+
+static const struct ide_port_ops osb4_port_ops = {
+       .set_pio_mode           = svwks_set_pio_mode,
+       .set_dma_mode           = svwks_set_dma_mode,
+       .udma_filter            = svwks_udma_filter,
+};
+
+static const struct ide_port_ops svwks_port_ops = {
+       .set_pio_mode           = svwks_set_pio_mode,
+       .set_dma_mode           = svwks_set_dma_mode,
+       .udma_filter            = svwks_udma_filter,
+       .cable_detect           = svwks_cable_detect,
+};
+
+#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
+
+static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+       {       /* 0: OSB4 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_svwks,
+               .port_ops       = &osb4_port_ops,
+               .host_flags     = IDE_HFLAGS_SVWKS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = 0x00, /* UDMA is problematic on OSB4 */
+       },
+       {       /* 1: CSB5 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_svwks,
+               .port_ops       = &svwks_port_ops,
+               .host_flags     = IDE_HFLAGS_SVWKS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       },
+       {       /* 2: CSB6 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_svwks,
+               .port_ops       = &svwks_port_ops,
+               .host_flags     = IDE_HFLAGS_SVWKS,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       },
+       {       /* 3: CSB6-2 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_svwks,
+               .port_ops       = &svwks_port_ops,
+               .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       },
+       {       /* 4: HT1000 */
+               .name           = DRV_NAME,
+               .init_chipset   = init_chipset_svwks,
+               .port_ops       = &svwks_port_ops,
+               .host_flags     = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA5,
+       }
+};
+
+/**
+ *     svwks_init_one  -       called when a OSB/CSB is found
+ *     @dev: the svwks device
+ *     @id: the matching pci id
+ *
+ *     Called when the PCI registration layer (or the IDE initialization)
+ *     finds a device matching our IDE device tables.
+ */
+static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+
+       d = serverworks_chipsets[idx];
+
+       if (idx == 1)
+               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
+       else if (idx == 2 || idx == 3) {
+               if ((PCI_FUNC(dev->devfn) & 1) == 0) {
+                       if (pci_resource_start(dev, 0) != 0x01f1)
+                               d.host_flags |= IDE_HFLAG_NON_BOOTABLE;
+                       d.host_flags |= IDE_HFLAG_SINGLE;
+               } else
+                       d.host_flags &= ~IDE_HFLAG_SINGLE;
+       }
+
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static const struct pci_device_id svwks_pci_tbl[] = {
+       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE),   0 },
+       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE),   1 },
+       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE),   2 },
+       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2),  3 },
+       { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
+
+static struct pci_driver svwks_pci_driver = {
+       .name           = "Serverworks_IDE",
+       .id_table       = svwks_pci_tbl,
+       .probe          = svwks_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init svwks_ide_init(void)
+{
+       return ide_pci_register_driver(&svwks_pci_driver);
+}
+
+static void __exit svwks_ide_exit(void)
+{
+       pci_unregister_driver(&svwks_pci_driver);
+}
+
+module_init(svwks_ide_init);
+module_exit(svwks_ide_exit);
+
+MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c
new file mode 100644 (file)
index 0000000..8af9b23
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2008 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/scatterlist.h>
+#include <linux/ioc4.h>
+#include <asm/io.h>
+
+#include <linux/ide.h>
+
+#define DRV_NAME "SGIIOC4"
+
+/* IOC4 Specific Definitions */
+#define IOC4_CMD_OFFSET                0x100
+#define IOC4_CTRL_OFFSET       0x120
+#define IOC4_DMA_OFFSET                0x140
+#define IOC4_INTR_OFFSET       0x0
+
+#define IOC4_TIMING            0x00
+#define IOC4_DMA_PTR_L         0x01
+#define IOC4_DMA_PTR_H         0x02
+#define IOC4_DMA_ADDR_L                0x03
+#define IOC4_DMA_ADDR_H                0x04
+#define IOC4_BC_DEV            0x05
+#define IOC4_BC_MEM            0x06
+#define        IOC4_DMA_CTRL           0x07
+#define        IOC4_DMA_END_ADDR       0x08
+
+/* Bits in the IOC4 Control/Status Register */
+#define        IOC4_S_DMA_START        0x01
+#define        IOC4_S_DMA_STOP         0x02
+#define        IOC4_S_DMA_DIR          0x04
+#define        IOC4_S_DMA_ACTIVE       0x08
+#define        IOC4_S_DMA_ERROR        0x10
+#define        IOC4_ATA_MEMERR         0x02
+
+/* Read/Write Directions */
+#define        IOC4_DMA_WRITE          0x04
+#define        IOC4_DMA_READ           0x00
+
+/* Interrupt Register Offsets */
+#define IOC4_INTR_REG          0x03
+#define        IOC4_INTR_SET           0x05
+#define        IOC4_INTR_CLEAR         0x07
+
+#define IOC4_IDE_CACHELINE_SIZE        128
+#define IOC4_CMD_CTL_BLK_SIZE  0x20
+#define IOC4_SUPPORTED_FIRMWARE_REV 46
+
+typedef struct {
+       u32 timing_reg0;
+       u32 timing_reg1;
+       u32 low_mem_ptr;
+       u32 high_mem_ptr;
+       u32 low_mem_addr;
+       u32 high_mem_addr;
+       u32 dev_byte_count;
+       u32 mem_byte_count;
+       u32 status;
+} ioc4_dma_regs_t;
+
+/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */
+/* IOC4 has only 1 IDE channel */
+#define IOC4_PRD_BYTES       16
+#define IOC4_PRD_ENTRIES     (PAGE_SIZE /(4*IOC4_PRD_BYTES))
+
+
+static void
+sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+                       unsigned long ctrl_port, unsigned long irq_port)
+{
+       unsigned long reg = data_port;
+       int i;
+
+       /* Registers are word (32 bit) aligned */
+       for (i = 0; i <= 7; i++)
+               hw->io_ports_array[i] = reg + i * 4;
+
+       hw->io_ports.ctl_addr = ctrl_port;
+       hw->io_ports.irq_addr = irq_port;
+}
+
+static int
+sgiioc4_checkirq(ide_hwif_t * hwif)
+{
+       unsigned long intr_addr =
+               hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
+
+       if ((u8)readl((void __iomem *)intr_addr) & 0x03)
+               return 1;
+
+       return 0;
+}
+
+static u8 sgiioc4_read_status(ide_hwif_t *);
+
+static int
+sgiioc4_clearirq(ide_drive_t * drive)
+{
+       u32 intr_reg;
+       ide_hwif_t *hwif = HWIF(drive);
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2);
+
+       /* Code to check for PCI error conditions */
+       intr_reg = readl((void __iomem *)other_ir);
+       if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
+               /*
+                * Using sgiioc4_read_status to read the Status register has a
+                * side effect of clearing the interrupt.  The first read should
+                * clear it if it is set.  The second read should return
+                * a "clear" status if it got cleared.  If not, then spin
+                * for a bit trying to clear it.
+                */
+               u8 stat = sgiioc4_read_status(hwif);
+               int count = 0;
+
+               stat = sgiioc4_read_status(hwif);
+               while ((stat & ATA_BUSY) && (count++ < 100)) {
+                       udelay(1);
+                       stat = sgiioc4_read_status(hwif);
+               }
+
+               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;
+
+                       pci_err_addr_low =
+                               readl((void __iomem *)io_ports->irq_addr);
+                       pci_err_addr_high =
+                               readl((void __iomem *)(io_ports->irq_addr + 4));
+                       pci_read_config_dword(dev, PCI_COMMAND,
+                                             &pci_stat_cmd_reg);
+                       printk(KERN_ERR
+                              "%s(%s) : PCI Bus Error when doing DMA:"
+                                  " status-cmd reg is 0x%x\n",
+                              __func__, drive->name, pci_stat_cmd_reg);
+                       printk(KERN_ERR
+                              "%s(%s) : PCI Error Address is 0x%x%x\n",
+                              __func__, drive->name,
+                              pci_err_addr_high, pci_err_addr_low);
+                       /* Clear the PCI Error indicator */
+                       pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
+               }
+
+               /* Clear the Interrupt, Error bits on the IOC4 */
+               writel(0x03, (void __iomem *)other_ir);
+
+               intr_reg = readl((void __iomem *)other_ir);
+       }
+
+       return intr_reg & 3;
+}
+
+static void sgiioc4_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
+       unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
+       unsigned int temp_reg = reg | IOC4_S_DMA_START;
+
+       writel(temp_reg, (void __iomem *)ioc4_dma_addr);
+}
+
+static u32
+sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
+{
+       unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
+       u32     ioc4_dma;
+       int     count;
+
+       count = 0;
+       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
+       while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
+               udelay(1);
+               ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
+       }
+       return ioc4_dma;
+}
+
+/* Stops the IOC4 DMA Engine */
+static int sgiioc4_dma_end(ide_drive_t *drive)
+{
+       u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
+       ide_hwif_t *hwif = HWIF(drive);
+       unsigned long dma_base = hwif->dma_base;
+       int dma_stat = 0;
+       unsigned long *ending_dma = ide_get_hwifdata(hwif);
+
+       writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4));
+
+       ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
+
+       if (ioc4_dma & IOC4_S_DMA_STOP) {
+               printk(KERN_ERR
+                      "%s(%s): IOC4 DMA STOP bit is still 1 :"
+                      "ioc4_dma_reg 0x%x\n",
+                      __func__, drive->name, ioc4_dma);
+               dma_stat = 1;
+       }
+
+       /*
+        * The IOC4 will DMA 1's to the ending dma area to indicate that
+        * previous data DMA is complete.  This is necessary because of relaxed
+        * ordering between register reads and DMA writes on the Altix.
+        */
+       while ((cnt++ < 200) && (!valid)) {
+               for (num = 0; num < 16; num++) {
+                       if (ending_dma[num]) {
+                               valid = 1;
+                               break;
+                       }
+               }
+               udelay(1);
+       }
+       if (!valid) {
+               printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__,
+                      drive->name);
+               dma_stat = 1;
+       }
+
+       bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4));
+       bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4));
+
+       if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
+               if (bc_dev > bc_mem + 8) {
+                       printk(KERN_ERR
+                              "%s(%s): WARNING!! byte_count_dev %d "
+                              "!= byte_count_mem %d\n",
+                              __func__, drive->name, bc_dev, bc_mem);
+               }
+       }
+
+       drive->waiting_for_dma = 0;
+       ide_destroy_dmatable(drive);
+
+       return dma_stat;
+}
+
+static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+}
+
+/* returns 1 if dma irq issued, 0 otherwise */
+static int sgiioc4_dma_test_irq(ide_drive_t *drive)
+{
+       return sgiioc4_checkirq(HWIF(drive));
+}
+
+static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
+{
+       if (!on)
+               sgiioc4_clearirq(drive);
+}
+
+static void
+sgiioc4_resetproc(ide_drive_t * drive)
+{
+       sgiioc4_dma_end(drive);
+       sgiioc4_clearirq(drive);
+}
+
+static void
+sgiioc4_dma_lost_irq(ide_drive_t * drive)
+{
+       sgiioc4_resetproc(drive);
+
+       ide_dma_lost_irq(drive);
+}
+
+static u8 sgiioc4_read_status(ide_hwif_t *hwif)
+{
+       unsigned long port = hwif->io_ports.status_addr;
+       u8 reg = (u8) readb((void __iomem *) port);
+
+       if (!(reg & ATA_BUSY)) {        /* Not busy... check for interrupt */
+               unsigned long other_ir = port - 0x110;
+               unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
+
+               /* Clear the Interrupt, Error bits on the IOC4 */
+               if (intr_reg & 0x03) {
+                       writel(0x03, (void __iomem *) other_ir);
+                       intr_reg = (u32) readl((void __iomem *) other_ir);
+               }
+       }
+
+       return reg;
+}
+
+/* Creates a dma map for the scatter-gather list entries */
+static int __devinit
+ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
+       int num_ports = sizeof (ioc4_dma_regs_t);
+       void *pad;
+
+       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
+
+       if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
+               printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
+                      "already in use\n", __func__, hwif->name,
+                      dma_base, dma_base + num_ports - 1);
+               return -1;
+       }
+
+       hwif->dma_base = (unsigned long)hwif->io_ports.irq_addr +
+                        IOC4_DMA_OFFSET;
+
+       hwif->sg_max_nents = IOC4_PRD_ENTRIES;
+
+       hwif->prd_max_nents = IOC4_PRD_ENTRIES;
+       hwif->prd_ent_size = IOC4_PRD_BYTES;
+
+       if (ide_allocate_dma_engine(hwif))
+               goto dma_pci_alloc_failure;
+
+       pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
+                                  (dma_addr_t *)&hwif->extra_base);
+       if (pad) {
+               ide_set_hwifdata(hwif, pad);
+               return 0;
+       }
+
+       ide_release_dma_engine(hwif);
+
+       printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
+              __func__, hwif->name);
+       printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
+
+dma_pci_alloc_failure:
+       release_mem_region(dma_base, num_ports);
+
+       return -1;
+}
+
+/* Initializes the IOC4 DMA Engine */
+static void
+sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
+{
+       u32 ioc4_dma;
+       ide_hwif_t *hwif = HWIF(drive);
+       unsigned long dma_base = hwif->dma_base;
+       unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
+       u32 dma_addr, ending_dma_addr;
+
+       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
+
+       if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
+               printk(KERN_WARNING
+                       "%s(%s):Warning!! DMA from previous transfer was still active\n",
+                      __func__, drive->name);
+               writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
+               ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
+
+               if (ioc4_dma & IOC4_S_DMA_STOP)
+                       printk(KERN_ERR
+                              "%s(%s) : IOC4 Dma STOP bit is still 1\n",
+                              __func__, drive->name);
+       }
+
+       ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
+       if (ioc4_dma & IOC4_S_DMA_ERROR) {
+               printk(KERN_WARNING
+                      "%s(%s) : Warning!! - DMA Error during Previous"
+                      " transfer | status 0x%x\n",
+                      __func__, drive->name, ioc4_dma);
+               writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
+               ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
+
+               if (ioc4_dma & IOC4_S_DMA_STOP)
+                       printk(KERN_ERR
+                              "%s(%s) : IOC4 DMA STOP bit is still 1\n",
+                              __func__, drive->name);
+       }
+
+       /* Address of the Scatter Gather List */
+       dma_addr = cpu_to_le32(hwif->dmatable_dma);
+       writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4));
+
+       /* Address of the Ending DMA */
+       memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
+       ending_dma_addr = cpu_to_le32(hwif->extra_base);
+       writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
+
+       writel(dma_direction, (void __iomem *)ioc4_dma_addr);
+       drive->waiting_for_dma = 1;
+}
+
+/* IOC4 Scatter Gather list Format                                      */
+/* 128 Bit entries to support 64 bit addresses in the future            */
+/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format     */
+/* --------------------------------------------------------------------- */
+/* | Upper 32 bits - Zero           |          Lower 32 bits- address | */
+/* --------------------------------------------------------------------- */
+/* | Upper 32 bits - Zero          |EOL| 15 unused     | 16 Bit Length| */
+/* --------------------------------------------------------------------- */
+/* Creates the scatter gather list, DMA Table */
+static unsigned int
+sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       unsigned int *table = hwif->dmatable_cpu;
+       unsigned int count = 0, i = 1;
+       struct scatterlist *sg;
+
+       hwif->sg_nents = i = ide_build_sglist(drive, rq);
+
+       if (!i)
+               return 0;       /* sglist of length Zero */
+
+       sg = hwif->sg_table;
+       while (i && sg_dma_len(sg)) {
+               dma_addr_t cur_addr;
+               int cur_len;
+               cur_addr = sg_dma_address(sg);
+               cur_len = sg_dma_len(sg);
+
+               while (cur_len) {
+                       if (count++ >= IOC4_PRD_ENTRIES) {
+                               printk(KERN_WARNING
+                                      "%s: DMA table too small\n",
+                                      drive->name);
+                               goto use_pio_instead;
+                       } else {
+                               u32 bcount =
+                                   0x10000 - (cur_addr & 0xffff);
+
+                               if (bcount > cur_len)
+                                       bcount = cur_len;
+
+                               /* put the addr, length in
+                                * the IOC4 dma-table format */
+                               *table = 0x0;
+                               table++;
+                               *table = cpu_to_be32(cur_addr);
+                               table++;
+                               *table = 0x0;
+                               table++;
+
+                               *table = cpu_to_be32(bcount);
+                               table++;
+
+                               cur_addr += bcount;
+                               cur_len -= bcount;
+                       }
+               }
+
+               sg = sg_next(sg);
+               i--;
+       }
+
+       if (count) {
+               table--;
+               *table |= cpu_to_be32(0x80000000);
+               return count;
+       }
+
+use_pio_instead:
+       ide_destroy_dmatable(drive);
+
+       return 0;               /* revert to PIO for this request */
+}
+
+static int sgiioc4_dma_setup(ide_drive_t *drive)
+{
+       struct request *rq = HWGROUP(drive)->rq;
+       unsigned int count = 0;
+       int ddir;
+
+       if (rq_data_dir(rq))
+               ddir = PCI_DMA_TODEVICE;
+       else
+               ddir = PCI_DMA_FROMDEVICE;
+
+       if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) {
+               /* try PIO instead of DMA */
+               ide_map_sg(drive, rq);
+               return 1;
+       }
+
+       if (rq_data_dir(rq))
+               /* Writes TO the IOC4 FROM Main Memory */
+               ddir = IOC4_DMA_READ;
+       else
+               /* Writes FROM the IOC4 TO Main Memory */
+               ddir = IOC4_DMA_WRITE;
+
+       sgiioc4_configure_for_dma(ddir, drive);
+
+       return 0;
+}
+
+static const struct ide_tp_ops sgiioc4_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = sgiioc4_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
+static const struct ide_port_ops sgiioc4_port_ops = {
+       .set_dma_mode           = sgiioc4_set_dma_mode,
+       /* reset DMA engine, clear IRQs */
+       .resetproc              = sgiioc4_resetproc,
+};
+
+static const struct ide_dma_ops sgiioc4_dma_ops = {
+       .dma_host_set           = sgiioc4_dma_host_set,
+       .dma_setup              = sgiioc4_dma_setup,
+       .dma_start              = sgiioc4_dma_start,
+       .dma_end                = sgiioc4_dma_end,
+       .dma_test_irq           = sgiioc4_dma_test_irq,
+       .dma_lost_irq           = sgiioc4_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info sgiioc4_port_info __devinitdata = {
+       .name                   = DRV_NAME,
+       .chipset                = ide_pci,
+       .init_dma               = ide_dma_sgiioc4,
+       .tp_ops                 = &sgiioc4_tp_ops,
+       .port_ops               = &sgiioc4_port_ops,
+       .dma_ops                = &sgiioc4_dma_ops,
+       .host_flags             = IDE_HFLAG_MMIO,
+       .mwdma_mask             = ATA_MWDMA2_ONLY,
+};
+
+static int __devinit
+sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+{
+       unsigned long cmd_base, irqport;
+       unsigned long bar0, cmd_phys_base, ctl;
+       void __iomem *virt_base;
+       struct ide_host *host;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+       struct ide_port_info d = sgiioc4_port_info;
+       int rc;
+
+       /*  Get the CmdBlk and CtrlBlk Base Registers */
+       bar0 = pci_resource_start(dev, 0);
+       virt_base = ioremap(bar0, pci_resource_len(dev, 0));
+       if (virt_base == NULL) {
+               printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
+                               DRV_NAME, bar0);
+               return -ENOMEM;
+       }
+       cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
+       ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
+       irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
+
+       cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
+       if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+                              DRV_NAME) == NULL) {
+               printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
+                      "already in use\n", DRV_NAME, pci_name(dev),
+                      cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
+               return -EBUSY;
+       }
+
+       /* 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;
+
+       /* Initializing chipset IRQ Registers */
+       writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
+
+       host = ide_host_alloc(&d, hws);
+       if (host == NULL) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       rc = ide_host_register(host, &d, hws);
+       if (rc)
+               goto err_free;
+
+       return 0;
+err_free:
+       ide_host_free(host);
+err:
+       release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
+       iounmap(virt_base);
+       return rc;
+}
+
+static unsigned int __devinit
+pci_init_sgiioc4(struct pci_dev *dev)
+{
+       int ret;
+
+       printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
+                        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",
+                               DRV_NAME, pci_name(dev));
+               ret = -EAGAIN;
+               goto out;
+       }
+       ret = sgiioc4_ide_setup_pci_device(dev);
+out:
+       return ret;
+}
+
+int
+ioc4_ide_attach_one(struct ioc4_driver_data *idd)
+{
+       /* PCI-RT does not bring out IDE connection.
+        * Do not attach to this particular IOC4.
+        */
+       if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
+               return 0;
+
+       return pci_init_sgiioc4(idd->idd_pdev);
+}
+
+static struct ioc4_submodule ioc4_ide_submodule = {
+       .is_name = "IOC4_ide",
+       .is_owner = THIS_MODULE,
+       .is_probe = ioc4_ide_attach_one,
+/*     .is_remove = ioc4_ide_remove_one,       */
+};
+
+static int __init ioc4_ide_init(void)
+{
+       return ioc4_register_submodule(&ioc4_ide_submodule);
+}
+
+late_initcall(ioc4_ide_init); /* Call only after IDE init is done */
+
+MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
+MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
new file mode 100644 (file)
index 0000000..eb4faf9
--- /dev/null
@@ -0,0 +1,857 @@
+/*
+ * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003          Red Hat <alan@redhat.com>
+ * Copyright (C) 2007-2008     MontaVista Software, Inc.
+ * Copyright (C) 2007-2008     Bartlomiej Zolnierkiewicz
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ *
+ *  Documentation for CMD680:
+ *  http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2
+ *
+ *  Documentation for SiI 3112:
+ *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
+ *
+ *  Errata and other documentation only available under NDA.
+ *
+ *
+ *  FAQ Items:
+ *     If you are using Marvell SATA-IDE adapters with Maxtor drives
+ *     ensure the system is set up for ATA100/UDMA5, not UDMA6.
+ *
+ *     If you are using WD drives with SATA bridges you must set the
+ *     drive to "Single". "Master" will hang.
+ *
+ *     If you have strange problems with nVidia chipset systems please
+ *     see the SI support documentation and update your system BIOS
+ *     if necessary
+ *
+ *  The Dell DRAC4 has some interesting features including effectively hot
+ *  unplugging/replugging the virtual CD interface when the DRAC is reset.
+ *  This often causes drivers/ide/siimage to panic but is ok with the rather
+ *  smarter code in libata.
+ *
+ * TODO:
+ * - IORDY fixes
+ * - VDMA support
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#define DRV_NAME "siimage"
+
+/**
+ *     pdev_is_sata            -       check if device is SATA
+ *     @pdev:  PCI device to check
+ *
+ *     Returns true if this is a SATA controller
+ */
+
+static int pdev_is_sata(struct pci_dev *pdev)
+{
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_SII_3112:
+       case PCI_DEVICE_ID_SII_1210SA:
+               return 1;
+       case PCI_DEVICE_ID_SII_680:
+               return 0;
+       }
+       BUG();
+#endif
+       return 0;
+}
+
+/**
+ *     is_sata                 -       check if hwif is SATA
+ *     @hwif:  interface to check
+ *
+ *     Returns true if this is a SATA controller
+ */
+
+static inline int is_sata(ide_hwif_t *hwif)
+{
+       return pdev_is_sata(to_pci_dev(hwif->dev));
+}
+
+/**
+ *     siimage_selreg          -       return register base
+ *     @hwif: interface
+ *     @r: config offset
+ *
+ *     Turn a config register offset into the right address in either
+ *     PCI space or MMIO space to access the control register in question
+ *     Thankfully this is a configuration operation, so isn't performance
+ *     critical.
+ */
+
+static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
+{
+       unsigned long base = (unsigned long)hwif->hwif_data;
+
+       base += 0xA0 + r;
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               base += hwif->channel << 6;
+       else
+               base += hwif->channel << 4;
+       return base;
+}
+
+/**
+ *     siimage_seldev          -       return register base
+ *     @hwif: interface
+ *     @r: config offset
+ *
+ *     Turn a config register offset into the right address in either
+ *     PCI space or MMIO space to access the control register in question
+ *     including accounting for the unit shift.
+ */
+
+static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       unsigned long base      = (unsigned long)hwif->hwif_data;
+       u8 unit                 = drive->dn & 1;
+
+       base += 0xA0 + r;
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               base += hwif->channel << 6;
+       else
+               base += hwif->channel << 4;
+       base |= unit << unit;
+       return base;
+}
+
+static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       u8 tmp = 0;
+
+       if (host->host_priv)
+               tmp = readb((void __iomem *)addr);
+       else
+               pci_read_config_byte(dev, addr, &tmp);
+
+       return tmp;
+}
+
+static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       u16 tmp = 0;
+
+       if (host->host_priv)
+               tmp = readw((void __iomem *)addr);
+       else
+               pci_read_config_word(dev, addr, &tmp);
+
+       return tmp;
+}
+
+static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       if (host->host_priv)
+               writeb(val, (void __iomem *)addr);
+       else
+               pci_write_config_byte(dev, addr, val);
+}
+
+static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       if (host->host_priv)
+               writew(val, (void __iomem *)addr);
+       else
+               pci_write_config_word(dev, addr, val);
+}
+
+static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       if (host->host_priv)
+               writel(val, (void __iomem *)addr);
+       else
+               pci_write_config_dword(dev, addr, val);
+}
+
+/**
+ *     sil_udma_filter         -       compute UDMA mask
+ *     @drive: IDE device
+ *
+ *     Compute the available UDMA speeds for the device on the interface.
+ *
+ *     For the CMD680 this depends on the clocking mode (scsc), for the
+ *     SI3112 SATA controller life is a bit simpler.
+ */
+
+static u8 sil_pata_udma_filter(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = drive->hwif;
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned long base      = (unsigned long)hwif->hwif_data;
+       u8 scsc, mask           = 0;
+
+       base += (hwif->host_flags & IDE_HFLAG_MMIO) ? 0x4A : 0x8A;
+
+       scsc = sil_ioread8(dev, base);
+
+       switch (scsc & 0x30) {
+       case 0x10:      /* 133 */
+               mask = ATA_UDMA6;
+               break;
+       case 0x20:      /* 2xPCI */
+               mask = ATA_UDMA6;
+               break;
+       case 0x00:      /* 100 */
+               mask = ATA_UDMA5;
+               break;
+       default:        /* Disabled ? */
+               BUG();
+       }
+
+       return mask;
+}
+
+static u8 sil_sata_udma_filter(ide_drive_t *drive)
+{
+       char *m = (char *)&drive->id[ATA_ID_PROD];
+
+       return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
+}
+
+/**
+ *     sil_set_pio_mode        -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     Load the timing settings for this device mode into the
+ *     controller. If we are in PIO mode 3 or 4 turn on IORDY
+ *     monitoring (bit 9). The TF timing is bits 31:16
+ */
+
+static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+       static const u16 tf_speed[]   = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
+       static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
+
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       ide_drive_t *pair       = ide_get_pair_dev(drive);
+       u32 speedt              = 0;
+       u16 speedp              = 0;
+       unsigned long addr      = siimage_seldev(drive, 0x04);
+       unsigned long tfaddr    = siimage_selreg(hwif,  0x02);
+       unsigned long base      = (unsigned long)hwif->hwif_data;
+       u8 tf_pio               = pio;
+       u8 mmio                 = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+       u8 addr_mask            = hwif->channel ? (mmio ? 0xF4 : 0x84)
+                                               : (mmio ? 0xB4 : 0x80);
+       u8 mode                 = 0;
+       u8 unit                 = drive->dn & 1;
+
+       /* trim *taskfile* PIO to the slowest of the master/slave */
+       if (pair) {
+               u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
+
+               if (pair_pio < tf_pio)
+                       tf_pio = pair_pio;
+       }
+
+       /* cheat for now and use the docs */
+       speedp = data_speed[pio];
+       speedt = tf_speed[tf_pio];
+
+       sil_iowrite16(dev, speedp, addr);
+       sil_iowrite16(dev, speedt, tfaddr);
+
+       /* now set up IORDY */
+       speedp = sil_ioread16(dev, tfaddr - 2);
+       speedp &= ~0x200;
+       if (pio > 2)
+               speedp |= 0x200;
+       sil_iowrite16(dev, speedp, tfaddr - 2);
+
+       mode = sil_ioread8(dev, base + addr_mask);
+       mode &= ~(unit ? 0x30 : 0x03);
+       mode |= unit ? 0x10 : 0x01;
+       sil_iowrite8(dev, mode, base + addr_mask);
+}
+
+/**
+ *     sil_set_dma_mode        -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
+ *
+ *     Tune the SiI chipset for the desired DMA mode.
+ */
+
+static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
+       static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
+       static const u16 dma[]   = { 0x2208, 0x10C2, 0x10C1 };
+
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned long base      = (unsigned long)hwif->hwif_data;
+       u16 ultra = 0, multi    = 0;
+       u8 mode = 0, unit       = drive->dn & 1;
+       u8 mmio                 = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+       u8 scsc = 0, addr_mask  = hwif->channel ? (mmio ? 0xF4 : 0x84)
+                                               : (mmio ? 0xB4 : 0x80);
+       unsigned long ma        = siimage_seldev(drive, 0x08);
+       unsigned long ua        = siimage_seldev(drive, 0x0C);
+
+       scsc  = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A));
+       mode  = sil_ioread8 (dev, base + addr_mask);
+       multi = sil_ioread16(dev, ma);
+       ultra = sil_ioread16(dev, ua);
+
+       mode  &= ~(unit ? 0x30 : 0x03);
+       ultra &= ~0x3F;
+       scsc = ((scsc & 0x30) == 0x00) ? 0 : 1;
+
+       scsc = is_sata(hwif) ? 1 : scsc;
+
+       if (speed >= XFER_UDMA_0) {
+               multi  = dma[2];
+               ultra |= scsc ? ultra6[speed - XFER_UDMA_0] :
+                               ultra5[speed - XFER_UDMA_0];
+               mode  |= unit ? 0x30 : 0x03;
+       } else {
+               multi = dma[speed - XFER_MW_DMA_0];
+               mode |= unit ? 0x20 : 0x02;
+       }
+
+       sil_iowrite8 (dev, mode, base + addr_mask);
+       sil_iowrite16(dev, multi, ma);
+       sil_iowrite16(dev, ultra, ua);
+}
+
+/* returns 1 if dma irq issued, 0 otherwise */
+static int siimage_io_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u8 dma_altstat          = 0;
+       unsigned long addr      = siimage_selreg(hwif, 1);
+
+       /* return 1 if INTR asserted */
+       if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
+               return 1;
+
+       /* return 1 if Device INTR asserted */
+       pci_read_config_byte(dev, addr, &dma_altstat);
+       if (dma_altstat & 8)
+               return 0;       /* return 1; */
+
+       return 0;
+}
+
+/**
+ *     siimage_mmio_dma_test_irq       -       check we caused an IRQ
+ *     @drive: drive we are testing
+ *
+ *     Check if we caused an IDE DMA interrupt. We may also have caused
+ *     SATA status interrupts, if so we clean them up and continue.
+ */
+
+static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       unsigned long addr      = siimage_selreg(hwif, 0x1);
+       void __iomem *sata_error_addr
+               = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
+
+       if (sata_error_addr) {
+               unsigned long base      = (unsigned long)hwif->hwif_data;
+               u32 ext_stat            = readl((void __iomem *)(base + 0x10));
+               u8 watchdog             = 0;
+
+               if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
+                       u32 sata_error = readl(sata_error_addr);
+
+                       writel(sata_error, sata_error_addr);
+                       watchdog = (sata_error & 0x00680000) ? 1 : 0;
+                       printk(KERN_WARNING "%s: sata_error = 0x%08x, "
+                               "watchdog = %d, %s\n",
+                               drive->name, sata_error, watchdog, __func__);
+               } else
+                       watchdog = (ext_stat & 0x8000) ? 1 : 0;
+
+               ext_stat >>= 16;
+               if (!(ext_stat & 0x0404) && !watchdog)
+                       return 0;
+       }
+
+       /* return 1 if INTR asserted */
+       if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
+               return 1;
+
+       /* return 1 if Device INTR asserted */
+       if (readb((void __iomem *)addr) & 8)
+               return 0;       /* return 1; */
+
+       return 0;
+}
+
+static int siimage_dma_test_irq(ide_drive_t *drive)
+{
+       if (drive->hwif->host_flags & IDE_HFLAG_MMIO)
+               return siimage_mmio_dma_test_irq(drive);
+       else
+               return siimage_io_dma_test_irq(drive);
+}
+
+/**
+ *     sil_sata_reset_poll     -       wait for SATA reset
+ *     @drive: drive we are resetting
+ *
+ *     Poll the SATA phy and see whether it has come back from the dead
+ *     yet.
+ */
+
+static int sil_sata_reset_poll(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       void __iomem *sata_status_addr
+               = (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET];
+
+       if (sata_status_addr) {
+               /* SATA Status is available only when in MMIO mode */
+               u32 sata_stat = readl(sata_status_addr);
+
+               if ((sata_stat & 0x03) != 0x03) {
+                       printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
+                                           hwif->name, sata_stat);
+                       return -ENXIO;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ *     sil_sata_pre_reset      -       reset hook
+ *     @drive: IDE device being reset
+ *
+ *     For the SATA devices we need to handle recalibration/geometry
+ *     differently
+ */
+
+static void sil_sata_pre_reset(ide_drive_t *drive)
+{
+       if (drive->media == ide_disk) {
+               drive->special.b.set_geometry = 0;
+               drive->special.b.recalibrate = 0;
+       }
+}
+
+/**
+ *     init_chipset_siimage    -       set up an SI device
+ *     @dev: PCI device
+ *
+ *     Perform the initial PCI set up for this device. Attempt to switch
+ *     to 133 MHz clocking if the system isn't already set up to do it.
+ */
+
+static unsigned int init_chipset_siimage(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       void __iomem *ioaddr = host->host_priv;
+       unsigned long base, scsc_addr;
+       u8 rev = dev->revision, tmp;
+
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
+
+       if (ioaddr)
+               pci_set_master(dev);
+
+       base = (unsigned long)ioaddr;
+
+       if (ioaddr && pdev_is_sata(dev)) {
+               u32 tmp32, irq_mask;
+
+               /* make sure IDE0/1 interrupts are not masked */
+               irq_mask = (1 << 22) | (1 << 23);
+               tmp32 = readl(ioaddr + 0x48);
+               if (tmp32 & irq_mask) {
+                       tmp32 &= ~irq_mask;
+                       writel(tmp32, ioaddr + 0x48);
+                       readl(ioaddr + 0x48); /* flush */
+               }
+               writel(0, ioaddr + 0x148);
+               writel(0, ioaddr + 0x1C8);
+       }
+
+       sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80);
+       sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84);
+
+       scsc_addr = base ? (base + 0x4A) : 0x8A;
+       tmp = sil_ioread8(dev, scsc_addr);
+
+       switch (tmp & 0x30) {
+       case 0x00:
+               /* On 100 MHz clocking, try and switch to 133 MHz */
+               sil_iowrite8(dev, tmp | 0x10, scsc_addr);
+               break;
+       case 0x30:
+               /* Clocking is disabled, attempt to force 133MHz clocking. */
+               sil_iowrite8(dev, tmp & ~0x20, scsc_addr);
+       case 0x10:
+               /* On 133Mhz clocking. */
+               break;
+       case 0x20:
+               /* On PCIx2 clocking. */
+               break;
+       }
+
+       tmp = sil_ioread8(dev, scsc_addr);
+
+       sil_iowrite8 (dev,       0x72, base + 0xA1);
+       sil_iowrite16(dev,     0x328A, base + 0xA2);
+       sil_iowrite32(dev, 0x62DD62DD, base + 0xA4);
+       sil_iowrite32(dev, 0x43924392, base + 0xA8);
+       sil_iowrite32(dev, 0x40094009, base + 0xAC);
+       sil_iowrite8 (dev,       0x72, base ? (base + 0xE1) : 0xB1);
+       sil_iowrite16(dev,     0x328A, base ? (base + 0xE2) : 0xB2);
+       sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4);
+       sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8);
+       sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC);
+
+       if (base && pdev_is_sata(dev)) {
+               writel(0xFFFF0000, ioaddr + 0x108);
+               writel(0xFFFF0000, ioaddr + 0x188);
+               writel(0x00680000, ioaddr + 0x148);
+               writel(0x00680000, ioaddr + 0x1C8);
+       }
+
+       /* report the clocking mode of the controller */
+       if (!pdev_is_sata(dev)) {
+               static const char *clk_str[] =
+                       { "== 100", "== 133", "== 2X PCI", "DISABLED!" };
+
+               tmp >>= 4;
+               printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n",
+                       pci_name(dev), clk_str[tmp & 3]);
+       }
+
+       return 0;
+}
+
+/**
+ *     init_mmio_iops_siimage  -       set up the iops for MMIO
+ *     @hwif: interface to set up
+ *
+ *     The basic setup here is fairly simple, we can use standard MMIO
+ *     operations. However we do have to set the taskfile register offsets
+ *     by hand as there isn't a standard defined layout for them this time.
+ *
+ *     The hardware supports buffered taskfiles and also some rather nice
+ *     extended PRD tables. For better SI3112 support use the libata driver
+ */
+
+static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       struct ide_host *host   = pci_get_drvdata(dev);
+       void *addr              = host->host_priv;
+       u8 ch                   = hwif->channel;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       unsigned long base;
+
+       /*
+        *      Fill in the basic hwif bits
+        */
+       hwif->host_flags |= IDE_HFLAG_MMIO;
+
+       hwif->hwif_data = addr;
+
+       /*
+        *      Now set up the hw. We have to do this ourselves as the
+        *      MMIO layout isn't the same as the standard port based I/O.
+        */
+       memset(io_ports, 0, sizeof(*io_ports));
+
+       base = (unsigned long)addr;
+       if (ch)
+               base += 0xC0;
+       else
+               base += 0x80;
+
+       /*
+        *      The buffered task file doesn't have status/control, so we
+        *      can't currently use it sanely since we want to use LBA48 mode.
+        */
+       io_ports->data_addr     = base;
+       io_ports->error_addr    = base + 1;
+       io_ports->nsect_addr    = base + 2;
+       io_ports->lbal_addr     = base + 3;
+       io_ports->lbam_addr     = base + 4;
+       io_ports->lbah_addr     = base + 5;
+       io_ports->device_addr   = base + 6;
+       io_ports->status_addr   = base + 7;
+       io_ports->ctl_addr      = base + 10;
+
+       if (pdev_is_sata(dev)) {
+               base = (unsigned long)addr;
+               if (ch)
+                       base += 0x80;
+               hwif->sata_scr[SATA_STATUS_OFFSET]      = base + 0x104;
+               hwif->sata_scr[SATA_ERROR_OFFSET]       = base + 0x108;
+               hwif->sata_scr[SATA_CONTROL_OFFSET]     = base + 0x100;
+       }
+
+       hwif->irq = dev->irq;
+
+       hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
+}
+
+static int is_dev_seagate_sata(ide_drive_t *drive)
+{
+       const char *s   = (const char *)&drive->id[ATA_ID_PROD];
+       unsigned len    = strnlen(s, ATA_ID_PROD_LEN);
+
+       if ((len > 4) && (!memcmp(s, "ST", 2)))
+               if ((!memcmp(s + len - 2, "AS", 2)) ||
+                   (!memcmp(s + len - 3, "ASL", 3))) {
+                       printk(KERN_INFO "%s: applying pessimistic Seagate "
+                                        "errata fix\n", drive->name);
+                       return 1;
+               }
+
+       return 0;
+}
+
+/**
+ *     sil_quirkproc           -       post probe fixups
+ *     @drive: drive
+ *
+ *     Called after drive probe we use this to decide whether the
+ *     Seagate fixup must be applied. This used to be in init_iops but
+ *     that can occur before we know what drives are present.
+ */
+
+static void sil_quirkproc(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+
+       /* Try and rise the rqsize */
+       if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
+               hwif->rqsize = 128;
+}
+
+/**
+ *     init_iops_siimage       -       set up iops
+ *     @hwif: interface to set up
+ *
+ *     Do the basic setup for the SIIMAGE hardware interface
+ *     and then do the MMIO setup if we can. This is the first
+ *     look in we get for setting up the hwif so that we
+ *     can get the iops right before using them.
+ */
+
+static void __devinit init_iops_siimage(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_host *host = pci_get_drvdata(dev);
+
+       hwif->hwif_data = NULL;
+
+       /* Pessimal until we finish probing */
+       hwif->rqsize = 15;
+
+       if (host->host_priv)
+               init_mmio_iops_siimage(hwif);
+}
+
+/**
+ *     sil_cable_detect        -       cable detection
+ *     @hwif: interface to check
+ *
+ *     Check for the presence of an ATA66 capable cable on the interface.
+ */
+
+static u8 sil_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned long addr      = siimage_selreg(hwif, 0);
+       u8 ata66                = sil_ioread8(dev, addr);
+
+       return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+}
+
+static const struct ide_port_ops sil_pata_port_ops = {
+       .set_pio_mode           = sil_set_pio_mode,
+       .set_dma_mode           = sil_set_dma_mode,
+       .quirkproc              = sil_quirkproc,
+       .udma_filter            = sil_pata_udma_filter,
+       .cable_detect           = sil_cable_detect,
+};
+
+static const struct ide_port_ops sil_sata_port_ops = {
+       .set_pio_mode           = sil_set_pio_mode,
+       .set_dma_mode           = sil_set_dma_mode,
+       .reset_poll             = sil_sata_reset_poll,
+       .pre_reset              = sil_sata_pre_reset,
+       .quirkproc              = sil_quirkproc,
+       .udma_filter            = sil_sata_udma_filter,
+       .cable_detect           = sil_cable_detect,
+};
+
+static const struct ide_dma_ops sil_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           = siimage_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+};
+
+#define DECLARE_SII_DEV(p_ops)                         \
+       {                                               \
+               .name           = DRV_NAME,             \
+               .init_chipset   = init_chipset_siimage, \
+               .init_iops      = init_iops_siimage,    \
+               .port_ops       = p_ops,                \
+               .dma_ops        = &sil_dma_ops,         \
+               .pio_mask       = ATA_PIO4,             \
+               .mwdma_mask     = ATA_MWDMA2,           \
+               .udma_mask      = ATA_UDMA6,            \
+       }
+
+static const struct ide_port_info siimage_chipsets[] __devinitdata = {
+       /* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
+       /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
+};
+
+/**
+ *     siimage_init_one        -       PCI layer discovery entry
+ *     @dev: PCI device
+ *     @id: ident table entry
+ *
+ *     Called by the PCI code when it finds an SiI680 or SiI3112 controller.
+ *     We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit siimage_init_one(struct pci_dev *dev,
+                                     const struct pci_device_id *id)
+{
+       void __iomem *ioaddr = NULL;
+       resource_size_t bar5 = pci_resource_start(dev, 5);
+       unsigned long barsize = pci_resource_len(dev, 5);
+       int rc;
+       struct ide_port_info d;
+       u8 idx = id->driver_data;
+       u8 BA5_EN;
+
+       d = siimage_chipsets[idx];
+
+       if (idx) {
+               static int first = 1;
+
+               if (first) {
+                       printk(KERN_INFO DRV_NAME ": For full SATA support you "
+                               "should use the libata sata_sil module.\n");
+                       first = 0;
+               }
+
+               d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+       }
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               return rc;
+
+       pci_read_config_byte(dev, 0x8A, &BA5_EN);
+       if ((BA5_EN & 0x01) || bar5) {
+               /*
+               * Drop back to PIO if we can't map the MMIO. Some systems
+               * seem to get terminally confused in the PCI spaces.
+               */
+               if (!request_mem_region(bar5, barsize, d.name)) {
+                       printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
+                               "available\n", pci_name(dev));
+               } else {
+                       ioaddr = ioremap(bar5, barsize);
+                       if (ioaddr == NULL)
+                               release_mem_region(bar5, barsize);
+               }
+       }
+
+       rc = ide_pci_init_one(dev, &d, ioaddr);
+       if (rc) {
+               if (ioaddr) {
+                       iounmap(ioaddr);
+                       release_mem_region(bar5, barsize);
+               }
+               pci_disable_device(dev);
+       }
+
+       return rc;
+}
+
+static void __devexit siimage_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       void __iomem *ioaddr = host->host_priv;
+
+       ide_pci_remove(dev);
+
+       if (ioaddr) {
+               resource_size_t bar5 = pci_resource_start(dev, 5);
+               unsigned long barsize = pci_resource_len(dev, 5);
+
+               iounmap(ioaddr);
+               release_mem_region(bar5, barsize);
+       }
+
+       pci_disable_device(dev);
+}
+
+static const struct pci_device_id siimage_pci_tbl[] = {
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680),    0 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112),   1 },
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
+#endif
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
+
+static struct pci_driver siimage_pci_driver = {
+       .name           = "SiI_IDE",
+       .id_table       = siimage_pci_tbl,
+       .probe          = siimage_init_one,
+       .remove         = __devexit_p(siimage_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init siimage_ide_init(void)
+{
+       return ide_pci_register_driver(&siimage_pci_driver);
+}
+
+static void __exit siimage_ide_exit(void)
+{
+       pci_unregister_driver(&siimage_pci_driver);
+}
+
+module_init(siimage_ide_init);
+module_exit(siimage_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick, Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for SiI IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
new file mode 100644 (file)
index 0000000..ad32e18
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 1999-2000     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2002          Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
+ * Copyright (C) 2003          Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ *
+ * Thanks :
+ *
+ * SiS Taiwan          : for direct support and hardware.
+ * Daniela Engert      : for initial ATA100 advices and numerous others.
+ * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt       :
+ *                       for checking code correctness, providing patches.
+ *
+ *
+ * Original tests and design on the SiS620 chipset.
+ * ATA100 tests and design on the SiS735 chipset.
+ * ATA16/33 support from specs
+ * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw>
+ * ATA133 961/962/963 fixes by Vojtech Pavlik <vojtech@suse.cz>
+ *
+ * Documentation:
+ *     SiS chipset documentation available under NDA to companies only
+ *      (not to individuals).
+ */
+
+/*
+ * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original
+ * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511
+ * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip.
+ *
+ * Later SiS chipsets integrated the 5513 functionality into the NorthBridge,
+ * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We
+ * can figure out that we have a more modern and more capable 5513 by looking
+ * for the respective NorthBridge IDs.
+ *
+ * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513
+ * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI
+ * ID, while the now ATA-133 capable 5513 still has the same PCI ID.
+ * Fortunately the 5513 can be 'unmasked' by fiddling with some config space
+ * bits, changing its device id to the true one - 5517 for 961 and 5518 for
+ * 962/963.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#define DRV_NAME "sis5513"
+
+/* registers layout and init values are chipset family dependant */
+
+#define ATA_16         0x01
+#define ATA_33         0x02
+#define ATA_66         0x03
+#define ATA_100a       0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
+#define ATA_100                0x05
+#define ATA_133a       0x06 /* SiS961b with 133 support */
+#define ATA_133                0x07 /* SiS962/963 */
+
+static u8 chipset_family;
+
+/*
+ * Devices supported
+ */
+static const struct {
+       const char *name;
+       u16 host_id;
+       u8 chipset_family;
+       u8 flags;
+} SiSHostChipInfo[] = {
+       { "SiS968",     PCI_DEVICE_ID_SI_968,   ATA_133  },
+       { "SiS966",     PCI_DEVICE_ID_SI_966,   ATA_133  },
+       { "SiS965",     PCI_DEVICE_ID_SI_965,   ATA_133  },
+       { "SiS745",     PCI_DEVICE_ID_SI_745,   ATA_100  },
+       { "SiS735",     PCI_DEVICE_ID_SI_735,   ATA_100  },
+       { "SiS733",     PCI_DEVICE_ID_SI_733,   ATA_100  },
+       { "SiS635",     PCI_DEVICE_ID_SI_635,   ATA_100  },
+       { "SiS633",     PCI_DEVICE_ID_SI_633,   ATA_100  },
+
+       { "SiS730",     PCI_DEVICE_ID_SI_730,   ATA_100a },
+       { "SiS550",     PCI_DEVICE_ID_SI_550,   ATA_100a },
+
+       { "SiS640",     PCI_DEVICE_ID_SI_640,   ATA_66   },
+       { "SiS630",     PCI_DEVICE_ID_SI_630,   ATA_66   },
+       { "SiS620",     PCI_DEVICE_ID_SI_620,   ATA_66   },
+       { "SiS540",     PCI_DEVICE_ID_SI_540,   ATA_66   },
+       { "SiS530",     PCI_DEVICE_ID_SI_530,   ATA_66   },
+
+       { "SiS5600",    PCI_DEVICE_ID_SI_5600,  ATA_33   },
+       { "SiS5598",    PCI_DEVICE_ID_SI_5598,  ATA_33   },
+       { "SiS5597",    PCI_DEVICE_ID_SI_5597,  ATA_33   },
+       { "SiS5591/2",  PCI_DEVICE_ID_SI_5591,  ATA_33   },
+       { "SiS5582",    PCI_DEVICE_ID_SI_5582,  ATA_33   },
+       { "SiS5581",    PCI_DEVICE_ID_SI_5581,  ATA_33   },
+
+       { "SiS5596",    PCI_DEVICE_ID_SI_5596,  ATA_16   },
+       { "SiS5571",    PCI_DEVICE_ID_SI_5571,  ATA_16   },
+       { "SiS5517",    PCI_DEVICE_ID_SI_5517,  ATA_16   },
+       { "SiS551x",    PCI_DEVICE_ID_SI_5511,  ATA_16   },
+};
+
+/* Cycle time bits and values vary across chip dma capabilities
+   These three arrays hold the register layout and the values to set.
+   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
+
+/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
+static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
+static u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
+static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
+       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       {  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       {  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
+       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
+       {  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
+                                     different cycle_time range and offset */
+       { 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
+       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
+       { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
+};
+/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
+   See SiS962 data sheet for more detail */
+static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
+       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
+       { 2, 1, 1, 0, 0, 0, 0 },
+       { 4, 3, 2, 1, 0, 0, 0 },
+       { 4, 3, 2, 1, 0, 0, 0 },
+       { 6, 4, 3, 1, 1, 1, 0 },
+       { 9, 6, 4, 2, 2, 2, 2 },
+       { 9, 6, 4, 2, 2, 2, 2 },
+};
+/* Initialize time, Active time, Recovery time vary across
+   IDE clock settings. These 3 arrays hold the register value
+   for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
+static u8 ini_time_value[][8] = {
+       { 0, 0, 0, 0, 0, 0, 0, 0 },
+       { 0, 0, 0, 0, 0, 0, 0, 0 },
+       { 2, 1, 0, 0, 0, 1, 0, 0 },
+       { 4, 3, 1, 1, 1, 3, 1, 1 },
+       { 4, 3, 1, 1, 1, 3, 1, 1 },
+       { 6, 4, 2, 2, 2, 4, 2, 2 },
+       { 9, 6, 3, 3, 3, 6, 3, 3 },
+       { 9, 6, 3, 3, 3, 6, 3, 3 },
+};
+static u8 act_time_value[][8] = {
+       {  0,  0,  0,  0, 0,  0,  0, 0 },
+       {  0,  0,  0,  0, 0,  0,  0, 0 },
+       {  9,  9,  9,  2, 2,  7,  2, 2 },
+       { 19, 19, 19,  5, 4, 14,  5, 4 },
+       { 19, 19, 19,  5, 4, 14,  5, 4 },
+       { 28, 28, 28,  7, 6, 21,  7, 6 },
+       { 38, 38, 38, 10, 9, 28, 10, 9 },
+       { 38, 38, 38, 10, 9, 28, 10, 9 },
+};
+static u8 rco_time_value[][8] = {
+       {  0,  0, 0,  0, 0,  0,  0, 0 },
+       {  0,  0, 0,  0, 0,  0,  0, 0 },
+       {  9,  2, 0,  2, 0,  7,  1, 1 },
+       { 19,  5, 1,  5, 2, 16,  3, 2 },
+       { 19,  5, 1,  5, 2, 16,  3, 2 },
+       { 30,  9, 3,  9, 4, 25,  6, 4 },
+       { 40, 12, 4, 12, 5, 34, 12, 5 },
+       { 40, 12, 4, 12, 5, 34, 12, 5 },
+};
+
+/*
+ * Printing configuration
+ */
+/* Used for chipset type printing at boot time */
+static char *chipset_capability[] = {
+       "ATA", "ATA 16",
+       "ATA 33", "ATA 66",
+       "ATA 100 (1st gen)", "ATA 100 (2nd gen)",
+       "ATA 133 (1st gen)", "ATA 133 (2nd gen)"
+};
+
+/*
+ * Configuration functions
+ */
+
+static u8 sis_ata133_get_base(ide_drive_t *drive)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u32 reg54 = 0;
+
+       pci_read_config_dword(dev, 0x54, &reg54);
+
+       return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
+}
+
+static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u16 t1 = 0;
+       u8 drive_pci = 0x40 + drive->dn * 2;
+
+       const u16 pio_timings[]   = { 0x000, 0x607, 0x404, 0x303, 0x301 };
+       const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 };
+
+       pci_read_config_word(dev, drive_pci, &t1);
+
+       /* clear active/recovery timings */
+       t1 &= ~0x070f;
+       if (mode >= XFER_MW_DMA_0) {
+               if (chipset_family > ATA_16)
+                       t1 &= ~0x8000;  /* disable UDMA */
+               t1 |= mwdma_timings[mode - XFER_MW_DMA_0];
+       } else
+               t1 |= pio_timings[mode - XFER_PIO_0];
+
+       pci_write_config_word(dev, drive_pci, t1);
+}
+
+static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u8 t1, drive_pci = 0x40 + drive->dn * 2;
+
+       /* timing bits: 7:4 active 3:0 recovery */
+       const u8 pio_timings[]   = { 0x00, 0x67, 0x44, 0x33, 0x31 };
+       const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 };
+
+       if (mode >= XFER_MW_DMA_0) {
+               u8 t2 = 0;
+
+               pci_read_config_byte(dev, drive_pci, &t2);
+               t2 &= ~0x80;    /* disable UDMA */
+               pci_write_config_byte(dev, drive_pci, t2);
+
+               t1 = mwdma_timings[mode - XFER_MW_DMA_0];
+       } else
+               t1 = pio_timings[mode - XFER_PIO_0];
+
+       pci_write_config_byte(dev, drive_pci + 1, t1);
+}
+
+static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u32 t1 = 0;
+       u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
+
+       pci_read_config_dword(dev, drive_pci, &t1);
+
+       t1 &= 0xc0c00fff;
+       clk = (t1 & 0x08) ? ATA_133 : ATA_100;
+       if (mode >= XFER_MW_DMA_0) {
+               t1 &= ~0x04;    /* disable UDMA */
+               idx = mode - XFER_MW_DMA_0 + 5;
+       } else
+               idx = mode - XFER_PIO_0;
+       t1 |= ini_time_value[clk][idx] << 12;
+       t1 |= act_time_value[clk][idx] << 16;
+       t1 |= rco_time_value[clk][idx] << 24;
+
+       pci_write_config_dword(dev, drive_pci, t1);
+}
+
+static void sis_program_timings(ide_drive_t *drive, const u8 mode)
+{
+       if (chipset_family < ATA_100)           /* ATA_16/33/66/100a */
+               sis_ata16_program_timings(drive, mode);
+       else if (chipset_family < ATA_133)      /* ATA_100/133a */
+               sis_ata100_program_timings(drive, mode);
+       else                                    /* ATA_133 */
+               sis_ata133_program_timings(drive, mode);
+}
+
+static void config_drive_art_rwp(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u8 reg4bh               = 0;
+       u8 rw_prefetch          = 0;
+
+       pci_read_config_byte(dev, 0x4b, &reg4bh);
+
+       if (drive->media == ide_disk)
+               rw_prefetch = 0x11 << drive->dn;
+
+       if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch)
+               pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
+}
+
+static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       config_drive_art_rwp(drive);
+       sis_program_timings(drive, XFER_PIO_0 + pio);
+}
+
+static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u32 regdw = 0;
+       u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
+
+       pci_read_config_dword(dev, drive_pci, &regdw);
+
+       regdw |= 0x04;
+       regdw &= 0xfffff00f;
+       /* check if ATA133 enable */
+       clk = (regdw & 0x08) ? ATA_133 : ATA_100;
+       idx = mode - XFER_UDMA_0;
+       regdw |= cycle_time_value[clk][idx] << 4;
+       regdw |= cvs_time_value[clk][idx] << 8;
+
+       pci_write_config_dword(dev, drive_pci, regdw);
+}
+
+static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
+
+       pci_read_config_byte(dev, drive_pci + 1, &reg);
+
+       /* force the UDMA bit on if we want to use UDMA */
+       reg |= 0x80;
+       /* clean reg cycle time bits */
+       reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
+       /* set reg cycle time bits */
+       reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
+
+       pci_write_config_byte(dev, drive_pci + 1, reg);
+}
+
+static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
+{
+       if (chipset_family >= ATA_133)  /* ATA_133 */
+               sis_ata133_program_udma_timings(drive, mode);
+       else                            /* ATA_33/66/100a/100/133a */
+               sis_ata33_program_udma_timings(drive, mode);
+}
+
+static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       if (speed >= XFER_UDMA_0)
+               sis_program_udma_timings(drive, speed);
+       else
+               sis_program_timings(drive, speed);
+}
+
+static u8 sis_ata133_udma_filter(ide_drive_t *drive)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u32 regdw = 0;
+       u8 drive_pci = sis_ata133_get_base(drive);
+
+       pci_read_config_dword(dev, drive_pci, &regdw);
+
+       /* if ATA133 disable, we should not set speed above UDMA5 */
+       return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
+}
+
+static int __devinit sis_find_family(struct pci_dev *dev)
+{
+       struct pci_dev *host;
+       int i = 0;
+
+       chipset_family = 0;
+
+       for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {
+
+               host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
+
+               if (!host)
+                       continue;
+
+               chipset_family = SiSHostChipInfo[i].chipset_family;
+
+               /* Special case for SiS630 : 630S/ET is ATA_100a */
+               if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
+                       if (host->revision >= 0x30)
+                               chipset_family = ATA_100a;
+               }
+               pci_dev_put(host);
+
+               printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
+                       pci_name(dev), SiSHostChipInfo[i].name,
+                       chipset_capability[chipset_family]);
+       }
+
+       if (!chipset_family) { /* Belongs to pci-quirks */
+
+                       u32 idemisc;
+                       u16 trueid;
+
+                       /* Disable ID masking and register remapping */
+                       pci_read_config_dword(dev, 0x54, &idemisc);
+                       pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));
+                       pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
+                       pci_write_config_dword(dev, 0x54, idemisc);
+
+                       if (trueid == 0x5518) {
+                               printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
+                                       pci_name(dev));
+                               chipset_family = ATA_133;
+
+                               /* Check for 5513 compability mapping
+                                * We must use this, else the port enabled code will fail,
+                                * as it expects the enablebits at 0x4a.
+                                */
+                               if ((idemisc & 0x40000000) == 0) {
+                                       pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
+                                       printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
+                                               pci_name(dev));
+                               }
+                       }
+       }
+
+       if (!chipset_family) { /* Belongs to pci-quirks */
+
+                       struct pci_dev *lpc_bridge;
+                       u16 trueid;
+                       u8 prefctl;
+                       u8 idecfg;
+
+                       pci_read_config_byte(dev, 0x4a, &idecfg);
+                       pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
+                       pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
+                       pci_write_config_byte(dev, 0x4a, idecfg);
+
+                       if (trueid == 0x5517) { /* SiS 961/961B */
+
+                               lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
+                               pci_read_config_byte(dev, 0x49, &prefctl);
+                               pci_dev_put(lpc_bridge);
+
+                               if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
+                                       printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
+                                               pci_name(dev));
+                                       chipset_family = ATA_133a;
+                               } else {
+                                       printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
+                                               pci_name(dev));
+                                       chipset_family = ATA_100;
+                               }
+                       }
+       }
+
+       return chipset_family;
+}
+
+static unsigned int init_chipset_sis5513(struct pci_dev *dev)
+{
+       /* Make general config ops here
+          1/ tell IDE channels to operate in Compatibility mode only
+          2/ tell old chips to allow per drive IDE timings */
+
+       u8 reg;
+       u16 regw;
+
+       switch (chipset_family) {
+       case ATA_133:
+               /* SiS962 operation mode */
+               pci_read_config_word(dev, 0x50, &regw);
+               if (regw & 0x08)
+                       pci_write_config_word(dev, 0x50, regw&0xfff7);
+               pci_read_config_word(dev, 0x52, &regw);
+               if (regw & 0x08)
+                       pci_write_config_word(dev, 0x52, regw&0xfff7);
+               break;
+       case ATA_133a:
+       case ATA_100:
+               /* Fixup latency */
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+               /* Set compatibility bit */
+               pci_read_config_byte(dev, 0x49, &reg);
+               if (!(reg & 0x01))
+                       pci_write_config_byte(dev, 0x49, reg|0x01);
+               break;
+       case ATA_100a:
+       case ATA_66:
+               /* Fixup latency */
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+
+               /* On ATA_66 chips the bit was elsewhere */
+               pci_read_config_byte(dev, 0x52, &reg);
+               if (!(reg & 0x04))
+                       pci_write_config_byte(dev, 0x52, reg|0x04);
+               break;
+       case ATA_33:
+               /* On ATA_33 we didn't have a single bit to set */
+               pci_read_config_byte(dev, 0x09, &reg);
+               if ((reg & 0x0f) != 0x00)
+                       pci_write_config_byte(dev, 0x09, reg&0xf0);
+       case ATA_16:
+               /* force per drive recovery and active timings
+                  needed on ATA_33 and below chips */
+               pci_read_config_byte(dev, 0x52, &reg);
+               if (!(reg & 0x08))
+                       pci_write_config_byte(dev, 0x52, reg|0x08);
+               break;
+       }
+
+       return 0;
+}
+
+struct sis_laptop {
+       u16 device;
+       u16 subvendor;
+       u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+       /* devid, subvendor, subdev */
+       { 0x5513, 0x1043, 0x1107 },     /* ASUS A6K */
+       { 0x5513, 0x1734, 0x105f },     /* FSC Amilo A1630 */
+       { 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
+       /* end marker */
+       { 0, }
+};
+
+static u8 sis_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       const struct sis_laptop *lap = &sis_laptop[0];
+       u8 ata66 = 0;
+
+       while (lap->device) {
+               if (lap->device == pdev->device &&
+                   lap->subvendor == pdev->subsystem_vendor &&
+                   lap->subdevice == pdev->subsystem_device)
+                       return ATA_CBL_PATA40_SHORT;
+               lap++;
+       }
+
+       if (chipset_family >= ATA_133) {
+               u16 regw = 0;
+               u16 reg_addr = hwif->channel ? 0x52: 0x50;
+               pci_read_config_word(pdev, reg_addr, &regw);
+               ata66 = (regw & 0x8000) ? 0 : 1;
+       } else if (chipset_family >= ATA_66) {
+               u8 reg48h = 0;
+               u8 mask = hwif->channel ? 0x20 : 0x10;
+               pci_read_config_byte(pdev, 0x48, &reg48h);
+               ata66 = (reg48h & mask) ? 0 : 1;
+       }
+
+       return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+}
+
+static const struct ide_port_ops sis_port_ops = {
+       .set_pio_mode           = sis_set_pio_mode,
+       .set_dma_mode           = sis_set_dma_mode,
+       .cable_detect           = sis_cable_detect,
+};
+
+static const struct ide_port_ops sis_ata133_port_ops = {
+       .set_pio_mode           = sis_set_pio_mode,
+       .set_dma_mode           = sis_set_dma_mode,
+       .udma_filter            = sis_ata133_udma_filter,
+       .cable_detect           = sis_cable_detect,
+};
+
+static const struct ide_port_info sis5513_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_sis5513,
+       .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
+       .host_flags     = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
+       .pio_mask       = ATA_PIO4,
+       .mwdma_mask     = ATA_MWDMA2,
+};
+
+static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d = sis5513_chipset;
+       u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
+       int rc;
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               return rc;
+
+       if (sis_find_family(dev) == 0)
+               return -ENOTSUPP;
+
+       if (chipset_family >= ATA_133)
+               d.port_ops = &sis_ata133_port_ops;
+       else
+               d.port_ops = &sis_port_ops;
+
+       d.udma_mask = udma_rates[chipset_family];
+
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static void __devexit sis5513_remove(struct pci_dev *dev)
+{
+       ide_pci_remove(dev);
+       pci_disable_device(dev);
+}
+
+static const struct pci_device_id sis5513_pci_tbl[] = {
+       { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 },
+       { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 },
+       { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
+
+static struct pci_driver sis5513_pci_driver = {
+       .name           = "SIS_IDE",
+       .id_table       = sis5513_pci_tbl,
+       .probe          = sis5513_init_one,
+       .remove         = __devexit_p(sis5513_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init sis5513_ide_init(void)
+{
+       return ide_pci_register_driver(&sis5513_pci_driver);
+}
+
+static void __exit sis5513_ide_exit(void)
+{
+       pci_unregister_driver(&sis5513_pci_driver);
+}
+
+module_init(sis5513_ide_init);
+module_exit(sis5513_ide_exit);
+
+MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
+MODULE_DESCRIPTION("PCI driver module for SIS IDE");
+MODULE_LICENSE("GPL");
+
+/*
+ * TODO:
+ *     - CLEANUP
+ *     - More checks in the config registers (force values instead of
+ *       relying on the BIOS setting them correctly).
+ *     - Further optimisations ?
+ *       . for example ATA66+ regs 0x48 & 0x4A
+ */
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
new file mode 100644 (file)
index 0000000..84dc336
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * SL82C105/Winbond 553 IDE driver
+ *
+ * Maintainer unknown.
+ *
+ * Drive tuning added from Rebel.com's kernel sources
+ *  -- Russell King (15/11/98) linux@arm.linux.org.uk
+ * 
+ * Merge in Russell's HW workarounds, fix various problems
+ * with the timing registers setup.
+ *  -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org
+ *
+ * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "sl82c105"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(arg) printk arg
+#else
+#define DBG(fmt,...)
+#endif
+/*
+ * SL82C105 PCI config register 0x40 bits.
+ */
+#define CTRL_IDE_IRQB   (1 << 30)
+#define CTRL_IDE_IRQA   (1 << 28)
+#define CTRL_LEGIRQ     (1 << 11)
+#define CTRL_P1F16      (1 << 5)
+#define CTRL_P1EN       (1 << 4)
+#define CTRL_P0F16      (1 << 1)
+#define CTRL_P0EN       (1 << 0)
+
+/*
+ * Convert a PIO mode and cycle time to the required on/off times
+ * for the interface.  This has protection against runaway timings.
+ */
+static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
+{
+       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+       unsigned int cmd_on, cmd_off;
+       u8 iordy = 0;
+
+       cmd_on  = (t->active + 29) / 30;
+       cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30;
+
+       if (cmd_on == 0)
+               cmd_on = 1;
+
+       if (cmd_off == 0)
+               cmd_off = 1;
+
+       if (pio > 2 || ata_id_has_iordy(drive->id))
+               iordy = 0x40;
+
+       return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy;
+}
+
+/*
+ * Configure the chipset for PIO mode.
+ */
+static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       struct pci_dev *dev     = to_pci_dev(drive->hwif->dev);
+       int reg                 = 0x44 + drive->dn * 4;
+       u16 drv_ctrl;
+
+       drv_ctrl = get_pio_timings(drive, pio);
+
+       /*
+        * Store the PIO timings so that we can restore them
+        * in case DMA will be turned off...
+        */
+       drive->drive_data &= 0xffff0000;
+       drive->drive_data |= drv_ctrl;
+
+       pci_write_config_word(dev, reg,  drv_ctrl);
+       pci_read_config_word (dev, reg, &drv_ctrl);
+
+       printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
+                         ide_xfer_verbose(pio + XFER_PIO_0),
+                         ide_pio_cycle_time(drive, pio), drv_ctrl);
+}
+
+/*
+ * Configure the chipset for DMA mode.
+ */
+static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+       static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
+       u16 drv_ctrl;
+
+       DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
+            drive->name, ide_xfer_verbose(speed)));
+
+       drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
+
+       /*
+        * Store the DMA timings so that we can actually program
+        * them when DMA will be turned on...
+        */
+       drive->drive_data &= 0x0000ffff;
+       drive->drive_data |= (unsigned long)drv_ctrl << 16;
+}
+
+/*
+ * The SL82C105 holds off all IDE interrupts while in DMA mode until
+ * all DMA activity is completed.  Sometimes this causes problems (eg,
+ * when the drive wants to report an error condition).
+ *
+ * 0x7e is a "chip testing" register.  Bit 2 resets the DMA controller
+ * state machine.  We need to kick this to work around various bugs.
+ */
+static inline void sl82c105_reset_host(struct pci_dev *dev)
+{
+       u16 val;
+
+       pci_read_config_word(dev, 0x7e, &val);
+       pci_write_config_word(dev, 0x7e, val | (1 << 2));
+       pci_write_config_word(dev, 0x7e, val & ~(1 << 2));
+}
+
+/*
+ * If we get an IRQ timeout, it might be that the DMA state machine
+ * got confused.  Fix from Todd Inglett.  Details from Winbond.
+ *
+ * This function is called when the IDE timer expires, the drive
+ * indicates that it is READY, and we were waiting for DMA to complete.
+ */
+static void sl82c105_dma_lost_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       u32 val, mask           = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+       u8 dma_cmd;
+
+       printk("sl82c105: lost IRQ, resetting host\n");
+
+       /*
+        * Check the raw interrupt from the drive.
+        */
+       pci_read_config_dword(dev, 0x40, &val);
+       if (val & mask)
+               printk("sl82c105: drive was requesting IRQ, but host lost it\n");
+
+       /*
+        * Was DMA enabled?  If so, disable it - we're resetting the
+        * host.  The IDE layer will be handling the drive for us.
+        */
+       dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+       if (dma_cmd & 1) {
+               outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+               printk("sl82c105: DMA was enabled\n");
+       }
+
+       sl82c105_reset_host(dev);
+}
+
+/*
+ * ATAPI devices can cause the SL82C105 DMA state machine to go gaga.
+ * Winbond recommend that the DMA state machine is reset prior to
+ * setting the bus master DMA enable bit.
+ *
+ * The generic IDE core will have disabled the BMEN bit before this
+ * function is called.
+ */
+static void sl82c105_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       int reg                 = 0x44 + drive->dn * 4;
+
+       DBG(("%s(drive:%s)\n", __func__, drive->name));
+
+       pci_write_config_word(dev, reg, drive->drive_data >> 16);
+
+       sl82c105_reset_host(dev);
+       ide_dma_start(drive);
+}
+
+static void sl82c105_dma_timeout(ide_drive_t *drive)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+
+       DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
+
+       sl82c105_reset_host(dev);
+       ide_dma_timeout(drive);
+}
+
+static int sl82c105_dma_end(ide_drive_t *drive)
+{
+       struct pci_dev *dev     = to_pci_dev(drive->hwif->dev);
+       int reg                 = 0x44 + drive->dn * 4;
+       int ret;
+
+       DBG(("%s(drive:%s)\n", __func__, drive->name));
+
+       ret = ide_dma_end(drive);
+
+       pci_write_config_word(dev, reg, drive->drive_data);
+
+       return ret;
+}
+
+/*
+ * ATA reset will clear the 16 bits mode in the control
+ * register, we need to reprogram it
+ */
+static void sl82c105_resetproc(ide_drive_t *drive)
+{
+       struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+       u32 val;
+
+       DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
+
+       pci_read_config_dword(dev, 0x40, &val);
+       val |= (CTRL_P1F16 | CTRL_P0F16);
+       pci_write_config_dword(dev, 0x40, val);
+}
+
+/*
+ * Return the revision of the Winbond bridge
+ * which this function is part of.
+ */
+static u8 sl82c105_bridge_revision(struct pci_dev *dev)
+{
+       struct pci_dev *bridge;
+
+       /*
+        * The bridge should be part of the same device, but function 0.
+        */
+       bridge = pci_get_bus_and_slot(dev->bus->number,
+                              PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       if (!bridge)
+               return -1;
+
+       /*
+        * Make sure it is a Winbond 553 and is an ISA bridge.
+        */
+       if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
+           bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
+           bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) {
+               pci_dev_put(bridge);
+               return -1;
+       }
+       /*
+        * We need to find function 0's revision, not function 1
+        */
+       pci_dev_put(bridge);
+
+       return bridge->revision;
+}
+
+/*
+ * Enable the PCI device
+ * 
+ * --BenH: It's arch fixup code that should enable channels that
+ * have not been enabled by firmware. I decided we can still enable
+ * channel 0 here at least, but channel 1 has to be enabled by
+ * firmware or arch code. We still set both to 16 bits mode.
+ */
+static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
+{
+       u32 val;
+
+       DBG(("init_chipset_sl82c105()\n"));
+
+       pci_read_config_dword(dev, 0x40, &val);
+       val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+       pci_write_config_dword(dev, 0x40, val);
+
+       return dev->irq;
+}
+
+static const struct ide_port_ops sl82c105_port_ops = {
+       .set_pio_mode           = sl82c105_set_pio_mode,
+       .set_dma_mode           = sl82c105_set_dma_mode,
+       .resetproc              = sl82c105_resetproc,
+};
+
+static const struct ide_dma_ops sl82c105_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = sl82c105_dma_start,
+       .dma_end                = sl82c105_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = sl82c105_dma_lost_irq,
+       .dma_timeout            = sl82c105_dma_timeout,
+};
+
+static const struct ide_port_info sl82c105_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_sl82c105,
+       .enablebits     = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
+       .port_ops       = &sl82c105_port_ops,
+       .dma_ops        = &sl82c105_dma_ops,
+       .host_flags     = IDE_HFLAG_IO_32BIT |
+                         IDE_HFLAG_UNMASK_IRQS |
+/* FIXME: check for Compatibility mode in generic IDE PCI code */
+#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
+                         IDE_HFLAG_FORCE_LEGACY_IRQS |
+#endif
+                         IDE_HFLAG_SERIALIZE_DMA |
+                         IDE_HFLAG_NO_AUTODMA,
+       .pio_mask       = ATA_PIO5,
+       .mwdma_mask     = ATA_MWDMA2,
+};
+
+static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct ide_port_info d = sl82c105_chipset;
+       u8 rev = sl82c105_bridge_revision(dev);
+
+       if (rev <= 5) {
+               /*
+                * Never ever EVER under any circumstances enable
+                * DMA when the bridge is this old.
+                */
+               printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge "
+                                "revision %d, BM-DMA disabled\n", rev);
+               d.dma_ops = NULL;
+               d.mwdma_mask = 0;
+               d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
+       }
+
+       return ide_pci_init_one(dev, &d, NULL);
+}
+
+static const struct pci_device_id sl82c105_pci_tbl[] = {
+       { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
+
+static struct pci_driver sl82c105_pci_driver = {
+       .name           = "W82C105_IDE",
+       .id_table       = sl82c105_pci_tbl,
+       .probe          = sl82c105_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init sl82c105_ide_init(void)
+{
+       return ide_pci_register_driver(&sl82c105_pci_driver);
+}
+
+static void __exit sl82c105_ide_exit(void)
+{
+       pci_unregister_driver(&sl82c105_pci_driver);
+}
+
+module_init(sl82c105_ide_init);
+module_exit(sl82c105_ide_exit);
+
+MODULE_DESCRIPTION("PCI driver module for W82C105 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
new file mode 100644 (file)
index 0000000..0f759e4
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This is a look-alike variation of the ICH0 PIIX4 Ultra-66,
+ * but this keeps the ISA-Bridge and slots alive.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "slc90e66"
+
+static DEFINE_SPINLOCK(slc90e66_lock);
+
+static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       int is_slave            = drive->dn & 1;
+       int master_port         = hwif->channel ? 0x42 : 0x40;
+       int slave_port          = 0x44;
+       unsigned long flags;
+       u16 master_data;
+       u8 slave_data;
+       int control = 0;
+                                    /* ISP  RTC */
+       static const u8 timings[][2] = {
+                                       { 0, 0 },
+                                       { 0, 0 },
+                                       { 1, 0 },
+                                       { 2, 1 },
+                                       { 2, 3 }, };
+
+       spin_lock_irqsave(&slc90e66_lock, flags);
+       pci_read_config_word(dev, master_port, &master_data);
+
+       if (pio > 1)
+               control |= 1;   /* Programmable timing on */
+       if (drive->media == ide_disk)
+               control |= 4;   /* Prefetch, post write */
+       if (pio > 2)
+               control |= 2;   /* IORDY */
+       if (is_slave) {
+               master_data |=  0x4000;
+               master_data &= ~0x0070;
+               if (pio > 1) {
+                       /* Set PPE, IE and TIME */
+                       master_data |= control << 4;
+               }
+               pci_read_config_byte(dev, slave_port, &slave_data);
+               slave_data &= hwif->channel ? 0x0f : 0xf0;
+               slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) <<
+                              (hwif->channel ? 4 : 0);
+       } else {
+               master_data &= ~0x3307;
+               if (pio > 1) {
+                       /* enable PPE, IE and TIME */
+                       master_data |= control;
+               }
+               master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
+       }
+       pci_write_config_word(dev, master_port, master_data);
+       if (is_slave)
+               pci_write_config_byte(dev, slave_port, slave_data);
+       spin_unlock_irqrestore(&slc90e66_lock, flags);
+}
+
+static void slc90e66_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 maslave              = hwif->channel ? 0x42 : 0x40;
+       int sitre = 0, a_speed  = 7 << (drive->dn * 4);
+       int u_speed = 0, u_flag = 1 << drive->dn;
+       u16                     reg4042, reg44, reg48, reg4a;
+
+       pci_read_config_word(dev, maslave, &reg4042);
+       sitre = (reg4042 & 0x4000) ? 1 : 0;
+       pci_read_config_word(dev, 0x44, &reg44);
+       pci_read_config_word(dev, 0x48, &reg48);
+       pci_read_config_word(dev, 0x4a, &reg4a);
+
+       if (speed >= XFER_UDMA_0) {
+               u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
+
+               if (!(reg48 & u_flag))
+                       pci_write_config_word(dev, 0x48, reg48|u_flag);
+               /* FIXME: (reg4a & a_speed) ? */
+               if ((reg4a & u_speed) != u_speed) {
+                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+                       pci_read_config_word(dev, 0x4a, &reg4a);
+                       pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+               }
+       } else {
+               const u8 mwdma_to_pio[] = { 0, 3, 4 };
+               u8 pio;
+
+               if (reg48 & u_flag)
+                       pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+               if (reg4a & a_speed)
+                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+
+               if (speed >= XFER_MW_DMA_0)
+                       pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+               else
+                       pio = 2; /* only SWDMA2 is allowed */
+
+               slc90e66_set_pio_mode(drive, pio);
+       }
+}
+
+static u8 slc90e66_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02;
+
+       pci_read_config_byte(dev, 0x47, &reg47);
+
+       /* bit[0(1)]: 0:80, 1:40 */
+       return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+static const struct ide_port_ops slc90e66_port_ops = {
+       .set_pio_mode           = slc90e66_set_pio_mode,
+       .set_dma_mode           = slc90e66_set_dma_mode,
+       .cable_detect           = slc90e66_cable_detect,
+};
+
+static const struct ide_port_info slc90e66_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
+       .port_ops       = &slc90e66_port_ops,
+       .host_flags     = IDE_HFLAG_LEGACY_IRQS,
+       .pio_mask       = ATA_PIO4,
+       .swdma_mask     = ATA_SWDMA2_ONLY,
+       .mwdma_mask     = ATA_MWDMA12_ONLY,
+       .udma_mask      = ATA_UDMA4,
+};
+
+static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &slc90e66_chipset, NULL);
+}
+
+static const struct pci_device_id slc90e66_pci_tbl[] = {
+       { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
+
+static struct pci_driver slc90e66_pci_driver = {
+       .name           = "SLC90e66_IDE",
+       .id_table       = slc90e66_pci_tbl,
+       .probe          = slc90e66_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init slc90e66_ide_init(void)
+{
+       return ide_pci_register_driver(&slc90e66_pci_driver);
+}
+
+static void __exit slc90e66_ide_exit(void)
+{
+       pci_unregister_driver(&slc90e66_pci_driver);
+}
+
+module_init(slc90e66_ide_init);
+module_exit(slc90e66_ide_exit);
+
+MODULE_AUTHOR("Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c
new file mode 100644 (file)
index 0000000..93e2cce
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2002 Toshiba Corporation
+ * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#define DRV_NAME "tc86c001"
+
+static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       unsigned long scr_port  = hwif->config_data + (drive->dn ? 0x02 : 0x00);
+       u16 mode, scr           = inw(scr_port);
+
+       switch (speed) {
+       case XFER_UDMA_4:       mode = 0x00c0; break;
+       case XFER_UDMA_3:       mode = 0x00b0; break;
+       case XFER_UDMA_2:       mode = 0x00a0; break;
+       case XFER_UDMA_1:       mode = 0x0090; break;
+       case XFER_UDMA_0:       mode = 0x0080; break;
+       case XFER_MW_DMA_2:     mode = 0x0070; break;
+       case XFER_MW_DMA_1:     mode = 0x0060; break;
+       case XFER_MW_DMA_0:     mode = 0x0050; break;
+       case XFER_PIO_4:        mode = 0x0400; break;
+       case XFER_PIO_3:        mode = 0x0300; break;
+       case XFER_PIO_2:        mode = 0x0200; break;
+       case XFER_PIO_1:        mode = 0x0100; break;
+       case XFER_PIO_0:
+       default:                mode = 0x0000; break;
+       }
+
+       scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
+       scr |= mode;
+       outw(scr, scr_port);
+}
+
+static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       tc86c001_set_mode(drive, XFER_PIO_0 + pio);
+}
+
+/*
+ * HACKITY HACK
+ *
+ * This is a workaround for the limitation 5 of the TC86C001 IDE controller:
+ * if a DMA transfer terminates prematurely, the controller leaves the device's
+ * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
+ * set the interrupt bit in the DMA status register), thus no PCI interrupt
+ * will occur until a DMA transfer has been successfully completed.
+ *
+ * We work around this by initiating dummy, zero-length DMA transfer on
+ * a DMA timeout expiration. I found no better way to do this with the current
+ * IDE core than to temporarily replace a higher level driver's timer expiry
+ * handler with our own backing up to that handler in case our recovery fails.
+ */
+static int tc86c001_timer_expiry(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       ide_expiry_t *expiry    = ide_get_hwifdata(hwif);
+       ide_hwgroup_t *hwgroup  = HWGROUP(drive);
+       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
+
+       /* Restore a higher level driver's expiry handler first. */
+       hwgroup->expiry = expiry;
+
+       if ((dma_stat & 5) == 1) {      /* DMA active and no interrupt */
+               unsigned long sc_base   = hwif->config_data;
+               unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
+               u8 dma_cmd              = inb(hwif->dma_base + ATA_DMA_CMD);
+
+               printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
+                      "attempting recovery...\n", drive->name);
+
+               /* Stop DMA */
+               outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
+
+               /* Setup the dummy DMA transfer */
+               outw(0, sc_base + 0x0a);        /* Sector Count */
+               outw(0, twcr_port);     /* Transfer Word Count 1 or 2 */
+
+               /* Start the dummy DMA transfer */
+
+               /* clear R_OR_WCTR for write */
+               outb(0x00, hwif->dma_base + ATA_DMA_CMD);
+               /* set START_STOPBM */
+               outb(0x01, hwif->dma_base + ATA_DMA_CMD);
+
+               /*
+                * If an interrupt was pending, it should come thru shortly.
+                * If not, a higher level driver's expiry handler should
+                * eventually cause some kind of recovery from the DMA stall.
+                */
+               return WAIT_MIN_SLEEP;
+       }
+
+       /* Chain to the restored expiry handler if DMA wasn't active. */
+       if (likely(expiry != NULL))
+               return expiry(drive);
+
+       /* If there was no handler, "emulate" that for ide_timer_expiry()... */
+       return -1;
+}
+
+static void tc86c001_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       ide_hwgroup_t *hwgroup  = HWGROUP(drive);
+       unsigned long sc_base   = hwif->config_data;
+       unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
+       unsigned long nsectors  = hwgroup->rq->nr_sectors;
+
+       /*
+        * We have to manually load the sector count and size into
+        * the appropriate system control registers for DMA to work
+        * with LBA48 and ATAPI devices...
+        */
+       outw(nsectors, sc_base + 0x0a); /* Sector Count */
+       outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
+
+       /* Install our timeout expiry hook, saving the current handler... */
+       ide_set_hwifdata(hwif, hwgroup->expiry);
+       hwgroup->expiry = &tc86c001_timer_expiry;
+
+       ide_dma_start(drive);
+}
+
+static u8 tc86c001_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long sc_base = pci_resource_start(dev, 5);
+       u16 scr1 = inw(sc_base + 0x00);
+
+       /*
+        * System Control  1 Register bit 13 (PDIAGN):
+        * 0=80-pin cable, 1=40-pin cable
+        */
+       return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+}
+
+static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned long sc_base   = pci_resource_start(dev, 5);
+       u16 scr1                = inw(sc_base + 0x00);
+
+       /* System Control 1 Register bit 15 (Soft Reset) set */
+       outw(scr1 |  0x8000, sc_base + 0x00);
+
+       /* System Control 1 Register bit 14 (FIFO Reset) set */
+       outw(scr1 |  0x4000, sc_base + 0x00);
+
+       /* System Control 1 Register: reset clear */
+       outw(scr1 & ~0xc000, sc_base + 0x00);
+
+       /* Store the system control register base for convenience... */
+       hwif->config_data = sc_base;
+
+       if (!hwif->dma_base)
+               return;
+
+       /*
+        * Sector Count Control Register bits 0 and 1 set:
+        * software sets Sector Count Register for master and slave device
+        */
+       outw(0x0003, sc_base + 0x0c);
+
+       /* Sector Count Register limit */
+       hwif->rqsize     = 0xffff;
+}
+
+static const struct ide_port_ops tc86c001_port_ops = {
+       .set_pio_mode           = tc86c001_set_pio_mode,
+       .set_dma_mode           = tc86c001_set_mode,
+       .cable_detect           = tc86c001_cable_detect,
+};
+
+static const struct ide_dma_ops tc86c001_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = tc86c001_dma_start,
+       .dma_end                = ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info tc86c001_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_hwif      = init_hwif_tc86c001,
+       .port_ops       = &tc86c001_port_ops,
+       .dma_ops        = &tc86c001_dma_ops,
+       .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
+       .pio_mask       = ATA_PIO4,
+       .mwdma_mask     = ATA_MWDMA2,
+       .udma_mask      = ATA_UDMA4,
+};
+
+static int __devinit tc86c001_init_one(struct pci_dev *dev,
+                                      const struct pci_device_id *id)
+{
+       int rc;
+
+       rc = pci_enable_device(dev);
+       if (rc)
+               goto out;
+
+       rc = pci_request_region(dev, 5, DRV_NAME);
+       if (rc) {
+               printk(KERN_ERR DRV_NAME ": system control regs already in use");
+               goto out_disable;
+       }
+
+       rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
+       if (rc)
+               goto out_release;
+
+       goto out;
+
+out_release:
+       pci_release_region(dev, 5);
+out_disable:
+       pci_disable_device(dev);
+out:
+       return rc;
+}
+
+static void __devexit tc86c001_remove(struct pci_dev *dev)
+{
+       ide_pci_remove(dev);
+       pci_release_region(dev, 5);
+       pci_disable_device(dev);
+}
+
+static const struct pci_device_id tc86c001_pci_tbl[] = {
+       { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
+
+static struct pci_driver tc86c001_pci_driver = {
+       .name           = "TC86C001",
+       .id_table       = tc86c001_pci_tbl,
+       .probe          = tc86c001_init_one,
+       .remove         = __devexit_p(tc86c001_remove),
+};
+
+static int __init tc86c001_ide_init(void)
+{
+       return ide_pci_register_driver(&tc86c001_pci_driver);
+}
+
+static void __exit tc86c001_ide_exit(void)
+{
+       pci_unregister_driver(&tc86c001_pci_driver);
+}
+
+module_init(tc86c001_ide_init);
+module_exit(tc86c001_ide_exit);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c
new file mode 100644 (file)
index 0000000..b6ff403
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * IDE Chipset driver for the Compaq TriFlex IDE controller.
+ * 
+ * Known to work with the Compaq Workstation 5x00 series.
+ *
+ * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
+ * Author: Torben Mathiasen <torben.mathiasen@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Loosely based on the piix & svwks drivers.
+ *
+ * Documentation:
+ *     Not publically available.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "triflex"
+
+static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       u32 triflex_timings = 0;
+       u16 timing = 0;
+       u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;
+
+       pci_read_config_dword(dev, channel_offset, &triflex_timings);
+
+       switch(speed) {
+               case XFER_MW_DMA_2:
+                       timing = 0x0103; 
+                       break;
+               case XFER_MW_DMA_1:
+                       timing = 0x0203;
+                       break;
+               case XFER_MW_DMA_0:
+                       timing = 0x0808;
+                       break;
+               case XFER_SW_DMA_2:
+               case XFER_SW_DMA_1:
+               case XFER_SW_DMA_0:
+                       timing = 0x0f0f;
+                       break;
+               case XFER_PIO_4:
+                       timing = 0x0202;
+                       break;
+               case XFER_PIO_3:
+                       timing = 0x0204;
+                       break;
+               case XFER_PIO_2:
+                       timing = 0x0404;
+                       break;
+               case XFER_PIO_1:
+                       timing = 0x0508;
+                       break;
+               case XFER_PIO_0:
+                       timing = 0x0808;
+                       break;
+       }
+
+       triflex_timings &= ~(0xFFFF << (16 * unit));
+       triflex_timings |= (timing << (16 * unit));
+       
+       pci_write_config_dword(dev, channel_offset, triflex_timings);
+}
+
+static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       triflex_set_mode(drive, XFER_PIO_0 + pio);
+}
+
+static const struct ide_port_ops triflex_port_ops = {
+       .set_pio_mode           = triflex_set_pio_mode,
+       .set_dma_mode           = triflex_set_mode,
+};
+
+static const struct ide_port_info triflex_device __devinitdata = {
+       .name           = DRV_NAME,
+       .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
+       .port_ops       = &triflex_port_ops,
+       .pio_mask       = ATA_PIO4,
+       .swdma_mask     = ATA_SWDMA2,
+       .mwdma_mask     = ATA_MWDMA2,
+};
+
+static int __devinit triflex_init_one(struct pci_dev *dev, 
+               const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &triflex_device, NULL);
+}
+
+static const struct pci_device_id triflex_pci_tbl[] = {
+       { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
+
+static struct pci_driver triflex_pci_driver = {
+       .name           = "TRIFLEX_IDE",
+       .id_table       = triflex_pci_tbl,
+       .probe          = triflex_init_one,
+       .remove         = ide_pci_remove,
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init triflex_ide_init(void)
+{
+       return ide_pci_register_driver(&triflex_pci_driver);
+}
+
+static void __exit triflex_ide_exit(void)
+{
+       pci_unregister_driver(&triflex_pci_driver);
+}
+
+module_init(triflex_ide_init);
+module_exit(triflex_ide_exit);
+
+MODULE_AUTHOR("Torben Mathiasen");
+MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
+MODULE_LICENSE("GPL");
+
+
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
new file mode 100644 (file)
index 0000000..75ea615
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ *  Copyright (c) 1997-1998  Mark Lord
+ *  Copyright (c) 2007       MontaVista Software, Inc. <source@mvista.com>
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ *
+ *  June 22, 2004 - get rid of check_region
+ *                   - Jesper Juhl
+ *
+ */
+
+/*
+ * This module provides support for the bus-master IDE DMA function
+ * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards,
+ * including a "Precision Instruments" board.  The TRM290 pre-dates
+ * the sff-8038 standard (ide-dma.c) by a few months, and differs
+ * significantly enough to warrant separate routines for some functions,
+ * while re-using others from ide-dma.c.
+ *
+ * EXPERIMENTAL!  It works for me (a sample of one).
+ *
+ * Works reliably for me in DMA mode (READs only),
+ * DMA WRITEs are disabled by default (see #define below);
+ *
+ * DMA is not enabled automatically for this chipset,
+ * but can be turned on manually (with "hdparm -d1") at run time.
+ *
+ * I need volunteers with "spare" drives for further testing
+ * and development, and maybe to help figure out the peculiarities.
+ * Even knowing the registers (below), some things behave strangely.
+ */
+
+#define TRM290_NO_DMA_WRITES   /* DMA writes seem unreliable sometimes */
+
+/*
+ * TRM-290 PCI-IDE2 Bus Master Chip
+ * ================================
+ * The configuration registers are addressed in normal I/O port space
+ * and are used as follows:
+ *
+ * trm290_base depends on jumper settings, and is probed for by ide-dma.c
+ *
+ * trm290_base+2 when WRITTEN: chiptest register (byte, write-only)
+ *     bit7 must always be written as "1"
+ *     bits6-2 undefined
+ *     bit1 1=legacy_compatible_mode, 0=native_pci_mode
+ *     bit0 1=test_mode, 0=normal(default)
+ *
+ * trm290_base+2 when READ: status register (byte, read-only)
+ *     bits7-2 undefined
+ *     bit1 channel0 busmaster interrupt status 0=none, 1=asserted
+ *     bit0 channel0 interrupt status 0=none, 1=asserted
+ *
+ * trm290_base+3 Interrupt mask register
+ *     bits7-5 undefined
+ *     bit4 legacy_header: 1=present, 0=absent
+ *     bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only)
+ *     bit2 channel1 interrupt status 0=none, 1=asserted (read only)
+ *     bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default)
+ *     bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default)
+ *
+ * trm290_base+1 "CPR" Config Pointer Register (byte)
+ *     bit7 1=autoincrement CPR bits 2-0 after each access of CDR
+ *     bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state
+ *     bit5 0=enabled master burst access (default), 1=disable  (write only)
+ *     bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast
+ *     bit3 0=primary IDE channel, 1=secondary IDE channel
+ *     bits2-0 register index for accesses through CDR port
+ *
+ * trm290_base+0 "CDR" Config Data Register (word)
+ *     two sets of seven config registers,
+ *     selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6),
+ *     each index defined below:
+ *
+ * Index-0 Base address register for command block (word)
+ *     defaults: 0x1f0 for primary, 0x170 for secondary
+ *
+ * Index-1 general config register (byte)
+ *     bit7 1=DMA enable, 0=DMA disable
+ *     bit6 1=activate IDE_RESET, 0=no action (default)
+ *     bit5 1=enable IORDY, 0=disable IORDY (default)
+ *     bit4 0=16-bit data port(default), 1=8-bit (XT) data port
+ *     bit3 interrupt polarity: 1=active_low, 0=active_high(default)
+ *     bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only)
+ *     bit1 bus_master_mode(?): 1=enable, 0=disable(default)
+ *     bit0 enable_io_ports: 1=enable(default), 0=disable
+ *
+ * Index-2 read-ahead counter preload bits 0-7 (byte, write only)
+ *     bits7-0 bits7-0 of readahead count
+ *
+ * Index-3 read-ahead config register (byte, write only)
+ *     bit7 1=enable_readahead, 0=disable_readahead(default)
+ *     bit6 1=clear_FIFO, 0=no_action
+ *     bit5 undefined
+ *     bit4 mode4 timing control: 1=enable, 0=disable(default)
+ *     bit3 undefined
+ *     bit2 undefined
+ *     bits1-0 bits9-8 of read-ahead count
+ *
+ * Index-4 base address register for control block (word)
+ *     defaults: 0x3f6 for primary, 0x376 for secondary
+ *
+ * Index-5 data port timings (shared by both drives) (byte)
+ *     standard PCI "clk" (clock) counts, default value = 0xf5
+ *
+ *     bits7-6 setup time:  00=1clk, 01=2clk, 10=3clk, 11=4clk
+ *     bits5-3 hold time:      000=1clk, 001=2clk, 010=3clk,
+ *                             011=4clk, 100=5clk, 101=6clk,
+ *                             110=8clk, 111=12clk
+ *     bits2-0 active time:    000=2clk, 001=3clk, 010=4clk,
+ *                             011=5clk, 100=6clk, 101=8clk,
+ *                             110=12clk, 111=16clk
+ *
+ * Index-6 command/control port timings (shared by both drives) (byte)
+ *     same layout as Index-5, default value = 0xde
+ *
+ * Suggested CDR programming for PIO mode0 (600ns):
+ *     0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde  ; primary
+ *     0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde  ; secondary
+ *
+ * Suggested CDR programming for PIO mode3 (180ns):
+ *     0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde  ; primary
+ *     0x0170,0x21,0xff,0x80,0x0376,0x09,0xde  ; secondary
+ *
+ * Suggested CDR programming for PIO mode4 (120ns):
+ *     0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde  ; primary
+ *     0x0170,0x21,0xff,0x80,0x0376,0x00,0xde  ; secondary
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "trm290"
+
+static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u16 reg = 0;
+       unsigned long flags;
+
+       /* select PIO or DMA */
+       reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82);
+
+       local_irq_save(flags);
+
+       if (reg != hwif->select_data) {
+               hwif->select_data = reg;
+               /* set PIO/DMA */
+               outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
+               outw(reg & 0xff, hwif->config_data);
+       }
+
+       /* enable IRQ if not probing */
+       if (drive->dev_flags & IDE_DFLAG_PRESENT) {
+               reg = inw(hwif->config_data + 3);
+               reg &= 0x13;
+               reg &= ~(1 << hwif->channel);
+               outw(reg, hwif->config_data + 3);
+       }
+
+       local_irq_restore(flags);
+}
+
+static void trm290_selectproc (ide_drive_t *drive)
+{
+       trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
+}
+
+static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+       ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL);
+}
+
+static int trm290_dma_setup(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *rq = hwif->hwgroup->rq;
+       unsigned int count, rw;
+
+       if (rq_data_dir(rq)) {
+#ifdef TRM290_NO_DMA_WRITES
+               /* always use PIO for writes */
+               trm290_prepare_drive(drive, 0); /* select PIO xfer */
+               return 1;
+#endif
+               rw = 1;
+       } else
+               rw = 2;
+
+       if (!(count = ide_build_dmatable(drive, rq))) {
+               /* try PIO instead of DMA */
+               trm290_prepare_drive(drive, 0); /* select PIO xfer */
+               return 1;
+       }
+       /* select DMA xfer */
+       trm290_prepare_drive(drive, 1);
+       outl(hwif->dmatable_dma | rw, hwif->dma_base);
+       drive->waiting_for_dma = 1;
+       /* start DMA */
+       outw(count * 2 - 1, hwif->dma_base + 2);
+       return 0;
+}
+
+static void trm290_dma_start(ide_drive_t *drive)
+{
+}
+
+static int trm290_dma_end(ide_drive_t *drive)
+{
+       u16 status;
+
+       drive->waiting_for_dma = 0;
+       /* purge DMA mappings */
+       ide_destroy_dmatable(drive);
+       status = inw(HWIF(drive)->dma_base + 2);
+       return status != 0x00ff;
+}
+
+static int trm290_dma_test_irq(ide_drive_t *drive)
+{
+       u16 status;
+
+       status = inw(HWIF(drive)->dma_base + 2);
+       return status == 0x00ff;
+}
+
+static void trm290_dma_host_set(ide_drive_t *drive, int on)
+{
+}
+
+static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned int  cfg_base  = pci_resource_start(dev, 4);
+       unsigned long flags;
+       u8 reg = 0;
+
+       if ((dev->class & 5) && cfg_base)
+               printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev));
+       else {
+               cfg_base = 0x3df0;
+               printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev));
+       }
+       printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
+       hwif->config_data = cfg_base;
+       hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
+
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+              hwif->name, hwif->dma_base, hwif->dma_base + 3);
+
+       if (ide_allocate_dma_engine(hwif))
+               return;
+
+       local_irq_save(flags);
+       /* put config reg into first byte of hwif->select_data */
+       outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
+       /* select PIO as default */
+       hwif->select_data = 0x21;
+       outb(hwif->select_data, hwif->config_data);
+       /* get IRQ info */
+       reg = inb(hwif->config_data + 3);
+       /* mask IRQs for both ports */
+       reg = (reg & 0x10) | 0x03;
+       outb(reg, hwif->config_data + 3);
+       local_irq_restore(flags);
+
+       if (reg & 0x10)
+               /* legacy mode */
+               hwif->irq = hwif->channel ? 15 : 14;
+       else if (!hwif->irq && hwif->mate && hwif->mate->irq)
+               /* sharing IRQ with mate */
+               hwif->irq = hwif->mate->irq;
+
+#if 1
+       {
+       /*
+        * My trm290-based card doesn't seem to work with all possible values
+        * for the control basereg, so this kludge ensures that we use only
+        * values that are known to work.  Ugh.         -ml
+        */
+               u16 new, old, compat = hwif->channel ? 0x374 : 0x3f4;
+               static u16 next_offset = 0;
+               u8 old_mask;
+
+               outb(0x54 | (hwif->channel << 3), hwif->config_data + 1);
+               old = inw(hwif->config_data);
+               old &= ~1;
+               old_mask = inb(old + 2);
+               if (old != compat && old_mask == 0xff) {
+                       /* leave lower 10 bits untouched */
+                       compat += (next_offset += 0x400);
+                       hwif->io_ports.ctl_addr = compat + 2;
+                       outw(compat | 1, hwif->config_data);
+                       new = inw(hwif->config_data);
+                       printk(KERN_INFO "%s: control basereg workaround: "
+                               "old=0x%04x, new=0x%04x\n",
+                               hwif->name, old, new & ~1);
+               }
+       }
+#endif
+}
+
+static const struct ide_port_ops trm290_port_ops = {
+       .selectproc             = trm290_selectproc,
+};
+
+static struct ide_dma_ops trm290_dma_ops = {
+       .dma_host_set           = trm290_dma_host_set,
+       .dma_setup              = trm290_dma_setup,
+       .dma_exec_cmd           = trm290_dma_exec_cmd,
+       .dma_start              = trm290_dma_start,
+       .dma_end                = trm290_dma_end,
+       .dma_test_irq           = trm290_dma_test_irq,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+};
+
+static const struct ide_port_info trm290_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_hwif      = init_hwif_trm290,
+       .chipset        = ide_trm290,
+       .port_ops       = &trm290_port_ops,
+       .dma_ops        = &trm290_dma_ops,
+       .host_flags     = IDE_HFLAG_NO_ATAPI_DMA |
+#if 0 /* play it safe for now */
+                         IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+#endif
+                         IDE_HFLAG_NO_AUTODMA |
+                         IDE_HFLAG_NO_LBA48,
+};
+
+static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       return ide_pci_init_one(dev, &trm290_chipset, NULL);
+}
+
+static const struct pci_device_id trm290_pci_tbl[] = {
+       { PCI_VDEVICE(TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290), 0 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
+
+static struct pci_driver trm290_pci_driver = {
+       .name           = "TRM290_IDE",
+       .id_table       = trm290_pci_tbl,
+       .probe          = trm290_init_one,
+       .remove         = ide_pci_remove,
+};
+
+static int __init trm290_ide_init(void)
+{
+       return ide_pci_register_driver(&trm290_pci_driver);
+}
+
+static void __exit trm290_ide_exit(void)
+{
+       pci_unregister_driver(&trm290_pci_driver);
+}
+
+module_init(trm290_ide_init);
+module_exit(trm290_ide_exit);
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
new file mode 100644 (file)
index 0000000..1da076e
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
+ */
+
+/*
+ *  Principal Author/Maintainer:  PODIEN@hml2.atlas.de (Wolfram Podien)
+ *
+ *  This file provides support for the advanced features
+ *  of the UMC 8672 IDE interface.
+ *
+ *  Version 0.01       Initial version, hacked out of ide.c,
+ *                     and #include'd rather than compiled separately.
+ *                     This will get cleaned up in a subsequent release.
+ *
+ *  Version 0.02       now configs/compiles separate from ide.c  -ml
+ *  Version 0.03       enhanced auto-tune, fix display bug
+ *  Version 0.05       replace sti() with restore_flags()  -ml
+ *                     add detection of possible race condition  -ml
+ */
+
+/*
+ * VLB Controller Support from
+ * Wolfram Podien
+ * Rohoefe 3
+ * D28832 Achim
+ * Germany
+ *
+ * To enable UMC8672 support there must a lilo line like
+ * append="ide0=umc8672"...
+ * To set the speed according to the abilities of the hardware there must be a
+ * line like
+ * #define UMC_DRIVE0 11
+ * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
+ * are some lines present). 0 - 11 are allowed speed values. These values are
+ * the results from the DOS speed test program supplied from UMC. 11 is the
+ * highest speed (about PIO mode 3)
+ */
+#define REALLY_SLOW_IO         /* some systems can safely undef this */
+
+#include <linux/module.h>
+#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/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define DRV_NAME "umc8672"
+
+/*
+ * Default speeds.  These can be changed with "auto-tune" and/or hdparm.
+ */
+#define UMC_DRIVE0      1              /* DOS measured drive speeds */
+#define UMC_DRIVE1      1              /* 0 to 11 allowed */
+#define UMC_DRIVE2      1              /* 11 = Fastest Speed */
+#define UMC_DRIVE3      1              /* In case of crash reduce speed */
+
+static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
+static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11};    /* rough guesses */
+
+/*       0    1    2    3    4    5    6    7    8    9    10   11      */
+static const u8 speedtab [3][12] = {
+       {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
+       {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
+       {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0}
+};
+
+static void out_umc(char port, char wert)
+{
+       outb_p(port, 0x108);
+       outb_p(wert, 0x109);
+}
+
+static inline u8 in_umc(char port)
+{
+       outb_p(port, 0x108);
+       return inb_p(0x109);
+}
+
+static void umc_set_speeds(u8 speeds[])
+{
+       int i, tmp;
+
+       outb_p(0x5A, 0x108); /* enable umc */
+
+       out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
+       out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
+       tmp = 0;
+       for (i = 3; i >= 0; i--)
+               tmp = (tmp << 2) | speedtab[1][speeds[i]];
+       out_umc(0xdc, tmp);
+       for (i = 0; i < 4; i++) {
+               out_umc(0xd0 + i, speedtab[2][speeds[i]]);
+               out_umc(0xd8 + i, speedtab[2][speeds[i]]);
+       }
+       outb_p(0xa5, 0x108); /* disable umc */
+
+       printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
+               speeds[0], speeds[1], speeds[2], speeds[3]);
+}
+
+static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       unsigned long flags;
+
+       printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
+               drive->name, pio, pio_to_umc[pio]);
+       spin_lock_irqsave(&ide_lock, flags);
+       if (hwif->mate && hwif->mate->hwgroup->handler) {
+               printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
+       } else {
+               current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
+               umc_set_speeds(current_speeds);
+       }
+       spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+static const struct ide_port_ops umc8672_port_ops = {
+       .set_pio_mode           = umc_set_pio_mode,
+};
+
+static const struct ide_port_info umc8672_port_info __initdata = {
+       .name                   = DRV_NAME,
+       .chipset                = ide_umc8672,
+       .port_ops               = &umc8672_port_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+       .pio_mask               = ATA_PIO4,
+};
+
+static int __init umc8672_probe(void)
+{
+       unsigned long flags;
+
+       if (!request_region(0x108, 2, "umc8672")) {
+               printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
+               return 1;
+       }
+       local_irq_save(flags);
+       outb_p(0x5A, 0x108); /* enable umc */
+       if (in_umc (0xd5) != 0xa0) {
+               local_irq_restore(flags);
+               printk(KERN_ERR "umc8672: not found\n");
+               release_region(0x108, 2);
+               return 1;
+       }
+       outb_p(0xa5, 0x108); /* disable umc */
+
+       umc_set_speeds(current_speeds);
+       local_irq_restore(flags);
+
+       return ide_legacy_device_add(&umc8672_port_info, 0);
+}
+
+static int probe_umc8672;
+
+module_param_named(probe, probe_umc8672, bool, 0);
+MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
+
+static int __init umc8672_init(void)
+{
+       if (probe_umc8672 == 0)
+               goto out;
+
+       if (umc8672_probe() == 0)
+               return 0;;
+out:
+       return -ENODEV;;
+}
+
+module_init(umc8672_init);
+
+MODULE_AUTHOR("Wolfram Podien");
+MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
new file mode 100644 (file)
index 0000000..2a812d3
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * VIA IDE driver for Linux. Supported southbridges:
+ *
+ *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
+ *   vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a,
+ *   vt8235, vt8237, vt8237a
+ *
+ * Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
+ *
+ * Based on the work of:
+ *     Michel Aubry
+ *     Jeff Garzik
+ *     Andre Hedrick
+ *
+ * Documentation:
+ *     Obsolete device documentation publically available from via.com.tw
+ *     Current device documentation available under NDA only
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/dmi.h>
+
+#ifdef CONFIG_PPC_CHRP
+#include <asm/processor.h>
+#endif
+
+#define DRV_NAME "via82cxxx"
+
+#define VIA_IDE_ENABLE         0x40
+#define VIA_IDE_CONFIG         0x41
+#define VIA_FIFO_CONFIG                0x43
+#define VIA_MISC_1             0x44
+#define VIA_MISC_2             0x45
+#define VIA_MISC_3             0x46
+#define VIA_DRIVE_TIMING       0x48
+#define VIA_8BIT_TIMING                0x4e
+#define VIA_ADDRESS_SETUP      0x4c
+#define VIA_UDMA_TIMING                0x50
+
+#define VIA_BAD_PREQ           0x01 /* Crashes if PREQ# till DDACK# set */
+#define VIA_BAD_CLK66          0x02 /* 66 MHz clock doesn't work correctly */
+#define VIA_SET_FIFO           0x04 /* Needs to have FIFO split set */
+#define VIA_NO_UNMASK          0x08 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID             0x10 /* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST            0x20 /* Don't touch Address Setup Timing */
+
+/*
+ * VIA SouthBridge chips.
+ */
+
+static struct via_isa_bridge {
+       char *name;
+       u16 id;
+       u8 rev_min;
+       u8 rev_max;
+       u8 udma_mask;
+       u8 flags;
+} via_isa_bridges[] = {
+       { "vx800",      PCI_DEVICE_ID_VIA_VX800,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "cx700",      PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8237s",    PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt6410",     PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8251",     PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8237",     PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8237a",    PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8235",     PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8233a",    PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+       { "vt8233c",    PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, ATA_UDMA5, },
+       { "vt8233",     PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, ATA_UDMA5, },
+       { "vt8231",     PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, ATA_UDMA5, },
+       { "vt82c686b",  PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, ATA_UDMA5, },
+       { "vt82c686a",  PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, ATA_UDMA4, },
+       { "vt82c686",   PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+       { "vt82c596b",  PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, ATA_UDMA4, },
+       { "vt82c596a",  PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+       { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
+       { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
+       { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
+       { "vt82c586a",  PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
+       { "vt82c586",   PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f,      0x00, VIA_SET_FIFO },
+       { "vt82c576",   PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
+       { "vt82c576",   PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+       { NULL }
+};
+
+static unsigned int via_clock;
+static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
+
+struct via82cxxx_dev
+{
+       struct via_isa_bridge *via_config;
+       unsigned int via_80w;
+};
+
+/**
+ *     via_set_speed                   -       write timing registers
+ *     @dev: PCI device
+ *     @dn: device
+ *     @timing: IDE timing data to use
+ *
+ *     via_set_speed writes timing values to the chipset registers
+ */
+
+static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
+{
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+       u8 t;
+
+       if (~vdev->via_config->flags & VIA_BAD_AST) {
+               pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
+               t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+               pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+       }
+
+       pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
+               ((clamp_val(timing->act8b, 1, 16) - 1) << 4) | (clamp_val(timing->rec8b, 1, 16) - 1));
+
+       pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
+               ((clamp_val(timing->active, 1, 16) - 1) << 4) | (clamp_val(timing->recover, 1, 16) - 1));
+
+       switch (vdev->via_config->udma_mask) {
+       case ATA_UDMA2: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 5) - 2)) : 0x03; break;
+       case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break;
+       case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
+       case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
+       default: return;
+       }
+
+       pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
+}
+
+/**
+ *     via_set_drive           -       configure transfer mode
+ *     @drive: Drive to set up
+ *     @speed: desired speed
+ *
+ *     via_set_drive() computes timing values configures the chipset to
+ *     a desired transfer mode.  It also can be called by upper layers.
+ */
+
+static void via_set_drive(ide_drive_t *drive, const u8 speed)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       ide_drive_t *peer = ide_get_pair_dev(drive);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+       struct ide_timing t, p;
+       unsigned int T, UT;
+
+       T = 1000000000 / via_clock;
+
+       switch (vdev->via_config->udma_mask) {
+       case ATA_UDMA2: UT = T;   break;
+       case ATA_UDMA4: UT = T/2; break;
+       case ATA_UDMA5: UT = T/3; break;
+       case ATA_UDMA6: UT = T/4; break;
+       default:        UT = T;
+       }
+
+       ide_timing_compute(drive, speed, &t, T, UT);
+
+       if (peer) {
+               ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+               ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
+       }
+
+       via_set_speed(HWIF(drive), drive->dn, &t);
+}
+
+/**
+ *     via_set_pio_mode        -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
+ *
+ *     A callback from the upper layers for PIO-only tuning.
+ */
+
+static void via_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       via_set_drive(drive, XFER_PIO_0 + pio);
+}
+
+static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
+{
+       struct via_isa_bridge *via_config;
+
+       for (via_config = via_isa_bridges; via_config->id; via_config++)
+               if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA +
+                       !!(via_config->flags & VIA_BAD_ID),
+                       via_config->id, NULL))) {
+
+                       if ((*isa)->revision >= via_config->rev_min &&
+                           (*isa)->revision <= via_config->rev_max)
+                               break;
+                       pci_dev_put(*isa);
+               }
+
+       return via_config;
+}
+
+/*
+ * Check and handle 80-wire cable presence
+ */
+static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
+{
+       int i;
+
+       switch (vdev->via_config->udma_mask) {
+               case ATA_UDMA4:
+                       for (i = 24; i >= 0; i -= 8)
+                               if (((u >> (i & 16)) & 8) &&
+                                   ((u >> i) & 0x20) &&
+                                    (((u >> i) & 7) < 2)) {
+                                       /*
+                                        * 2x PCI clock and
+                                        * UDMA w/ < 3T/cycle
+                                        */
+                                       vdev->via_80w |= (1 << (1 - (i >> 4)));
+                               }
+                       break;
+
+               case ATA_UDMA5:
+                       for (i = 24; i >= 0; i -= 8)
+                               if (((u >> i) & 0x10) ||
+                                   (((u >> i) & 0x20) &&
+                                    (((u >> i) & 7) < 4))) {
+                                       /* BIOS 80-wire bit or
+                                        * UDMA w/ < 60ns/cycle
+                                        */
+                                       vdev->via_80w |= (1 << (1 - (i >> 4)));
+                               }
+                       break;
+
+               case ATA_UDMA6:
+                       for (i = 24; i >= 0; i -= 8)
+                               if (((u >> i) & 0x10) ||
+                                   (((u >> i) & 0x20) &&
+                                    (((u >> i) & 7) < 6))) {
+                                       /* BIOS 80-wire bit or
+                                        * UDMA w/ < 60ns/cycle
+                                        */
+                                       vdev->via_80w |= (1 << (1 - (i >> 4)));
+                               }
+                       break;
+       }
+}
+
+/**
+ *     init_chipset_via82cxxx  -       initialization handler
+ *     @dev: PCI device
+ *
+ *     The initialization callback. Here we determine the IDE chip type
+ *     and initialize its drive independent registers.
+ */
+
+static unsigned int init_chipset_via82cxxx(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+       struct via_isa_bridge *via_config = vdev->via_config;
+       u8 t, v;
+       u32 u;
+
+       /*
+        * Detect cable and configure Clk66
+        */
+       pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+
+       via_cable_detect(vdev, u);
+
+       if (via_config->udma_mask == ATA_UDMA4) {
+               /* Enable Clk66 */
+               pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
+       } else if (via_config->flags & VIA_BAD_CLK66) {
+               /* Would cause trouble on 596a and 686 */
+               pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008);
+       }
+
+       /*
+        * Check whether interfaces are enabled.
+        */
+
+       pci_read_config_byte(dev, VIA_IDE_ENABLE, &v);
+
+       /*
+        * Set up FIFO sizes and thresholds.
+        */
+
+       pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);
+
+       /* Disable PREQ# till DDACK# */
+       if (via_config->flags & VIA_BAD_PREQ) {
+               /* Would crash on 586b rev 41 */
+               t &= 0x7f;
+       }
+
+       /* Fix FIFO split between channels */
+       if (via_config->flags & VIA_SET_FIFO) {
+               t &= (t & 0x9f);
+               switch (v & 3) {
+                       case 2: t |= 0x00; break;       /* 16 on primary */
+                       case 1: t |= 0x60; break;       /* 16 on secondary */
+                       case 3: t |= 0x20; break;       /* 8 pri 8 sec */
+               }
+       }
+
+       pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
+
+       return 0;
+}
+
+/*
+ *     Cable special cases
+ */
+
+static const struct dmi_system_id cable_dmi_table[] = {
+       {
+               .ident = "Acer Ferrari 3400",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+                       DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+               },
+       },
+       { }
+};
+
+static int via_cable_override(struct pci_dev *pdev)
+{
+       /* Systems by DMI */
+       if (dmi_check_system(cable_dmi_table))
+               return 1;
+
+       /* Arima W730-K8/Targa Visionary 811/... */
+       if (pdev->subsystem_vendor == 0x161F &&
+           pdev->subsystem_device == 0x2032)
+               return 1;
+
+       return 0;
+}
+
+static u8 via82cxxx_cable_detect(ide_hwif_t *hwif)
+{
+       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       struct ide_host *host = pci_get_drvdata(pdev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+
+       if (via_cable_override(pdev))
+               return ATA_CBL_PATA40_SHORT;
+
+       if ((vdev->via_80w >> hwif->channel) & 1)
+               return ATA_CBL_PATA80;
+       else
+               return ATA_CBL_PATA40;
+}
+
+static const struct ide_port_ops via_port_ops = {
+       .set_pio_mode           = via_set_pio_mode,
+       .set_dma_mode           = via_set_drive,
+       .cable_detect           = via82cxxx_cable_detect,
+};
+
+static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+       .name           = DRV_NAME,
+       .init_chipset   = init_chipset_via82cxxx,
+       .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+       .port_ops       = &via_port_ops,
+       .host_flags     = IDE_HFLAG_PIO_NO_BLACKLIST |
+                         IDE_HFLAG_POST_SET_MODE |
+                         IDE_HFLAG_IO_32BIT,
+       .pio_mask       = ATA_PIO5,
+       .swdma_mask     = ATA_SWDMA2,
+       .mwdma_mask     = ATA_MWDMA2,
+};
+
+static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct pci_dev *isa = NULL;
+       struct via_isa_bridge *via_config;
+       struct via82cxxx_dev *vdev;
+       int rc;
+       u8 idx = id->driver_data;
+       struct ide_port_info d;
+
+       d = via82cxxx_chipset;
+
+       /*
+        * Find the ISA bridge and check we know what it is.
+        */
+       via_config = via_config_find(&isa);
+       if (!via_config->id) {
+               printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n",
+                       pci_name(dev));
+               return -ENODEV;
+       }
+
+       /*
+        * Print the boot message.
+        */
+       printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n",
+               pci_name(dev), via_config->name, isa->revision,
+               via_config->udma_mask ? "U" : "MW",
+               via_dma[via_config->udma_mask ?
+                       (fls(via_config->udma_mask) - 1) : 0]);
+
+       pci_dev_put(isa);
+
+       /*
+        * Determine system bus clock.
+        */
+       via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+       switch (via_clock) {
+       case 33000: via_clock = 33333; break;
+       case 37000: via_clock = 37500; break;
+       case 41000: via_clock = 41666; break;
+       }
+
+       if (via_clock < 20000 || via_clock > 50000) {
+               printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
+                       "impossible (%d), using 33 MHz instead.\n", via_clock);
+               printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
+                       "to assume 80-wire cable.\n");
+               via_clock = 33333;
+       }
+
+       if (idx == 0)
+               d.host_flags |= IDE_HFLAG_NO_AUTODMA;
+       else
+               d.enablebits[1].reg = d.enablebits[0].reg = 0;
+
+       if ((via_config->flags & VIA_NO_UNMASK) == 0)
+               d.host_flags |= IDE_HFLAG_UNMASK_IRQS;
+
+#ifdef CONFIG_PPC_CHRP
+       if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos)
+               d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
+#endif
+
+       d.udma_mask = via_config->udma_mask;
+
+       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+       if (!vdev) {
+               printk(KERN_ERR DRV_NAME " %s: out of memory :(\n",
+                       pci_name(dev));
+               return -ENOMEM;
+       }
+
+       vdev->via_config = via_config;
+
+       rc = ide_pci_init_one(dev, &d, vdev);
+       if (rc)
+               kfree(vdev);
+
+       return rc;
+}
+
+static void __devexit via_remove(struct pci_dev *dev)
+{
+       struct ide_host *host = pci_get_drvdata(dev);
+       struct via82cxxx_dev *vdev = host->host_priv;
+
+       ide_pci_remove(dev);
+       kfree(vdev);
+}
+
+static const struct pci_device_id via_pci_tbl[] = {
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1),  0 },
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1),  0 },
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 },
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410),      1 },
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, via_pci_tbl);
+
+static struct pci_driver via_pci_driver = {
+       .name           = "VIA_IDE",
+       .id_table       = via_pci_tbl,
+       .probe          = via_init_one,
+       .remove         = __devexit_p(via_remove),
+       .suspend        = ide_pci_suspend,
+       .resume         = ide_pci_resume,
+};
+
+static int __init via_ide_init(void)
+{
+       return ide_pci_register_driver(&via_pci_driver);
+}
+
+static void __exit via_ide_exit(void)
+{
+       pci_unregister_driver(&via_pci_driver);
+}
+
+module_init(via_ide_init);
+module_exit(via_ide_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
+MODULE_DESCRIPTION("PCI driver module for VIA IDE");
+MODULE_LICENSE("GPL");