]> git.hungrycats.org Git - linux/commitdiff
[PATCH] 2.5.8-pre2 IDE 29b
authorMartin Dalecki <dalecki@evision-ventures.com>
Tue, 9 Apr 2002 04:08:04 +0000 (21:08 -0700)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Tue, 9 Apr 2002 04:08:04 +0000 (21:08 -0700)
- Eliminate the mate member of the ata_channel structure. The information
   provided by it is already present. This patch may have undesirable
   effects on the ns87415.c and trm290.c host chip drivers, but it's worth
   for structural reasons to have it.

- Kill unused code, which was "fixing" interrupt routing from ide-pci.c Don't
   pass any "mate" between the functions there.

- Don't define SUPPORT_VLB_SYNC unconditionally in ide-taskfile.c

- Apply Vojtech Pavliks fix for piix host-chip driver crashes.

- Add linux/types.h to ide-pnp.c.

- Apply latest sis5513 host chip driver patch from by Lionel Bouton by hand.

- Apply patch by Paul Macerras for power-mac.

- Try to make the ns87415 driver a bit more reentrant.

22 files changed:
MAINTAINERS
drivers/ide/ali14xx.c
drivers/ide/cmd640.c
drivers/ide/cs5530.c
drivers/ide/dtc2278.c
drivers/ide/hpt366.c
drivers/ide/ht6560b.c
drivers/ide/ide-dma.c
drivers/ide/ide-pci.c
drivers/ide/ide-pmac.c
drivers/ide/ide-pnp.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide.c
drivers/ide/ns87415.c
drivers/ide/pdc4030.c
drivers/ide/piix.c
drivers/ide/qd65xx.c
drivers/ide/sis5513.c
drivers/ide/trm290.c
drivers/ide/umc8672.c
include/linux/ide.h

index 5388402bb014f2c504a549e2f635dd4e1f797f7c..7f26fd691965cc221c3deeea4d27b31acc72da58 100644 (file)
@@ -1386,6 +1386,13 @@ P:       Ingo Molnar
 M:     mingo@redhat.com
 S:     Maintained
 
+SIS 5513 IDE CONTROLLER DRIVER
+P:      Lionel Bouton
+M:      Lionel.Bouton@inet6.fr
+W:      http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html
+W:      http://gyver.homeip.net/sis5513/index.html
+S:      Maintained
+
 SIS 900/7016 FAST ETHERNET DRIVER
 P:     Ollie Lho
 M:     ollie@sis.com.tw
index 10861d49571a92feb341a33905987386bdbff5c7..a735a8386c3462a46ad07c9fa2f0f846ea324e87 100644 (file)
@@ -212,9 +212,8 @@ void __init init_ali14xx (void)
        ide_hwifs[1].chipset = ide_ali14xx;
        ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
        ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
-       ide_hwifs[0].mate = &ide_hwifs[1];
-       ide_hwifs[1].mate = &ide_hwifs[0];
-       ide_hwifs[1].unit = 1;
+       ide_hwifs[0].unit = ATA_PRIMARY;
+       ide_hwifs[1].unit = ATA_SECONDARY;
 
        /* initialize controller registers */
        if (!initRegisters()) {
index 65aaf22b781c62f1f7703725f31cd8cb49b68aa0..4c7191cb33eaa35a96fdb552c07fe2ccc2d05f76 100644 (file)
@@ -689,7 +689,7 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted)
 /*
  * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
  */
-int __init ide_probe_for_cmd640x (void)
+int __init ide_probe_for_cmd640x(void)
 {
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
        int second_port_toggled = 0;
@@ -793,9 +793,7 @@ int __init ide_probe_for_cmd640x (void)
                cmd_hwif0->serialized = 1;
                cmd_hwif1->serialized = 1;
                cmd_hwif1->chipset = ide_cmd640;
-               cmd_hwif0->mate = cmd_hwif1;
-               cmd_hwif1->mate = cmd_hwif0;
-               cmd_hwif1->unit = 1;
+               cmd_hwif1->unit = ATA_SECONDARY;
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
                cmd_hwif1->tuneproc = &cmd640_tune_drive;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
@@ -811,8 +809,8 @@ int __init ide_probe_for_cmd640x (void)
                ide_drive_t *drive = cmd_drives[index];
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
                if (drive->autotune || ((index > 1) && second_port_toggled)) {
-                       /*
-                        * Reset timing to the slowest speed and turn off prefetch.
+                       /*
+                        * Reset timing to the slowest speed and turn off prefetch.
                         * This way, the drive identify code has a better chance.
                         */
                        setup_counts    [index] = 4;    /* max possible */
index 34526fa33404e26707d49abf17fe0f04e8c872b1..cc884486d03dfb0bea5b426b4d746b077fbf5620 100644 (file)
@@ -346,8 +346,7 @@ unsigned int __init pci_init_cs5530(struct pci_dev *dev)
  */
 void __init ide_init_cs5530(struct ata_channel *hwif)
 {
-       if (hwif->mate)
-               hwif->serialized = hwif->mate->serialized = 1;
+       hwif->serialized = 1;
        if (!hwif->dma_base) {
                hwif->autodma = 0;
        } else {
index b2cf501d9bc37acea7f5c9771fedb070006d1ae8..bec9cab6fc2c10362693b503f36b679e6c278d75 100644 (file)
@@ -124,7 +124,6 @@ void __init init_dtc2278 (void)
        ide_hwifs[0].drives[1].no_unmask = 1;
        ide_hwifs[1].drives[0].no_unmask = 1;
        ide_hwifs[1].drives[1].no_unmask = 1;
-       ide_hwifs[0].mate = &ide_hwifs[1];
-       ide_hwifs[1].mate = &ide_hwifs[0];
-       ide_hwifs[1].unit = 1;
+       ide_hwifs[0].unit = ATA_PRIMARY;
+       ide_hwifs[1].unit = ATA_SECONDARY;
 }
index 0703504f96f7afedaab8da80c397d81b45b07c3c..963bb034f4a567ac3931fdfbbd4ffb2168acb7bd 100644 (file)
@@ -1125,13 +1125,13 @@ unsigned int __init pci_init_hpt366(struct pci_dev *dev)
 
        if (n_hpt_devs < HPT366_MAX_DEVS)
                hpt_devs[n_hpt_devs++] = dev;
-       
+
 #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
        if (!hpt366_proc) {
                hpt366_proc = 1;
                hpt366_display_info = &hpt366_get_info;
        }
-#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
+#endif
 
        return dev->irq;
 }
@@ -1146,7 +1146,7 @@ unsigned int __init ata66_hpt366(struct ata_channel *hwif)
        printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
                ata66, (ata66 & regmask) ? "33" : "66",
                PCI_FUNC(hwif->pci_dev->devfn));
-#endif /* DEBUG */
+#endif
        return ((ata66 & regmask) ? 0 : 1);
 }
 
index 4212382f45d68dcccb912c71e8f0ffec2f1a3bb4..f5ef34f08f1a0940b0abc08abe1ef9969393a079 100644 (file)
@@ -319,10 +319,9 @@ void __init init_ht6560b (void)
                        ide_hwifs[1].tuneproc = &tune_ht6560b;
                        ide_hwifs[0].serialized = 1;  /* is this needed? */
                        ide_hwifs[1].serialized = 1;  /* is this needed? */
-                       ide_hwifs[0].mate = &ide_hwifs[1];
-                       ide_hwifs[1].mate = &ide_hwifs[0];
-                       ide_hwifs[1].unit = 1;
-                       
+                       ide_hwifs[0].unit = ATA_PRIMARY;
+                       ide_hwifs[1].unit = ATA_SECONDARY;
+
                        /*
                         * Setting default configurations for drives
                         */
index a2b53f68fe3fc94a3be3f869630c7af950c425d3..8979a5fa9fa0508ca62e2b6d1b7a7ea67c464cdd 100644 (file)
@@ -421,7 +421,7 @@ int check_drive_lists (ide_drive_t *drive, int good_bad)
        return 0;
 }
 
-static int report_drive_dmaing (ide_drive_t *drive)
+int report_drive_dmaing (ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
 
index 486f3bca98cd6fc1fb5bc57f467a89aab0a4ba1f..23654b14202d5281ec8bfab0d122fb91a31a6bfc 100644 (file)
@@ -182,7 +182,7 @@ typedef struct ide_pci_device_s {
        unsigned short          device;
        unsigned int            (*init_chipset)(struct pci_dev *dev);
        unsigned int            (*ata66_check)(struct ata_channel *hwif);
-       void                    (*init_hwif)(struct ata_channel *hwif);
+       void                    (*init_channel)(struct ata_channel *hwif);
        void                    (*dma_init)(struct ata_channel *hwif, unsigned long dmabase);
        ide_pci_enablebit_t     enablebits[2];
        unsigned int            bootable;
@@ -436,24 +436,21 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
        unsigned long   dma_base = 0;
        struct pci_dev  *dev = hwif->pci_dev;
 
-       /*
-        * If we are on the second channel, the dma base address will be one
-        * entry away from the primary interface.
-        */
-
-       if (hwif->mate && hwif->mate->dma_base)
-               dma_base = hwif->mate->dma_base - (hwif->unit ? 0 : 8);
-       else
-               dma_base = pci_resource_start(dev, 4);
-
+       dma_base = pci_resource_start(dev, 4);
        if (!dma_base)
                return 0;
 
-       if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
+       /* PDC20246, PDC20262, HPT343, & HPT366 */
+       if (extra) {
                request_region(dma_base + 16, extra, name);
+               hwif->dma_extra = extra;
+       }
 
-       dma_base += hwif->unit ? 8 : 0;
-       hwif->dma_extra = extra;
+       /* If we are on the second channel, the dma base address will be one
+        * entry away from the primary interface.
+        */
+       if (hwif->unit == ATA_SECONDARY)
+               dma_base += 8;
 
        if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) ||
                        (dev->vendor == PCI_VENDOR_ID_AMD && dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) ||
@@ -463,8 +460,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
                        printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
        } else {
 
-               /*
-                * If the device claims "simplex" DMA, this means only one of
+               /* If the device claims "simplex" DMA, this means only one of
                 * the two interfaces can be trusted with DMA at any point in
                 * time.  So we should enable DMA only on one of the two
                 * interfaces.
@@ -472,7 +468,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
 
                if ((inb(dma_base + 2) & 0x80)) {
                        if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
-                                       (hwif->mate && hwif->mate->dma_base)) {
+                               hwif->unit == ATA_SECONDARY) {
                                printk("%s: simplex device:  DMA disabled\n", name);
                                dma_base = 0;
                        }
@@ -489,8 +485,9 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
                ide_pci_device_t *d,
                int port,
                u8 class_rev,
-               int pciirq, struct ata_channel **mate,
-               int autodma, unsigned short *pcicmd)
+               int pciirq,
+               int autodma,
+               unsigned short *pcicmd)
 {
        unsigned long dma_base;
 
@@ -503,8 +500,13 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
        if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
                return;
 
-       dma_base = get_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name);
-       if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) {
+       dma_base = get_dma_base(hwif, ((port == ATA_PRIMARY) && d->extra) ? d->extra : 0, dev->name);
+       if (!dma_base) {
+               printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
+
+               return;
+       }
+       if (!(*pcicmd & PCI_COMMAND_MASTER)) {
 
                /*
                 * Set up BM-DMA capability (PnP BIOS should have done this already)
@@ -517,13 +519,10 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
                        dma_base = 0;
                }
        }
-       if (dma_base) {
-               if (d->dma_init)
-                       d->dma_init(hwif, dma_base);
-               else
-                       ide_setup_dma(hwif, dma_base, 8);
-       } else
-               printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
+       if (d->dma_init)
+               d->dma_init(hwif, dma_base);
+       else
+               ide_setup_dma(hwif, dma_base, 8);
 }
 #endif
 
@@ -537,17 +536,16 @@ static int __init setup_host_channel(struct pci_dev *dev,
                int port,
                u8 class_rev,
                int pciirq,
-               struct ata_channel **mate,
                int autodma,
                unsigned short *pcicmd)
 {
        unsigned long base = 0;
        unsigned long ctl = 0;
        ide_pci_enablebit_t *e = &(d->enablebits[port]);
-       struct ata_channel *hwif;
+       struct ata_channel *ch;
 
        u8 tmp;
-       if (port == 1) {
+       if (port == ATA_SECONDARY) {
 
                /* If this is a Promise FakeRaid controller, the 2nd controller
                 * will be marked as disabled while it is actually there and
@@ -569,7 +567,7 @@ static int __init setup_host_channel(struct pci_dev *dev,
 
        /* Nothing to be done for the second port.
         */
-       if (port == 1) {
+       if (port == ATA_SECONDARY) {
                if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03))
                        return 0;
        }
@@ -599,57 +597,50 @@ controller_ok:
        if (!base)
                base = port ? 0x170 : 0x1f0;
 
-       if ((hwif = lookup_hwif(base, d->bootable, dev->name)) == NULL)
+       if ((ch = lookup_hwif(base, d->bootable, dev->name)) == NULL)
                return -ENOMEM; /* no room in ide_hwifs[] */
 
-       if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
-               ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
-               memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
-               hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+       if (ch->io_ports[IDE_DATA_OFFSET] != base) {
+               ide_init_hwif_ports(&ch->hw, base, (ctl | 2), NULL);
+               memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
+               ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
        }
 
-       hwif->chipset = ide_pci;
-       hwif->pci_dev = dev;
-       hwif->unit = port;
-       if (!hwif->irq)
-               hwif->irq = pciirq;
+       ch->chipset = ide_pci;
+       ch->pci_dev = dev;
+       ch->unit = port;
+       if (!ch->irq)
+               ch->irq = pciirq;
 
-       /* Setup the mate interface if we have two channels.
+       /* Serialize the interfaces if requested by configuration information.
         */
-       if (*mate) {
-               hwif->mate = *mate;
-               (*mate)->mate = hwif;
-               if (d->flags & ATA_F_SER) {
-                       hwif->serialized = 1;
-                       (*mate)->serialized = 1;
-               }
-       }
+       if (d->flags & ATA_F_SER)
+           ch->serialized = 1;
 
        /* Cross wired IRQ lines on UMC chips and no DMA transfers.*/
        if (d->flags & ATA_F_FIXIRQ) {
-               hwif->irq = port ? 15 : 14;
+               ch->irq = port ? 15 : 14;
                goto no_dma;
        }
        if (d->flags & ATA_F_NODMA)
                goto no_dma;
 
        /* Check whatever this interface is UDMA4 mode capable. */
-       if (hwif->udma_four) {
+       if (ch->udma_four) {
                printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
        } else {
                if (d->ata66_check)
-                       hwif->udma_four = d->ata66_check(hwif);
+                       ch->udma_four = d->ata66_check(ch);
        }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-       setup_channel_dma(hwif, dev, d, port, class_rev, pciirq,  mate, autodma, pcicmd);
+       setup_channel_dma(ch, dev, d, port, class_rev, pciirq, autodma, pcicmd);
 #endif
 
 no_dma:
-       if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
-               d->init_hwif(hwif);
-
-       *mate = hwif;
+       /* Call chipset-specific routine for each enabled channel. */
+       if (d->init_channel)
+               d->init_channel(ch);
 
        return 0;
 }
@@ -671,7 +662,6 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
        int pciirq = 0;
        unsigned short pcicmd = 0;
        unsigned short tried_config = 0;
-       struct ata_channel *mate = NULL;
        unsigned int class_rev;
 
 #ifdef CONFIG_IDEDMA_AUTO
@@ -679,9 +669,9 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
                autodma = 1;
 #endif
 
-       if (d->init_hwif == IDE_NO_DRIVER) {
+       if (d->init_channel == IDE_NO_DRIVER) {
                printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", dev->name);
-               d->init_hwif = NULL;
+               d->init_channel = NULL;
        }
 
        if (pci_enable_device(dev)) {
@@ -779,8 +769,8 @@ check_if_enabled:
        /*
         * Set up IDE chanells. First the primary, then the secondary.
         */
-       setup_host_channel(dev, d, 0, class_rev, pciirq, &mate, autodma, &pcicmd);
-       setup_host_channel(dev, d, 1, class_rev, pciirq, &mate, autodma, &pcicmd);
+       setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma, &pcicmd);
+       setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd);
 }
 
 static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
@@ -856,12 +846,6 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
                        if (hpt363_shared_pin && hpt363_shared_irq) {
                                d->bootable = ON_BOARD;
                                printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2);
-#if 0
-                               /* I forgot why I did this once, but it fixed something. */
-                               pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
-                               printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
-                               pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
-#endif
                        }
                        break;
                }
@@ -894,7 +878,7 @@ static void __init scan_pcidev(struct pci_dev *dev)
        while (d->vendor && !(d->vendor == vendor && d->device == device))
                ++d;
 
-       if (d->init_hwif == ATA_PCI_IGNORE)
+       if (d->init_channel == ATA_PCI_IGNORE)
                printk("%s: has been ignored by PCI bus scan\n", dev->name);
        else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1))
                return;
index 5223f54a51e1d91bc5c879bcef0fe048597f9225..dc31ffc78f4c67125ba63efe7f97f784d1420690 100644 (file)
  * Some code taken from drivers/ide/ide-dma.c:
  *
  *  Copyright (c) 1995-1998  Mark Lord
+ *  
+ * TODO:
+ * 
+ *  - Find a way to duplicate less code with ide-dma and use the
+ *    dma fileds in the hwif structure instead of our own
+ *  - Fix check_disk_change() call
+ *  - Make module-able (includes setting ppc_md. hooks from within
+ *    this file and not from arch code, and handling module deps with
+ *    mediabay (by having both modules do dynamic lookup of each other
+ *    symbols or by storing hooks at arch level).
  *
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/pci.h>
 
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/ide.h>
 #include <asm/mediabay.h>
-#include <asm/feature.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/sections.h>
+#include <asm/irq.h>
 #ifdef CONFIG_PMAC_PBOOK
 #include <linux/adb.h>
 #include <linux/pmu.h>
-#include <asm/irq.h>
 #endif
 #include "ata-timing.h"
 
 extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
+extern spinlock_t ide_lock;
 
 #undef IDE_PMAC_DEBUG
 
-#define IDE_SYSCLK_NS          30
-#define IDE_SYSCLK_ULTRA_PS    0x1d4c /* (15 * 1000 / 2)*/
+#define DMA_WAIT_TIMEOUT       500
 
 struct pmac_ide_hwif {
        ide_ioreg_t                     regbase;
@@ -53,11 +67,20 @@ struct pmac_ide_hwif {
        struct device_node*             node;
        u32                             timings[2];
 #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*     dma_regs;
-       struct dbdma_cmd*               dma_table;
-#endif
+       struct dbdma_cmd*               dma_table_cpu;
+       dma_addr_t                      dma_table_dma;
+       struct scatterlist*             sg_table;
+       int                             sg_nents;
+       int                             sg_dma_direction;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
        
-} pmac_ide[MAX_HWIFS];
+} pmac_ide[MAX_HWIFS] __pmacdata;
 
 static int pmac_ide_count;
 
@@ -65,36 +88,160 @@ enum {
        controller_ohare,       /* OHare based */
        controller_heathrow,    /* Heathrow/Paddington */
        controller_kl_ata3,     /* KeyLargo ATA-3 */
-       controller_kl_ata4      /* KeyLargo ATA-4 */
+       controller_kl_ata4,     /* KeyLargo ATA-4 */
+       controller_kl_ata4_80   /* KeyLargo ATA-4 with 80 conductor cable */
 };
 
+/*
+ * Extra registers, both 32-bit little-endian
+ */
+#define IDE_TIMING_CONFIG      0x200
+#define IDE_INTERRUPT          0x300
+
+/*
+ * 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 */
+
+/* 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. I can't explain that, I tried it and it broke everything
+ * here.
+ */
+#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
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
 # define BAD_DMA_DRIVE         0
 # define GOOD_DMA_DRIVE                1
 
-typedef struct {
+/* 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;
-} pmac_ide_timing;
+};
 
-/* Multiword DMA timings */
-static pmac_ide_timing mdma_timings[] =
+struct mdma_timings_t mdma_timings_33[] __pmacdata =
 {
-    { 215,    480 },   /* Mode 0 */
-    {  80,    150 },   /*      1 */
-    {  70,    120 }    /*      2 */
+    { 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 }
 };
 
-/* Ultra DMA timings (for use when I know how to calculate them */
-static pmac_ide_timing udma_timings[] =
+struct mdma_timings_t mdma_timings_33k[] __pmacdata =
 {
-    {   0,    114 },   /* Mode 0 */
-    {   0,     75 },   /*      1 */
-    {   0,     55 },   /*      2 */
-    {   100,   45 },   /*      3 */
-    {   100,   25 }    /*      4 */
+    { 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[] __pmacdata =
+{
+    { 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 }
+};
+
+/* Ultra DMA timings (rounded) */
+struct {
+       int     addrSetup; /* ??? */
+       int     rdy2pause;
+       int     wrDataSetup;
+} udma_timings[] __pmacdata =
+{
+    {   0, 180,  120 },        /* Mode 0 */
+    {   0, 150,  90 }, /*      1 */
+    {   0, 120,  60 }, /*      2 */
+    {   0, 90,   45 }, /*      3 */
+    {   0, 90,   30 }  /*      4 */
 };
 
 /* allow up to 256 DBDMA commands per xfer */
@@ -124,7 +271,7 @@ struct pmu_sleep_notifier idepmac_sleep_notifier = {
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
-static int
+static int __pmac
 pmac_ide_find(ide_drive_t *drive)
 {
        struct ata_channel *hwif = drive->channel;
@@ -143,7 +290,8 @@ pmac_ide_find(ide_drive_t *drive)
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
-void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+void __pmac
+pmac_ide_init_hwif_ports(hw_regs_t *hw,
                              ide_ioreg_t data_port, ide_ioreg_t ctrl_port,
                              int *irq)
 {
@@ -174,7 +322,7 @@ void pmac_ide_init_hwif_ports(hw_regs_t *hw,
        ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
        ide_hwifs[ix].selectproc = pmac_ide_selectproc;
        ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
-       if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
+       if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) {
                ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
                if (!noautodma)
@@ -201,24 +349,33 @@ pmac_ide_get_devnode(ide_drive_t *drive)
 /* Setup timings for the selected drive (master/slave). I still need to verify if this
  * is enough, I beleive selectproc will be called whenever an IDE command is started,
  * but... */
-static void
+static void __pmac
 pmac_ide_selectproc(ide_drive_t *drive)
 {
        int i = pmac_ide_find(drive);
        if (i < 0)
                return;
-                       
-       if (drive->select.all & 0x10)
-               out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]);
+
+       if (drive->select.b.unit & 0x01)
+               out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
+                       pmac_ide[i].timings[1]);
        else
-               out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]);
+               out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
+                       pmac_ide[i].timings[0]);
+       (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
 }
 
-/* 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_UDMA(t)   (((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
 
-static __inline__ int
+/* Note: We don't use the generic routine here because for some
+ * yet unexplained reasons, it cause some media-bay CD-ROMs to
+ * lockup the bus. Strangely, this new version of the code is
+ * almost identical to the generic one and works, I've not yet
+ * managed to figure out what bit is causing the lockup in the
+ * generic code, possibly a timing issue...
+ * 
+ * --BenH
+ */
+static int __pmac
 wait_for_ready(ide_drive_t *drive)
 {
        /* Timeout bumped for some powerbooks */
@@ -244,57 +401,80 @@ wait_for_ready(ide_drive_t *drive)
        return 0;
 }
 
-/* Note: We don't use the generic routine here because some of Apple's
- * controller seem to be very sensitive about how things are done.
- * We should probably set the NIEN bit, but that's an example of thing
- * that can cause the controller to hang under some circumstances when
- * done on the media-bay CD-ROM during boot. We do get occasional
- * spurrious interrupts because of that.
- * --BenH
- */
-static int
+static int __pmac
 pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
 {
-       unsigned long flags;
        int result = 1;
-
-       save_flags(flags);
-       cli();
+       unsigned long flags;
+       struct ata_channel *hwif = HWIF(drive);
+       
+       disable_irq(hwif->irq); /* disable_irq_nosync ?? */
        udelay(1);
        SELECT_DRIVE(drive->channel, drive);
        SELECT_MASK(drive->channel, drive, 0);
        udelay(1);
+       (void)GET_STAT(); /* Get rid of pending error state */
        if(wait_for_ready(drive)) {
                printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
                goto out;
        }
-       OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+       udelay(10);
+       OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
        OUT_BYTE(command, IDE_NSECTOR_REG);
+       OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
        OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
        udelay(1);
+       __save_flags(flags);    /* local CPU only */
+       ide__sti();             /* local CPU only -- for jiffies */
        result = wait_for_ready(drive);
+       __restore_flags(flags); /* local CPU only */
+       OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
        if (result)
                printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
 out:
-       restore_flags(flags);
+       SELECT_MASK(HWIF(drive), drive, 0);
+       if (result == 0) {
+               drive->id->dma_ultra &= ~0xFF00;
+               drive->id->dma_mword &= ~0x0F00;
+               drive->id->dma_1word &= ~0x0F00;
+               switch(command) {
+                       case XFER_UDMA_7:   drive->id->dma_ultra |= 0x8080; break;
+                       case XFER_UDMA_6:   drive->id->dma_ultra |= 0x4040; break;
+                       case XFER_UDMA_5:   drive->id->dma_ultra |= 0x2020; break;
+                       case XFER_UDMA_4:   drive->id->dma_ultra |= 0x1010; break;
+                       case XFER_UDMA_3:   drive->id->dma_ultra |= 0x0808; break;
+                       case XFER_UDMA_2:   drive->id->dma_ultra |= 0x0404; break;
+                       case XFER_UDMA_1:   drive->id->dma_ultra |= 0x0202; break;
+                       case XFER_UDMA_0:   drive->id->dma_ultra |= 0x0101; break;
+                       case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
+                       case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
+                       case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
+                       case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
+                       case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
+                       case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
+                       default: break;
+               }
+       }
+       enable_irq(hwif->irq);
 
        return result;
 }
 
 /* Calculate PIO timings */
-static void
+static void __pmac
 pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
 {
        struct ata_timing *t;
        int i;
        u32 *timings;
-       int accessTicks, recTicks;
+       unsigned accessTicks, recTicks;
+       unsigned accessTime, recTime;
 
        i = pmac_ide_find(drive);
        if (i < 0)
                return;
 
-       if (pio = 255)
+       if (pio == 255)
                pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
        else
                pio = XFER_PIO_0 + min_t(byte, pio, 4);
@@ -302,27 +482,40 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
        t = ata_timing_data(pio);
 
        accessTicks = SYSCLK_TICKS(t->active);
-       if (drive->select.all & 0x10)
-               timings = &pmac_ide[i].timings[1];
-       else
-               timings = &pmac_ide[i].timings[0];
-
-       if (pmac_ide[i].kind == controller_kl_ata4) {
-               /* The "ata-4" IDE controller of Core99 machines */
-               accessTicks = SYSCLK_TICKS_UDMA(t->active * 1000);
-               recTicks = SYSCLK_TICKS_UDMA(t->cycle * 1000) - accessTicks;
-
-               *timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5);
+       timings = &pmac_ide[i].timings[drive->select.b.unit & 0x01];
+
+       recTime = t->cycle - t->active - t->setup;
+       recTime = max(recTime, 150U);
+       accessTime = t->active;
+       accessTime = max(accessTime, 150U);
+       if (pmac_ide[i].kind == controller_kl_ata4 ||
+               pmac_ide[i].kind == controller_kl_ata4_80) {
+               /* 66Mhz cell */
+               accessTicks = SYSCLK_TICKS_66(accessTime);
+               accessTicks = min(accessTicks, 0x1fU);
+               recTicks = SYSCLK_TICKS_66(recTime);
+               recTicks = min(recTicks, 0x1fU);
+               *timings = ((*timings) & ~TR_66_PIO_MASK) |
+                               (accessTicks << TR_66_PIO_ACCESS_SHIFT) |
+                               (recTicks << TR_66_PIO_RECOVERY_SHIFT);
        } else {
-               /* The old "ata-3" IDE controller */
-               accessTicks = SYSCLK_TICKS(t->active);
-               if (accessTicks < 4)
-                       accessTicks = 4;
-               recTicks = SYSCLK_TICKS(t->cycle) - accessTicks - 4;
-               if (recTicks < 1)
-                       recTicks = 1;
-       
-               *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
+               /* 33Mhz cell */
+               int ebit = 0;
+               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;
+               }
+               *timings = ((*timings) & ~TR_33_PIO_MASK) |
+                               (accessTicks << TR_33_PIO_ACCESS_SHIFT) |
+                               (recTicks << TR_33_PIO_RECOVERY_SHIFT);
+               if (ebit)
+                       *timings |= TR_33_PIO_E;
        }
 
 #ifdef IDE_PMAC_DEBUG
@@ -335,70 +528,134 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-static int
-set_timings_udma(int intf, u32 *timings, byte speed)
+static int __pmac
+set_timings_udma(u32 *timings, byte speed)
 {
-       int cycleTime, accessTime;
-       int rdyToPauseTicks, cycleTicks;
+       unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
 
-       if (pmac_ide[intf].kind != controller_kl_ata4)
-               return 1;
-               
-       cycleTime = udma_timings[speed & 0xf].cycleTime;
-       accessTime = udma_timings[speed & 0xf].accessTime;
+       rdyToPauseTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].rdy2pause);
+       wrDataSetupTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].wrDataSetup);
+       addrTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].addrSetup);
 
-       rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-       cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
-
-       *timings = ((*timings) & 0xe00fffff) |
-                       ((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+       *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;
 }
 
-static int
-set_timings_mdma(int intf, u32 *timings, byte speed)
+static int __pmac
+set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time)
 {
-       int cycleTime, accessTime;
-       int accessTicks, recTicks;
+       int cycleTime, accessTime, recTime;
+       unsigned accessTicks, recTicks;
+       struct mdma_timings_t* tm;
+       int i;
 
-       /* Calculate accesstime and cycle time */
-       cycleTime = mdma_timings[speed & 0xf].cycleTime;
-       accessTime = mdma_timings[speed & 0xf].accessTime;
-       if ((pmac_ide[intf].kind == controller_ohare) && (cycleTime < 150))
+       /* 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:
+                       return -1;
+       }
+       /* Adjust for drive */
+       if (drive_cycle_time && drive_cycle_time > cycleTime)
+               cycleTime = drive_cycle_time;
+       /* 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_kl_ata4:
+               case controller_kl_ata4_80:
+                       tm = mdma_timings_66;
+                       break;
+               case controller_kl_ata3:
+                       tm = mdma_timings_33k;
+                       break;
+               default:
+                       tm = mdma_timings_33;
+                       break;
+       }
+       /* Lookup matching access & recovery times */
+       i = -1;
+       for (;;) {
+               if (tm[i+1].cycleTime < cycleTime)
+                       break;
+               i++;
+       }
+       if (i < 0)
+               return -1;
+       cycleTime = tm[i].cycleTime;
+       accessTime = tm[i].accessTime;
+       recTime = tm[i].recoveryTime;
 
-       /* For ata-4 controller */
-       if (pmac_ide[intf].kind == controller_kl_ata4) {
-               accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-               recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
-               *timings = ((*timings) & 0xffe003ff) |
-                       (accessTicks | (recTicks << 5)) << 10;
+#ifdef IDE_PMAC_DEBUG
+       printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",
+               cycleTime, accessTime, recTime);
+#endif 
+       if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) {
+               /* 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);
+       } else if (intf_type == 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);
        } else {
+               /* 33Mhz cell on others */
                int halfTick = 0;
                int origAccessTime = accessTime;
-               int origCycleTime = cycleTime;
+               int origRecTime = recTime;
                
                accessTicks = SYSCLK_TICKS(accessTime);
-               if (accessTicks < 1)
-                       accessTicks = 1;
+               accessTicks = max(accessTicks, 1U);
+               accessTicks = min(accessTicks, 0x1fU);
                accessTime = accessTicks * IDE_SYSCLK_NS;
-               recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
-               if (recTicks < 1)
-                       recTicks = 1;
-               cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
-
-               /* KeyLargo ata-3 don't support the half-tick stuff */
-               if ((pmac_ide[intf].kind != controller_kl_ata3) &&
-                       (accessTicks > 1) &&
-                       ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
-                       ((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
-                               halfTick    = 1;
-                               accessTicks--;
+               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) & 0x7FF) |
-                       (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
+               *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 "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
+               speed & 0xf,  *timings);
+#endif 
        return 0;
 }
 #endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
@@ -406,11 +663,11 @@ set_timings_mdma(int intf, u32 *timings, byte speed)
 /* You may notice we don't use this function on normal operation,
  * our, normal mdma function is supposed to be more precise
  */
-static int
+static int __pmac
 pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
 {
        int intf                = pmac_ide_find(drive);
-       int unit                = (drive->select.all & 0x10) ? 1:0;
+       int unit                = (drive->select.b.unit & 0x01);
        int ret                 = 0;
        u32 *timings;
 
@@ -423,19 +680,25 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
                case XFER_UDMA_4:
                case XFER_UDMA_3:
+                       if (pmac_ide[intf].kind != controller_kl_ata4_80)
+                               return 1;               
                case XFER_UDMA_2:
                case XFER_UDMA_1:
                case XFER_UDMA_0:
-                       ret = set_timings_udma(intf, timings, speed);
+                       if (pmac_ide[intf].kind != controller_kl_ata4 &&
+                               pmac_ide[intf].kind != controller_kl_ata4_80)
+                               return 1;               
+                       ret = set_timings_udma(timings, speed);
                        break;
                case XFER_MW_DMA_2:
                case XFER_MW_DMA_1:
                case XFER_MW_DMA_0:
+                       ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0);
+                       break;
                case XFER_SW_DMA_2:
                case XFER_SW_DMA_1:
                case XFER_SW_DMA_0:
-                       ret = set_timings_mdma(intf, timings, speed);
-                       break;
+                       return 1;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
                case XFER_PIO_4:
                case XFER_PIO_3:
@@ -460,13 +723,46 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
        return 0;
 }
 
-ide_ioreg_t
+static void __pmac
+sanitize_timings(int i)
+{
+       unsigned value;
+       
+       switch(pmac_ide[i].kind) {
+               case controller_kl_ata4:
+               case controller_kl_ata4_80:
+                       value = 0x0008438c;
+                       break;
+               case controller_kl_ata3:
+                       value = 0x00084526;
+                       break;
+               case controller_heathrow:
+               case controller_ohare:
+               default:
+                       value = 0x00074526;
+                       break;
+       }
+       pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value;
+}
+
+ide_ioreg_t __pmac
 pmac_ide_get_base(int index)
 {
        return pmac_ide[index].regbase;
 }
 
-int
+int __pmac
+pmac_ide_check_base(ide_ioreg_t base)
+{
+       int ix;
+       
+       for (ix = 0; ix < MAX_HWIFS; ++ix)
+               if (base == pmac_ide[ix].regbase)
+                       return ix;
+       return -1;
+}
+
+int __pmac
 pmac_ide_get_irq(ide_ioreg_t base)
 {
        int ix;
@@ -477,7 +773,7 @@ pmac_ide_get_irq(ide_ioreg_t base)
        return 0;
 }
 
-static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+static int ide_majors[]  __pmacdata = { 3, 22, 33, 34, 56, 57 };
 
 kdev_t __init
 pmac_find_ide_boot(char *bootdevice, int n)
@@ -494,11 +790,11 @@ pmac_find_ide_boot(char *bootdevice, int n)
                name = pmac_ide[i].node->full_name;
                if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
                        /* XXX should cope with the 2nd drive as well... */
-                       return MKDEV(ide_majors[i], 0);
+                       return mk_kdev(ide_majors[i], 0);
                }
        }
 
-       return 0;
+       return NODEV;
 }
 
 void __init
@@ -541,9 +837,12 @@ pmac_ide_probe(void)
 
        for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
                struct device_node *tp;
+               struct pmac_ide_hwif *pmif;
                int *bidp;
                int in_bay = 0;
-
+               u8 pbus, pid;
+               struct pci_dev *pdev = NULL;
+               
                /*
                 * If this node is not under a mac-io or dbdma node,
                 * leave it to the generic PCI driver.
@@ -561,6 +860,15 @@ pmac_ide_probe(void)
                        continue;
                }
 
+               /* We need to find the pci_dev of the mac-io holding the
+                * IDE interface
+                */
+               if (pci_device_from_OF_node(tp, &pbus, &pid) == 0)
+                       pdev = pci_find_slot(pbus, pid);
+               if (pdev == NULL)
+                       printk(KERN_WARNING "ide: no PCI host for device %s, DMA disabled\n",
+                              np->full_name);
+               
                /*
                 * If this slot is taken (e.g. by ide-pci.c) try the next one.
                 */
@@ -569,8 +877,23 @@ pmac_ide_probe(void)
                        ++i;
                if (i >= MAX_HWIFS)
                        break;
+               pmif = &pmac_ide[i];
+
+               /*
+                * Some older OFs have bogus sizes, causing request_OF_resource
+                * to fail. We fix them up here
+                */
+               if (np->addrs[0].size > 0x1000)
+                       np->addrs[0].size = 0x1000;
+               if (np->n_addrs > 1 && np->addrs[1].size > 0x100)
+                       np->addrs[1].size = 0x100;
+
+               if (request_OF_resource(np, 0, "  (mac-io IDE IO)") == NULL) {
+                       printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name);
+                       continue;
+               }
 
-               base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE;
+               base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE;
 
                /* XXX This is bogus. Should be fixed in the registry by checking
                   the kind of host interrupt controller, a bit like gatwick
@@ -583,21 +906,30 @@ pmac_ide_probe(void)
                } else {
                        irq = np->intrs[0].line;
                }
-               pmac_ide[i].regbase = base;
-               pmac_ide[i].irq = irq;
-               pmac_ide[i].node = np;
+               pmif->regbase = base;
+               pmif->irq = irq;
+               pmif->node = np;
                if (device_is_compatible(np, "keylargo-ata")) {
                        if (strcmp(np->name, "ata-4") == 0)
-                               pmac_ide[i].kind = controller_kl_ata4;
+                               pmif->kind = controller_kl_ata4;
                        else
-                               pmac_ide[i].kind = controller_kl_ata3;
+                               pmif->kind = controller_kl_ata3;
                } else if (device_is_compatible(np, "heathrow-ata"))
-                       pmac_ide[i].kind = controller_heathrow;
+                       pmif->kind = controller_heathrow;
                else
-                       pmac_ide[i].kind = controller_ohare;
+                       pmif->kind = controller_ohare;
 
                bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
-               pmac_ide[i].aapl_bus_id =  bidp ? *bidp : 0;
+               pmif->aapl_bus_id =  bidp ? *bidp : 0;
+
+               if (pmif->kind == controller_kl_ata4) {
+                       char* cable = get_property(np, "cable-type", NULL);
+                       if (cable && !strncmp(cable, "80-", 3))
+                               pmif->kind = controller_kl_ata4_80;
+               }
+
+               /* Make sure we have sane timings */
+               sanitize_timings(i);
 
                if (np->parent && np->parent->name
                    && strcasecmp(np->parent->name, "media-bay") == 0) {
@@ -605,39 +937,22 @@ pmac_ide_probe(void)
                        media_bay_set_ide_infos(np->parent,base,irq,i);
 #endif /* CONFIG_PMAC_PBOOK */
                        in_bay = 1;
-               } else if (pmac_ide[i].kind == controller_ohare) {
+                       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
                         */
-                        feature_set(np, FEATURE_IDE0_enable);
+                       ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
                } else {
                        /* This is necessary to enable IDE when net-booting */
                        printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",
-                               pmac_ide[i].aapl_bus_id);
-                       switch(pmac_ide[i].aapl_bus_id) {
-                           case 0:
-                               feature_set(np, FEATURE_IDE0_reset);
-                               mdelay(10);
-                               feature_set(np, FEATURE_IDE0_enable);
-                               mdelay(10);
-                               feature_clear(np, FEATURE_IDE0_reset);
-                               break;
-                           case 1:
-                               feature_set(np, FEATURE_IDE1_reset);
-                               mdelay(10);
-                               feature_set(np, FEATURE_IDE1_enable);
-                               mdelay(10);
-                               feature_clear(np, FEATURE_IDE1_reset);
-                               break;
-                           case 2:
-                               /* This one exists only for KL, I don't know
-                                  about any enable bit */
-                               feature_set(np, FEATURE_IDE2_reset);
-                               mdelay(10);
-                               feature_clear(np, FEATURE_IDE2_reset);
-                               break;
-                       }
+                               pmif->aapl_bus_id);
+                       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);
+                       mdelay(10);
+                       ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);
                        big_delay = 1;
                }
 
@@ -646,13 +961,15 @@ pmac_ide_probe(void)
                memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
                hwif->chipset = ide_pmac;
                hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay;
+               hwif->udma_four = (pmif->kind == controller_kl_ata4_80);
+               hwif->pci_dev = pdev;
 #ifdef CONFIG_PMAC_PBOOK
                if (in_bay && check_media_bay_by_base(base, MB_CD) == 0)
                        hwif->noprobe = 0;
 #endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-               if (np->n_addrs >= 2) {
+               if (pdev && np->n_addrs >= 2) {
                        /* has a DBDMA controller channel */
                        pmac_ide_setup_dma(np, i);
                }
@@ -674,7 +991,15 @@ pmac_ide_probe(void)
 static void __init 
 pmac_ide_setup_dma(struct device_node *np, int ix)
 {
-       pmac_ide[ix].dma_regs =
+       struct pmac_ide_hwif *pmif = &pmac_ide[ix];
+
+       if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) {
+               printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n",
+                       np->name);
+               return;
+       }
+
+       pmif->dma_regs =
                (volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);
 
        /*
@@ -682,14 +1007,24 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
         * The +2 is +1 for the stop command and +1 to allow for
         * aligning the start address to a multiple of 16 bytes.
         */
-       pmac_ide[ix].dma_table = (struct dbdma_cmd*)
-              kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);
-       if (pmac_ide[ix].dma_table == 0) {
+       pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
+               ide_hwifs[ix].pci_dev,
+               (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
+               &pmif->dma_table_dma);
+       if (pmif->dma_table_cpu == NULL) {
                printk(KERN_ERR "%s: unable to allocate DMA command list\n",
                       ide_hwifs[ix].name);
                return;
        }
 
+       pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS,
+                                GFP_KERNEL);
+       if (pmif->sg_table == NULL) {
+               pci_free_consistent(    ide_hwifs[ix].pci_dev,
+                                       (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
+                                       pmif->dma_table_cpu, pmif->dma_table_dma);
+               return;
+       }
        ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
        if (!noautodma)
@@ -697,6 +1032,62 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
 #endif
 }
 
+static int
+pmac_ide_build_sglist (int ix, struct request *rq)
+{
+       struct ata_channel *hwif = &ide_hwifs[ix];
+       struct pmac_ide_hwif *pmif = &pmac_ide[ix];
+       request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
+       struct scatterlist *sg = pmif->sg_table;
+       int nents;
+
+       nents = blk_rq_map_sg(q, rq, pmif->sg_table);
+
+       if (rq->q && nents > rq->nr_phys_segments)
+               printk("ide-pmac: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
+
+       if (rq_data_dir(rq) == READ)
+               pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+       else
+               pmif->sg_dma_direction = PCI_DMA_TODEVICE;
+
+       return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
+}
+
+static int
+pmac_ide_raw_build_sglist (int ix, struct request *rq)
+{
+       struct ata_channel *hwif = &ide_hwifs[ix];
+       struct pmac_ide_hwif *pmif = &pmac_ide[ix];
+       struct scatterlist *sg = pmif->sg_table;
+       int nents = 0;
+       ide_task_t *args = rq->special;
+       unsigned char *virt_addr = rq->buffer;
+       int sector_count = rq->nr_sectors;
+
+       if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
+               pmif->sg_dma_direction = PCI_DMA_TODEVICE;
+       else
+               pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+
+       if (sector_count > 128) {
+               memset(&sg[nents], 0, sizeof(*sg));
+               sg[nents].page = virt_to_page(virt_addr);
+               sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
+               sg[nents].length = 128  * SECTOR_SIZE;
+               nents++;
+               virt_addr = virt_addr + (128 * SECTOR_SIZE);
+               sector_count -= 128;
+       }
+       memset(&sg[nents], 0, sizeof(*sg));
+       sg[nents].page = virt_to_page(virt_addr);
+       sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
+       sg[nents].length =  sector_count  * SECTOR_SIZE;
+       nents++;
+
+       return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
+}
+
 /*
  * pmac_ide_build_dmatable builds the DBDMA command list
  * for a transfer and sets the DBDMA channel to point to it.
@@ -704,47 +1095,40 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
 static int
 pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
 {
-       struct dbdma_cmd *table, *tstart;
-       int count = 0;
+       struct dbdma_cmd *table;
+       int i, count = 0;
        struct request *rq = HWGROUP(drive)->rq;
-       struct buffer_head *bh = rq->bh;
-       unsigned int size, addr;
        volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;
+       struct scatterlist *sg;
+
+       /* DMA table is already aligned */
+       table = (struct dbdma_cmd *) pmac_ide[ix].dma_table_cpu;
 
-       table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table);
+       /* Make sure DMA controller is stopped (necessary ?) */
        out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
        while (in_le32(&dma->status) & RUN)
                udelay(1);
 
-       do {
-               /*
-                * Determine addr and size of next buffer area.  We assume that
-                * individual virtual buffers are always composed linearly in
-                * physical memory.  For example, we assume that any 8kB buffer
-                * is always composed of two adjacent physical 4kB pages rather
-                * than two possibly non-adjacent physical 4kB pages.
-                */
-               if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
-                       addr = virt_to_bus(rq->buffer);
-                       size = rq->nr_sectors << 9;
-               } else {
-                       /* group sequential buffers into one large buffer */
-                       addr = virt_to_bus(bh->b_data);
-                       size = bh->b_size;
-                       while ((bh = bh->b_reqnext) != NULL) {
-                               if ((addr + size) != virt_to_bus(bh->b_data))
-                                       break;
-                               size += bh->b_size;
-                       }
-               }
+       /* Build sglist */
+       if (rq->flags & REQ_DRIVE_TASKFILE) {
+               pmac_ide[ix].sg_nents = i = pmac_ide_raw_build_sglist(ix, rq);
+       } else {
+               pmac_ide[ix].sg_nents = i = pmac_ide_build_sglist(ix, rq);
+       }
+       if (!i)
+               return 0;
 
-               /*
-                * Fill in the next DBDMA command block.
-                * Note that one DBDMA command can transfer
-                * at most 65535 bytes.
-                */
-               while (size) {
-                       unsigned int tc = (size < 0xfe00)? size: 0xfe00;
+       /* Build DBDMA commands list */
+       sg = pmac_ide[ix].sg_table;
+       while (i) {
+               u32 cur_addr;
+               u32 cur_len;
+
+               cur_addr = sg_dma_address(sg);
+               cur_len = sg_dma_len(sg);
+
+               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",
@@ -753,15 +1137,17 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
                        }
                        st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);
                        st_le16(&table->req_count, tc);
-                       st_le32(&table->phy_addr, addr);
+                       st_le32(&table->phy_addr, cur_addr);
                        table->cmd_dep = 0;
                        table->xfer_status = 0;
                        table->res_count = 0;
-                       addr += tc;
-                       size -= tc;
+                       cur_addr += tc;
+                       cur_len -= tc;
                        ++table;
                }
-       } while (bh != NULL);
+               sg++;
+               i--;
+       }
 
        /* convert the last command to an input/output last command */
        if (count)
@@ -773,10 +1159,24 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
        memset(table, 0, sizeof(struct dbdma_cmd));
        out_le16(&table->command, DBDMA_STOP);
 
-       out_le32(&dma->cmdptr, virt_to_bus(tstart));
+       out_le32(&dma->cmdptr, pmac_ide[ix].dma_table_dma);
        return 1;
 }
 
+/* Teardown mappings after DMA has completed.  */
+static void
+pmac_ide_destroy_dmatable (ide_drive_t *drive, int ix)
+{
+       struct pci_dev *dev = HWIF(drive)->pci_dev;
+       struct scatterlist *sg = pmac_ide[ix].sg_table;
+       int nents = pmac_ide[ix].sg_nents;
+
+       if (nents) {
+               pci_unmap_sg(dev, sg, nents, pmac_ide[ix].sg_dma_direction);
+               pmac_ide[ix].sg_nents = 0;
+       }
+}
+
 
 static __inline__ unsigned char
 dma_bits_to_command(unsigned char bits)
@@ -791,12 +1191,14 @@ dma_bits_to_command(unsigned char bits)
 }
 
 static __inline__ unsigned char
-udma_bits_to_command(unsigned char bits)
+udma_bits_to_command(unsigned char bits, int high_speed)
 {
-       if(bits & 0x10)
-               return XFER_UDMA_4;
-       if(bits & 0x08)
-               return XFER_UDMA_3;
+       if (high_speed) {
+               if(bits & 0x10)
+                       return XFER_UDMA_4;
+               if(bits & 0x08)
+                       return XFER_UDMA_3;
+       }
        if(bits & 0x04)
                return XFER_UDMA_2;
        if(bits & 0x02)
@@ -807,14 +1209,13 @@ udma_bits_to_command(unsigned char bits)
 }
 
 /* Calculate MultiWord DMA timings */
-static int
+static int __pmac
 pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
 {
        byte bits = drive->id->dma_mword & 0x07;
        byte feature = dma_bits_to_command(bits);
        u32 *timings;
-       int cycleTime, accessTime;
-       int accessTicks, recTicks;
+       int drive_cycle_time;
        struct hd_driveid *id = drive->id;
        int ret;
 
@@ -830,66 +1231,30 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
                drive->init_speed = feature;
        
        /* which drive is it ? */
-       if (drive->select.all & 0x10)
+       if (drive->select.b.unit & 0x01)
                timings = &pmac_ide[idx].timings[1];
        else
                timings = &pmac_ide[idx].timings[0];
 
-       /* Calculate accesstime and cycle time */
-       cycleTime = mdma_timings[feature & 0xf].cycleTime;
-       accessTime = mdma_timings[feature & 0xf].accessTime;
+       /* Check if drive provide explicit cycle time */
        if ((id->field_valid & 2) && (id->eide_dma_time))
-               cycleTime = id->eide_dma_time;
-       if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))
-               cycleTime = 150;
+               drive_cycle_time = id->eide_dma_time;
+       else
+               drive_cycle_time = 0;
+
+       /* Calculate controller timings */
+       set_timings_mdma(pmac_ide[idx].kind, timings, feature, drive_cycle_time);
 
-       /* For ata-4 controller */
-       if (pmac_ide[idx].kind == controller_kl_ata4) {
-               accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-               recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
-               *timings = ((*timings) & 0xffe003ff) |
-                       (accessTicks | (recTicks << 5)) << 10;
-       } else {
-               int halfTick = 0;
-               int origAccessTime = accessTime;
-               int origCycleTime = cycleTime;
-               
-               accessTicks = SYSCLK_TICKS(accessTime);
-               if (accessTicks < 1)
-                       accessTicks = 1;
-               accessTime = accessTicks * IDE_SYSCLK_NS;
-               recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
-               if (recTicks < 1)
-                       recTicks = 1;
-               cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
-
-               /* KeyLargo ata-3 don't support the half-tick stuff */
-               if ((pmac_ide[idx].kind != controller_kl_ata3) &&
-                       (accessTicks > 1) &&
-                       ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
-                       ((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
-                               halfTick    = 1;
-                               accessTicks--;
-               }
-               *timings = ((*timings) & 0x7FF) |
-                       (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
-       }
-#ifdef IDE_PMAC_DEBUG
-       printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
-               feature & 0xf, *timings);
-#endif
        drive->current_speed = feature; 
        return 1;
 }
 
 /* Calculate Ultra DMA timings */
-static int
-pmac_ide_udma_enable(ide_drive_t *drive, int idx)
+static int __pmac
+pmac_ide_udma_enable(ide_drive_t *drive, int idx, int high_speed)
 {
        byte bits = drive->id->dma_ultra & 0x1f;
-       byte feature = udma_bits_to_command(bits);
-       int cycleTime, accessTime;
-       int rdyToPauseTicks, cycleTicks;
+       byte feature = udma_bits_to_command(bits, high_speed);
        u32 *timings;
        int ret;
 
@@ -905,25 +1270,18 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx)
                drive->init_speed = feature;
 
        /* which drive is it ? */
-       if (drive->select.all & 0x10)
+       if (drive->select.b.unit & 0x01)
                timings = &pmac_ide[idx].timings[1];
        else
                timings = &pmac_ide[idx].timings[0];
 
-       cycleTime = udma_timings[feature & 0xf].cycleTime;
-       accessTime = udma_timings[feature & 0xf].accessTime;
-
-       rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-       cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
-
-       *timings = ((*timings) & 0xe00fffff) |
-                       ((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+       set_timings_udma(timings, feature);
 
        drive->current_speed = feature; 
        return 1;
 }
 
-static int
+static int __pmac
 pmac_ide_check_dma(ide_drive_t *drive)
 {
        int ata4, udma, idx;
@@ -944,21 +1302,20 @@ pmac_ide_check_dma(ide_drive_t *drive)
                enable = 0;
 
        udma = 0;
-       ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
+       ata4 = (pmac_ide[idx].kind == controller_kl_ata4 ||
+               pmac_ide[idx].kind == controller_kl_ata4_80);
 
        if(enable) {
                if (ata4 && (drive->type == ATA_DISK) &&
-                   (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
+                   (id->field_valid & 0x0004) && (id->dma_ultra & 0x1f)) {
                        /* UltraDMA modes. */
-                       drive->using_dma = pmac_ide_udma_enable(drive, idx);
+                       drive->using_dma = pmac_ide_udma_enable(drive, idx,
+                               pmac_ide[idx].kind == controller_kl_ata4_80);
                }
                if (!drive->using_dma && (id->dma_mword & 0x0007)) {
                        /* Normal MultiWord DMA modes. */
                        drive->using_dma = pmac_ide_mdma_enable(drive, idx);
                }
-               /* Without this, strange things will happen on Keylargo-based
-                * machines
-                */
                OUT_BYTE(0, IDE_CONTROL_REG);
                /* Apply settings to controller */
                pmac_ide_selectproc(drive);
@@ -966,11 +1323,26 @@ pmac_ide_check_dma(ide_drive_t *drive)
        return 0;
 }
 
+static void ide_toggle_bounce(ide_drive_t *drive, int on)
+{
+       dma64_addr_t addr = BLK_BOUNCE_HIGH;
+
+       if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) {
+               if (!PCI_DMA_BUS_IS_PHYS)
+                       addr = BLK_BOUNCE_ANY;
+               else
+                       addr = HWIF(drive)->pci_dev->dma_mask;
+       }
+
+       blk_queue_bounce_limit(&drive->queue, addr);
+}
+
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-       int ix, dstat, i;
+       int ix, dstat, reading, ata4;
        volatile struct dbdma_regs *dma;
-
+       byte unit = (drive->select.b.unit & 0x01);
+       
        /* Can we stuff a pointer to our intf structure in config_data
         * or select_data in hwif ?
         */
@@ -978,59 +1350,106 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
        if (ix < 0)
                return 0;               
        dma = pmac_ide[ix].dma_regs;
-
+       ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
+               pmac_ide[ix].kind == controller_kl_ata4_80);
+       
        switch (func) {
        case ide_dma_off:
                printk(KERN_INFO "%s: DMA disabled\n", drive->name);
        case ide_dma_off_quietly:
                drive->using_dma = 0;
+               ide_toggle_bounce(drive, 0);
                break;
        case ide_dma_on:
        case ide_dma_check:
+               /* Change this to better match ide-dma.c */
                pmac_ide_check_dma(drive);
+               ide_toggle_bounce(drive, drive->using_dma);
                break;
        case ide_dma_read:
        case ide_dma_write:
-               if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
+               /* this almost certainly isn't needed since we don't
+                  appear to have a rwproc */
+               if (HWIF(drive)->rwproc)
+                       HWIF(drive)->rwproc(drive, func);
+               reading = (func == ide_dma_read);
+               if (!pmac_ide_build_dmatable(drive, ix, !reading))
                        return 1;
+               /* Apple adds 60ns to wrDataSetup on reads */
+               if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) {
+                       out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
+                               pmac_ide[ix].timings[unit] + 
+                               ((func == ide_dma_read) ? 0x00800000UL : 0));
+                       (void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
+               }
                drive->waiting_for_dma = 1;
                if (drive->type != ATA_DISK)
                        return 0;
                BUG_ON(HWGROUP(drive)->handler);
                ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
-               OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA,
-                        IDE_COMMAND_REG);
+               if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
+                   (drive->addressing == 1)) {
+                       ide_task_t *args = HWGROUP(drive)->rq->special;
+                       OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
+               } else if (drive->addressing) {
+                       OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
+               } else {
+                       OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
+               }
+               /* fall through */
        case ide_dma_begin:
                out_le32(&dma->control, (RUN << 16) | RUN);
+               /* Make sure it gets to the controller right now */
+               (void)in_le32(&dma->control);
                break;
-       case ide_dma_end:
+       case ide_dma_end: /* returns 1 on error, 0 otherwise */
                drive->waiting_for_dma = 0;
                dstat = in_le32(&dma->status);
                out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
+               pmac_ide_destroy_dmatable(drive, ix);
                /* verify good dma status */
                return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
-       case ide_dma_test_irq:
-               if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN)
-                       return 1;
-               /* That's a bit ugly and dangerous, but works in our case
-                * to workaround a problem with the channel status staying
-                * active if the drive returns an error
+       case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+               /* We have to things to deal with here:
+                * 
+                * - The dbdma won't stop if the command was started
+                * but completed with an error without transfering 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.
+                * 
+                * The trick here is to increment drive->waiting_for_dma,
+                * and return as if no interrupt occured. If the counter
+                * reach a certain timeout value, we then return 1. If
+                * we really got the interrupt, it will happen right away
+                * again.
+                * Apple's solution here may be more elegant. They issue
+                * a DMA channel interrupt (a separate irq line) via a DBDMA
+                * NOP command just before the STOP, and wait for both the
+                * disk and DBDMA interrupts to have completed.
                 */
-               if (IDE_CONTROL_REG) {
-                       byte stat;
-                       stat = GET_ALTSTAT();
-                       if (stat & ERR_STAT)
-                               return 1;
-               }
-               /* In some edge cases, some datas may still be in the dbdma
-                * engine fifo, we wait a bit for dbdma to complete
+                
+               /* If ACTIVE is cleared, the STOP command have passed and
+                * transfer is complete.
                 */
-               while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) {
-                       if (++i > 100)
-                               return 0;
-                       udelay(1);
+               if (!(in_le32(&dma->status) & ACTIVE))
+                       return 1;
+               if (!drive->waiting_for_dma)
+                       printk(KERN_WARNING "ide%d, ide_dma_test_irq \
+                               called while not waiting\n", ix);
+
+               /* 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 "ide%d, timeout waiting \
+                               for dbdma command stop\n", ix);
+                       return 1;
                }
-               return 1;
+               udelay(1);
+               return 0;
 
                /* Let's implement tose just in case someone wants them */
        case ide_dma_bad_drive:
@@ -1051,7 +1470,6 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
-#ifdef CONFIG_PMAC_PBOOK
 static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
 {
        int j;
@@ -1062,7 +1480,9 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
        switch (drive->type) {
        case ATA_DISK:
                /* Spin down the drive */
-               outb(0xa0, base+0x60);
+               outb(drive->select.all, base+0x60);
+               (void)inb(base+0x60);
+               udelay(100);
                outb(0x0, base+0x30);
                outb(0x0, base+0x20);
                outb(0x0, base+0x40);
@@ -1086,19 +1506,21 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
        }
 }
 
-static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
- {
+#ifdef CONFIG_PMAC_PBOOK
+static void __pmac
+idepmac_wake_device(ide_drive_t *drive, int used_dma)
+{
        /* We force the IDE subdriver to check for a media change
         * This must be done first or we may lost the condition
         *
         * Problem: This can schedule. I moved the block device
         * wakeup almost late by priority because of that.
         */
-       if (DRIVER(drive) && DRIVER(drive)->media_change)
-               DRIVER(drive)->media_change(drive);
+       if (drive->driver != NULL && ata_ops(drive)->check_media_change)
+               ata_ops(drive)->check_media_change(drive);
 
        /* We kick the VFS too (see fix in ide.c revalidate) */
-       check_disk_change(MKDEV(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
+       check_disk_change(mk_kdev(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
        
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        /* We re-enable DMA on the drive if it was active. */
@@ -1108,15 +1530,16 @@ static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
         */
        if (used_dma && !ide_spin_wait_hwgroup(drive)) {
                /* Lock HW group */
-               HWGROUP(drive)->busy = 1;
+               set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
                pmac_ide_check_dma(drive);
-               HWGROUP(drive)->busy = 0;
+               clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
                spin_unlock_irq(&ide_lock);
        }
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 }
 
-static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
+static void __pmac
+idepmac_sleep_interface(int i, unsigned base, int mediabay)
 {
        struct device_node* np = pmac_ide[i].node;
 
@@ -1128,73 +1551,81 @@ static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
        if (mediabay)
                return;
        
-       /* Disable and reset the bus */
-       feature_set(np, FEATURE_IDE0_reset);
-       feature_clear(np, FEATURE_IDE0_enable);
-       switch(pmac_ide[i].aapl_bus_id) {
-           case 0:
-               feature_set(np, FEATURE_IDE0_reset);
-               feature_clear(np, FEATURE_IDE0_enable);
-               break;
-           case 1:
-               feature_set(np, FEATURE_IDE1_reset);
-               feature_clear(np, FEATURE_IDE1_enable);
-               break;
-           case 2:
-               feature_set(np, FEATURE_IDE2_reset);
-               break;
-       }
+       /* Disable the bus */
+       ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 0);
 }
 
-static void idepmac_wake_interface(int i, unsigned long base, int mediabay)
+static void __pmac
+idepmac_wake_interface(int i, unsigned long base, int mediabay)
 {
        struct device_node* np = pmac_ide[i].node;
 
        if (!mediabay) {
                /* Revive IDE disk and controller */
-               switch(pmac_ide[i].aapl_bus_id) {
-                   case 0:
-                       feature_set(np, FEATURE_IDE0_reset);
-                       feature_set(np, FEATURE_IOBUS_enable);
-                       mdelay(10);
-                       feature_set(np, FEATURE_IDE0_enable);
-                       mdelay(10);
-                       feature_clear(np, FEATURE_IDE0_reset);
-                       break;
-                   case 1:
-                       feature_set(np, FEATURE_IDE1_reset);
-                       feature_set(np, FEATURE_IOBUS_enable);
-                       mdelay(10);
-                       feature_set(np, FEATURE_IDE1_enable);
-                       mdelay(10);
-                       feature_clear(np, FEATURE_IDE1_reset);
-                       break;
-                   case 2:
-                       /* This one exists only for KL, I don't know
-                          about any enable bit */
-                       feature_set(np, FEATURE_IDE2_reset);
-                       mdelay(10);
-                       feature_clear(np, FEATURE_IDE2_reset);
-                       break;
-               }
+               ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 1);
+               ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 1);
+               mdelay(10);
+               ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 0);
        }
+}
+
+static void
+idepmac_sleep_drive(ide_drive_t *drive, int idx, unsigned long base)
+{
+       /* Wait for HW group to complete operations */
+       if (ide_spin_wait_hwgroup(drive))
+               // What can we do here ? Wake drive we had already
+               // put to sleep and return an error ?
+               return;
+       else {
+               /* Lock HW group */
+               set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
+               /* Stop the device */
+               idepmac_sleep_device(drive, idx, base);
+               spin_unlock_irq(&ide_lock);
+       }
+}
+
+static void
+idepmac_wake_drive(ide_drive_t *drive, unsigned long base)
+{
+       int j;
        
        /* Reset timings */
-       pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
+       pmac_ide_selectproc(drive);
        mdelay(10);
+       
+       /* Wait up to 20 seconds for the drive to be ready */
+       for (j = 0; j < 200; j++) {
+               int status;
+               mdelay(100);
+               outb(drive->select.all, base + 0x60);
+               if (inb(base + 0x60) != drive->select.all)
+                       continue;
+               status = inb(base + 0x70);
+               if (!(status & BUSY_STAT))
+                       break;
+       }
+
+       /* We resume processing on the HW group */
+       spin_lock_irq(&ide_lock);
+       clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
+       if (!list_empty(&drive->queue.queue_head))
+               do_ide_request(&drive->queue);
+       spin_unlock_irq(&ide_lock);
 }
 
 /* Note: We support only master drives for now. This will have to be
  * improved if we want to handle sleep on the iMacDV where the CD-ROM
  * is a slave
  */
-static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
+static int __pmac
+idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
        int i, ret;
        unsigned long base;
-       unsigned long flags;
        int big_delay;
-
        switch (when) {
        case PBOOK_SLEEP_REQUEST:
                break;
@@ -1203,34 +1634,19 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
        case PBOOK_SLEEP_NOW:
                for (i = 0; i < pmac_ide_count; ++i) {
                        struct ata_channel *hwif;
-                       ide_drive_t *drive;
-                       int unlock = 0;
+                       int dn;
 
                        if ((base = pmac_ide[i].regbase) == 0)
-                               continue;       
+                               continue;
 
                        hwif = &ide_hwifs[i];
-                       drive = &hwif->drives[0];
-                       
-                       if (drive->present) {
-                               /* Wait for HW group to complete operations */
-                               if (ide_spin_wait_hwgroup(drive)) {
-                                       // What can we do here ? Wake drive we had already
-                                       // put to sleep and return an error ?
-                               } else {
-                                       unlock = 1;
-                                       /* Lock HW group */
-                                       HWGROUP(drive)->busy = 1;
-
-                                       /* Stop the device */
-                                       idepmac_sleep_device(drive, i, base);
-                               
-                               }
+                       for (dn=0; dn<MAX_DRIVES; dn++) {
+                               if (!hwif->drives[dn].present)
+                                       continue;
+                               idepmac_sleep_drive(&hwif->drives[dn], i, base);
                        }
                        /* Disable irq during sleep */
                        disable_irq(pmac_ide[i].irq);
-                       if (unlock)
-                               spin_unlock_irq(&ide_lock);
                        
                        /* Check if this is a media bay with an IDE device or not
                         * a media bay.
@@ -1247,6 +1663,9 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
                        if ((base = pmac_ide[i].regbase) == 0)
                                continue;
                                
+                       /* Make sure we have sane timings */            
+                       sanitize_timings(i);
+
                        /* Check if this is a media bay with an IDE device or not
                         * a media bay
                         */
@@ -1263,43 +1682,29 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
        
                for (i = 0; i < pmac_ide_count; ++i) {
                        struct ata_channel *hwif;
-                       ide_drive_t *drive;
-                       int j, used_dma;
+                       int used_dma, dn;
+                       int irq_on = 0;
                        
                        if ((base = pmac_ide[i].regbase) == 0)
                                continue;
                                
                        hwif = &ide_hwifs[i];
-                       drive = &hwif->drives[0];
-
-                       /* Wait for the drive to come up and set it's DMA */
-                       if (drive->present) {
-                               /* Wait up to 20 seconds */
-                               for (j = 0; j < 200; j++) {
-                                       int status;
-                                       mdelay(100);
-                                       status = inb(base + 0x70);
-                                       if (!(status & BUSY_STAT))
-                                               break;
+                       for (dn=0; dn<MAX_DRIVES; dn++) {
+                               ide_drive_t *drive = &hwif->drives[dn];
+                               if (!drive->present)
+                                       continue;
+                               /* We don't have re-configured DMA yet */
+                               used_dma = drive->using_dma;
+                               drive->using_dma = 0;
+                               idepmac_wake_drive(drive, base);
+                               if (!irq_on) {
+                                       enable_irq(pmac_ide[i].irq);
+                                       irq_on = 1;
                                }
-                       }
-                       
-                       /* We don't have re-configured DMA yet */
-                       used_dma = drive->using_dma;
-                       drive->using_dma = 0;
-
-                       /* We resume processing on the HW group */
-                       spin_lock_irqsave(&ide_lock, flags);
-                       enable_irq(pmac_ide[i].irq);
-                       if (drive->present)
-                               HWGROUP(drive)->busy = 0;
-                       spin_unlock_irqrestore(&ide_lock, flags);
-                       
-                       /* Wake the device
-                        * We could handle the slave here
-                        */
-                       if (drive->present)
                                idepmac_wake_device(drive, used_dma);
+                       }
+                       if (!irq_on)
+                               enable_irq(pmac_ide[i].irq);
                }
                break;
        }
index 818689eab6a6d6788a7635bc9999f5995e48678a..0bfe01578804b9c9e0ddb67fa91297fdb6f310bf 100644 (file)
@@ -16,6 +16,7 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/types.h>
 #include <linux/ide.h>
 #include <linux/init.h>
 
index a7857ced574b262bee860241d4fb593b7ac349d8..8f7a63f09bcaa638d3ad38678db4c114fc1291fc 100644 (file)
@@ -140,7 +140,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
                                /* kludge for Apple PowerBook internal zip */
                                if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
                                        printk ("FLOPPY");
-                                       type = ide_floppy;
+                                       type = ATA_FLOPPY;
                                        break;
                                }
 #endif
@@ -666,13 +666,12 @@ static int init_irq(struct ata_channel *hwif)
                                hwif->sharing_irq = h->sharing_irq = 1;
                                if (hwif->chipset != ide_pci || h->chipset != ide_pci)
                                        save_match(hwif, h, &match);
-                       }
-                       if (hwif->serialized) {
-                               if (hwif->mate && hwif->mate->irq == h->irq)
-                                       save_match(hwif, h, &match);
-                       }
-                       if (h->serialized) {
-                               if (h->mate && hwif->irq == h->mate->irq)
+
+                               /* FIXME: This is still confusing. What would
+                                * happen if we match-ed two times?
+                                */
+
+                               if (hwif->serialized || h->serialized)
                                        save_match(hwif, h, &match);
                        }
                }
@@ -823,12 +822,11 @@ static void init_gendisk(struct ata_channel *hwif)
 
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                char name[80];
+
                ide_add_generic_settings(hwif->drives + unit);
                hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit);
                sprintf (name, "host%d/bus%d/target%d/lun%d",
-                       (hwif->unit && hwif->mate) ?
-                       hwif->mate->index : hwif->index,
-                       hwif->unit, unit, hwif->drives[unit].lun);
+                       hwif->index, hwif->unit, unit, hwif->drives[unit].lun);
                if (hwif->drives[unit].present)
                        hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
        }
index a80053ba45f50f9010c9b4cf38a7de938c69f7db..018f20face75a99b2c35e6d735f59cb51ffba9f3 100644 (file)
@@ -164,19 +164,6 @@ static int proc_ide_read_imodel
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
-static int proc_ide_read_mate
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       struct ata_channel *hwif = data;
-       int             len;
-
-       if (hwif && hwif->mate && hwif->mate->present)
-               len = sprintf(page, "%s\n", hwif->mate->name);
-       else
-               len = sprintf(page, "(none)\n");
-       PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
 static int proc_ide_read_channel
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -493,7 +480,6 @@ void destroy_proc_ide_drives(struct ata_channel *hwif)
 
 static ide_proc_entry_t hwif_entries[] = {
        { "channel",    S_IFREG|S_IRUGO,        proc_ide_read_channel,  NULL },
-       { "mate",       S_IFREG|S_IRUGO,        proc_ide_read_mate,     NULL },
        { "model",      S_IFREG|S_IRUGO,        proc_ide_read_imodel,   NULL },
        { NULL, 0, NULL, NULL }
 };
index 75f0f19c21f08e2dee90b2c91d578d433aaf69df..26bdbb5687602c07dda5e1b7862d5126a5cd2d50 100644 (file)
@@ -2177,7 +2177,7 @@ int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
                }
                for (h = 0; h < MAX_HWIFS; ++h) {
                        hwif = &ide_hwifs[h];
-                       if ((!hwif->present && !hwif->mate && !initializing) ||
+                       if ((!hwif->present && (hwif->unit == ATA_PRIMARY) && !initializing) ||
                            (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
                                goto found;
                }
@@ -3052,9 +3052,13 @@ int __init ide_setup (char *s)
                                goto done;
                        case -2: /* "serialize" */
                        do_serialize:
-                               hwif->mate = &ide_hwifs[hw^1];
-                               hwif->mate->mate = hwif;
-                               hwif->serialized = hwif->mate->serialized = 1;
+                               {
+                                       struct ata_channel *mate;
+
+                                       mate = &ide_hwifs[hw ^ 1];
+                                       hwif->serialized = 1;
+                                       mate->serialized = 1;
+                               }
                                goto done;
 
                        case -1: /* "noprobe" */
index 787cc4bf0bfbeb377af24ee5d9691fcdc9292c02..cf4bf89898f7faba78e48584b4f4d5edc931dc43 100644 (file)
@@ -141,11 +141,21 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
        using_inta = progif & (1 << (hwif->unit << 1));
        if (!using_inta)
                using_inta = ctrl & (1 << (4 + hwif->unit));
-       if (hwif->mate) {
-               hwif->select_data = hwif->mate->select_data;
+       if (hwif->unit == ATA_SECONDARY) {
+
+               /* FIXME: If we are initializing the secondary channel, let us
+                * assume that the primary channel got initialized just a tad
+                * bit before now.  It would be much cleaner if the data in
+                * ns87415_control just got duplicated.
+                */
+
+               if (!hwif->select_data)
+                   hwif->select_data = (unsigned long)
+                       &ns87415_control[ns87415_count - 1];
        } else {
-               hwif->select_data = (unsigned long)
-                                       &ns87415_control[ns87415_count++];
+               if (!hwif->select_data)
+                   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 */
@@ -170,9 +180,9 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
                do {
                        udelay(50);
                        stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]);
-                       if (stat == 0xff)
-                               break;
-               } while ((stat & BUSY_STAT) && --timeout);
+                       if (stat == 0xff)
+                               break;
+               } while ((stat & BUSY_STAT) && --timeout);
 #endif
        }
 
@@ -181,13 +191,23 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
 
        if (!using_inta)
                hwif->irq = hwif->unit ? 15 : 14;       /* legacy mode */
-       else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-               hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
+       else {
+               static int primary_irq = 0;
+
+               /* Ugly way to let the primary and secondary channel on the
+                * chip use the same IRQ line.
+                */
+
+               if (hwif->unit == ATA_PRIMARY)
+                       primary_irq = hwif->irq;
+               else if (!hwif->irq)
+                       hwif->irq = primary_irq;
+       }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if (hwif->dma_base)
                hwif->dmaproc = &ns87415_dmaproc;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif
 
        hwif->selectproc = &ns87415_selectproc;
 }
index 70408f3573a2e0747f4256d71671e01cd862d78c..73a32607b1f46c341cd8506b27bdfe511d588e13 100644 (file)
@@ -162,7 +162,7 @@ int __init setup_pdc4030(struct ata_channel *hwif)
        struct dc_ident ident;
        int i;
        ide_startstop_t startstop;
-       
+
        if (!hwif) return 0;
 
        drive = &hwif->drives[0];
@@ -224,9 +224,8 @@ int __init setup_pdc4030(struct ata_channel *hwif)
         */
 
        hwif->chipset   = hwif2->chipset = ide_pdc4030;
-       hwif->mate      = hwif2;
-       hwif2->mate     = hwif;
-       hwif2->unit     = 1;
+       hwif->unit      = ATA_PRIMARY;
+       hwif2->unit     = ATA_SECONDARY;
        hwif->selectproc = hwif2->selectproc = &promise_selectproc;
        hwif->serialized = hwif2->serialized = 1;
 
index 8e023e8d3d283d089d2b3040d453b3dc423e2a6a..e97a2ec203db4e4df9c25ba11fce94a504264134 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: piix.c,v 1.2 2002/03/13 22:50:43 vojtech Exp $
+ * $Id: piix.c,v 1.3 2002/03/29 16:06:06 vojtech Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik
  *
@@ -128,7 +128,7 @@ static int piix_get_info(char *buffer, char **addr, off_t offset, int count)
 
        piix_print("----------PIIX BusMastering IDE Configuration---------------");
 
-       piix_print("Driver Version:                     1.2");
+       piix_print("Driver Version:                     1.3");
        piix_print("South Bridge:                       %s", bmide_dev->name);
 
        pci_read_config_byte(dev, PCI_REVISION_ID, &t);
@@ -331,7 +331,7 @@ static int piix_set_drive(ide_drive_t *drive, unsigned char speed)
                umul = 2;
 
        T = 1000000000 / piix_clock;
-       UT = T / umul;
+       UT = umul ? (T / umul) : 0;
 
        ata_timing_compute(drive, speed, &t, T, UT);
 
index 8f9a2cc0e679e511a88356f3bbf14c8961f4fd18..572acb19a4a32b5d2fc3f695137511847b6b6a2a 100644 (file)
@@ -411,22 +411,23 @@ int __init probe (int base)
 
                        return 1;
                } else {
-                       int i,j;
+                       int i;
+
                        /* secondary enabled */
                        printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
                                        ide_hwifs[0].name,ide_hwifs[1].name);
 
-                       for (i=0;i<2;i++) {
+                       for (i = 0; i < 2; i++) {
+                               int j;
 
                                ide_hwifs[i].chipset = ide_qd65xx;
-                               ide_hwifs[i].mate = &ide_hwifs[i^1];
                                ide_hwifs[i].unit = i;
 
                                ide_hwifs[i].select_data = base;
                                ide_hwifs[i].config_data = config | (control <<8);
                                ide_hwifs[i].tuneproc = &qd6580_tune_drive;
 
-                               for (j=0;j<2;j++) {
+                               for (j = 0; j < 2; j++) {
                                        ide_hwifs[i].drives[j].drive_data =
                                               i?QD6580_DEF_DATA2:QD6580_DEF_DATA;
                                        ide_hwifs[i].drives[j].io_32bit = 1;
index 9b45da0205f7556d3488c0f8793c877e51b18a08..fd4a10629951c037ca34bff57ae664bcf2cd5c57 100644 (file)
@@ -1,17 +1,17 @@
 /*
- * linux/drivers/ide/sis5513.c         Version 0.13    March 4, 2002
+ * linux/drivers/ide/sis5513.c         Version 0.13    March 6, 2002
  *
  * Copyright (C) 1999-2000     Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002          Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
  * May be copied or modified under the terms of the GNU General Public License
  *
-*/
-
-/* Thanks :
- * For direct support and hardware : SiS Taiwan.
- * For ATA100 support advice       : Daniela Engert.
- * For checking code correctness, providing patches :
- * John Fremlin, Manfred Spraul
+ *
+ * Thanks :
+ *
+ * SiS Taiwan          : for direct support and hardware.
+ * Daniela Engert      : for initial ATA100 advices and numerous others.
+ * John Fremlin, Manfred Spraul :
+ *                       for checking code correctness, providing patches.
  */
 
 /*
 
 #include "ata-timing.h"
 
+/* When DEBUG is defined it outputs initial PCI config register
+   values and changes made to them by the driver */
 // #define DEBUG
-/* if BROKEN_LEVEL is defined it limits the DMA mode
+/* When BROKEN_LEVEL is defined it limits the DMA mode
    at boot time to its value */
 // #define BROKEN_LEVEL XFER_SW_DMA_0
 #define DISPLAY_SIS_TIMINGS
 
 /* Miscellaneaous flags */
 #define SIS5513_LATENCY                0x01
-/* ATA transfer mode capabilities */
+
+/* registers layout and init values are chipset family dependant */
+/* 1/ define families */
 #define ATA_00         0x00
 #define ATA_16         0x01
 #define ATA_33         0x02
 #define ATA_66         0x03
-#define ATA_100a       0x04
+#define ATA_100a       0x04    // SiS730 is ATA100 with ATA66 layout
 #define ATA_100                0x05
 #define ATA_133                0x06
 
-static unsigned char dma_capability = 0x00;
-
+/* 2/ variable holding the controller chipset family value */
+static unsigned char chipset_family;
 
 /*
  * Debug code: following IDE config registers' changes
  */
 #ifdef DEBUG
-/* Copy of IDE Config registers 0x00 -> 0x58
+/* Copy of IDE Config registers 0x00 -> 0x57
    Fewer might be used depending on the actual chipset */
-static unsigned char ide_regs_copy[] = {
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0,
-       0x0, 0x0, 0x0, 0x0
-};
+static unsigned char ide_regs_copy[0x58];
 
 static byte sis5513_max_config_register(void) {
-       switch(dma_capability) {
+       switch(chipset_family) {
                case ATA_00:
                case ATA_16:    return 0x4f;
                case ATA_33:    return 0x52;
@@ -185,7 +166,7 @@ static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
 static const struct {
        const char *name;
        unsigned short host_id;
-       unsigned char dma_capability;
+       unsigned char chipset_family;
        unsigned char flags;
 } SiSHostChipInfo[] = {
        { "SiS750",     PCI_DEVICE_ID_SI_750,   ATA_100,        SIS5513_LATENCY },
@@ -211,7 +192,7 @@ static const struct {
 
 /* Cycle time bits and values vary accross chip dma capabilities
    These three arrays hold the register layout and the values to set.
-   Indexed by dma_capability and (dma_mode - XFER_UDMA_0) */
+   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
 static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
 static byte cycle_time_range[] = {0,0,2,3,3,4,4};
 static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
@@ -293,13 +274,13 @@ static char* get_drives_info (char *buffer, byte pos)
        pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
 
 /* UDMA */
-       if (dma_capability >= ATA_33) {
+       if (chipset_family >= ATA_33) {
                p += sprintf(p, "                UDMA %s \t \t \t UDMA %s\n",
                             (reg01 & 0x80)  ? "Enabled" : "Disabled",
                             (reg11 & 0x80) ? "Enabled" : "Disabled");
 
                p += sprintf(p, "                UDMA Cycle Time    ");
-               switch(dma_capability) {
+               switch(chipset_family) {
                        case ATA_33:    p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
                        case ATA_66:
                        case ATA_100a:  p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
@@ -308,7 +289,7 @@ static char* get_drives_info (char *buffer, byte pos)
                        default:        p += sprintf(p, "133+ ?"); break;
                }
                p += sprintf(p, " \t UDMA Cycle Time    ");
-               switch(dma_capability) {
+               switch(chipset_family) {
                        case ATA_33:    p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
                        case ATA_66:
                        case ATA_100a:  p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
@@ -321,7 +302,7 @@ static char* get_drives_info (char *buffer, byte pos)
 
 /* Data Active */
        p += sprintf(p, "                Data Active Time   ");
-       switch(dma_capability) {
+       switch(chipset_family) {
                case ATA_00:
                case ATA_16: /* confirmed */
                case ATA_33:
@@ -332,7 +313,7 @@ static char* get_drives_info (char *buffer, byte pos)
                default: p += sprintf(p, "133+ ?"); break;
        }
        p += sprintf(p, " \t Data Active Time   ");
-       switch(dma_capability) {
+       switch(chipset_family) {
                case ATA_00:
                case ATA_16:
                case ATA_33:
@@ -370,7 +351,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
        u16 reg2, reg3;
 
        p += sprintf(p, "\nSiS 5513 ");
-       switch(dma_capability) {
+       switch(chipset_family) {
                case ATA_00: p += sprintf(p, "Unknown???"); break;
                case ATA_16: p += sprintf(p, "DMA 16"); break;
                case ATA_33: p += sprintf(p, "Ultra 33"); break;
@@ -386,7 +367,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
 /* Status */
        pci_read_config_byte(bmide_dev, 0x4a, &reg);
        p += sprintf(p, "Channel Status: ");
-       if (dma_capability < ATA_66) {
+       if (chipset_family < ATA_66) {
                p += sprintf(p, "%s \t \t \t \t %s\n",
                             (reg & 0x04) ? "On" : "Off",
                             (reg & 0x02) ? "On" : "Off");
@@ -403,7 +384,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
                     (reg & 0x04) ? "Native" : "Compatible");
 
 /* 80-pin cable ? */
-       if (dma_capability > ATA_33) {
+       if (chipset_family > ATA_33) {
                pci_read_config_byte(bmide_dev, 0x48, &reg);
                p += sprintf(p, "Cable Type:     %s \t \t \t %s\n",
                             (reg & 0x10) ? cable_type[1] : cable_type[0],
@@ -507,7 +488,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
        }
 
        /* register layout changed with newer ATA100 chips */
-       if (dma_capability < ATA_100) {
+       if (chipset_family < ATA_100) {
                pci_read_config_byte(dev, drive_pci, &test1);
                pci_read_config_byte(dev, drive_pci+1, &test2);
 
@@ -587,7 +568,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
 
        pci_read_config_byte(dev, drive_pci+1, &reg);
        /* Disable UDMA bit for non UDMA modes on UDMA chips */
-       if ((speed < XFER_UDMA_0) && (dma_capability > ATA_16)) {
+       if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
                reg &= 0x7F;
                pci_write_config_byte(dev, drive_pci+1, reg);
        }
@@ -604,11 +585,11 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
                        /* Force the UDMA bit on if we want to use UDMA */
                        reg |= 0x80;
                        /* clean reg cycle time bits */
-                       reg &= ~((0xFF >> (8 - cycle_time_range[dma_capability]))
-                                << cycle_time_offset[dma_capability]);
+                       reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
+                                << cycle_time_offset[chipset_family]);
                        /* set reg cycle time bits */
-                       reg |= cycle_time_value[dma_capability-ATA_00][speed-XFER_UDMA_0]
-                               << cycle_time_offset[dma_capability];
+                       reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0]
+                               << cycle_time_offset[chipset_family];
                        pci_write_config_byte(dev, drive_pci+1, reg);
                        break;
                case XFER_MW_DMA_2:
@@ -624,7 +605,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
                case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2));
                case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1));
                case XFER_PIO_0:
-               default:         return((int) config_chipset_for_pio(drive, 0));        
+               default:         return((int) config_chipset_for_pio(drive, 0));
        }
        drive->current_speed = speed;
 #ifdef DEBUG
@@ -657,17 +638,17 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
               drive->dn, ultra);
 #endif
 
-       if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (dma_capability >= ATA_100a))
+       if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a))
                speed = XFER_UDMA_5;
-       else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (dma_capability >= ATA_66))
+       else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66))
                speed = XFER_UDMA_4;
-       else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (dma_capability >= ATA_66))
+       else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66))
                speed = XFER_UDMA_3;
-       else if ((id->dma_ultra & 0x0004) && ultra && (dma_capability >= ATA_33))
+       else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33))
                speed = XFER_UDMA_2;
-       else if ((id->dma_ultra & 0x0002) && ultra && (dma_capability >= ATA_33))
+       else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33))
                speed = XFER_UDMA_1;
-       else if ((id->dma_ultra & 0x0001) && ultra && (dma_capability >= ATA_33))
+       else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33))
                speed = XFER_UDMA_0;
        else if (id->dma_mword & 0x0004)
                speed = XFER_MW_DMA_2;
@@ -700,6 +681,8 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
        struct hd_driveid *id           = drive->id;
        ide_dma_action_t dma_func       = ide_dma_off_quietly;
 
+       config_chipset_for_pio(drive, 5);
+
        if (id && (id->capability & 1) && drive->channel->autodma) {
                /* Consult the list of known "bad" drives */
                if (ide_dmaproc(ide_dma_bad_drive, drive)) {
@@ -764,10 +747,6 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
        struct pci_dev *host;
        int i = 0;
 
-#ifdef DEBUG
-       sis5513_print_registers(dev, "pci_init_sis5513 start");
-#endif
-
        /* Find the chip */
        for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) {
                host = pci_find_device (PCI_VENDOR_ID_SI,
@@ -777,12 +756,16 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
                        continue;
 
                host_dev = host;
-               dma_capability = SiSHostChipInfo[i].dma_capability;
+               chipset_family = SiSHostChipInfo[i].chipset_family;
                printk(SiSHostChipInfo[i].name);
                printk("\n");
 
+#ifdef DEBUG
+               sis5513_print_registers(dev, "pci_init_sis5513 start");
+#endif
+
                if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
-                       byte latency = (dma_capability == ATA_100)? 0x80 : 0x10; /* Lacking specs */
+                       byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
                        pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
                }
        }
@@ -792,7 +775,7 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
           2/ tell old chips to allow per drive IDE timings */
        if (host_dev) {
                byte reg;
-               switch(dma_capability) {
+               switch(chipset_family) {
                        case ATA_133:
                        case ATA_100:
                                /* Set compatibility bit */
@@ -847,7 +830,7 @@ unsigned int __init ata66_sis5513(struct ata_channel *hwif)
        byte mask = hwif->unit ? 0x20 : 0x10;
        pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
 
-       if (dma_capability >= ATA_66) {
+       if (chipset_family >= ATA_66) {
                ata66 = (reg48h & mask) ? 0 : 1;
        }
         return ata66;
@@ -866,7 +849,7 @@ void __init ide_init_sis5513(struct ata_channel *hwif)
 
        if (host_dev) {
 #ifdef CONFIG_BLK_DEV_IDEDMA
-               if (dma_capability > ATA_16) {
+               if (chipset_family > ATA_16) {
                        hwif->autodma = noautodma ? 0 : 1;
                        hwif->highmem = 1;
                        hwif->dmaproc = &sis5513_dmaproc;
index 50675cfeed52b9381b3aa0d6c09cc5017c28a657..f3aee6e8b9ff54aad62b25429b6017d7f969eb0d 100644 (file)
@@ -248,8 +248,19 @@ void __init ide_init_trm290(struct ata_channel *hwif)
 
        if ((reg & 0x10))
                hwif->irq = hwif->unit ? 15 : 14;       /* legacy mode */
-       else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-               hwif->irq = hwif->mate->irq;            /* sharing IRQ with mate */
+       else {
+               static int primary_irq = 0;
+
+               /* Ugly way to let the primary and secondary channel on the
+                * chip use the same IRQ line.
+                */
+
+               if (hwif->unit == ATA_PRIMARY)
+                       primary_irq = hwif->irq;
+               else if (!hwif->irq)
+                       hwif->irq = primary_irq;
+       }
+
        ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
index bb70bc74fab236834710d59e5a8372bd862b435d..747e4229c13e830a2f78ff7300ff9efe1e90191f 100644 (file)
@@ -146,7 +146,7 @@ void __init init_umc8672 (void)     /* called from ide.c */
        {
                __restore_flags(flags); /* local CPU only */
                printk ("umc8672: not found\n");
-               return;  
+               return;
        }
        outb_p (0xa5,0x108); /* disable umc */
 
@@ -158,7 +158,6 @@ void __init init_umc8672 (void)     /* called from ide.c */
        ide_hwifs[1].chipset = ide_umc8672;
        ide_hwifs[0].tuneproc = &tune_umc;
        ide_hwifs[1].tuneproc = &tune_umc;
-       ide_hwifs[0].mate = &ide_hwifs[1];
-       ide_hwifs[1].mate = &ide_hwifs[0];
-       ide_hwifs[1].unit = 1;
+       ide_hwifs[0].unit = ATA_PRIMARY;
+       ide_hwifs[1].unit = ATA_SECONDARY;
 }
index 6d80160690b2834a8643d60c8301ac5db17fc7e4..1b0d74f37f3ea6aff2755c42057cc5044d560b9d 100644 (file)
@@ -433,10 +433,10 @@ typedef void (ide_intrproc_t) (ide_drive_t *);
 typedef void (ide_maskproc_t) (ide_drive_t *, int);
 typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t);
 
-/*
- * ide soft-power support
- */
-typedef int (ide_busproc_t) (ide_drive_t *, int);
+enum {
+       ATA_PRIMARY     = 0,
+       ATA_SECONDARY   = 1
+};
 
 struct ata_channel {
        struct device   dev;            /* device handle */
@@ -467,7 +467,6 @@ struct ata_channel {
        struct scatterlist *sg_table;   /* Scatter-gather list used to build the above */
        int sg_nents;                   /* Current number of entries in it */
        int sg_dma_direction;           /* dma transfer direction */
-       struct ata_channel *mate;       /* other hwif from same PCI chip */
        unsigned long   dma_base;       /* base addr for dma ports */
        unsigned        dma_extra;      /* extra addr for dma ports */
        unsigned long   config_data;    /* for use by chipset-specific code */
@@ -480,7 +479,7 @@ struct ata_channel {
        hwif_chipset_t  chipset;        /* sub-module for tuning.. */
        unsigned        noprobe    : 1; /* don't probe for this interface */
        unsigned        present    : 1; /* there is a device on this interface */
-       unsigned        serialized : 1; /* serialized operation with mate hwif */
+       unsigned        serialized : 1; /* serialized operation between channels */
        unsigned        sharing_irq: 1; /* 1 = sharing irq with another hwif */
        unsigned        reset      : 1; /* reset after probe */
        unsigned        autodma    : 1; /* automatically try to enable DMA at boot */
@@ -490,7 +489,7 @@ struct ata_channel {
        unsigned long   last_time;      /* time when previous rq was done */
 #endif
        byte            straight8;      /* Alan's straight 8 check */
-       ide_busproc_t   *busproc;       /* driver soft-power interface */
+       int (*busproc)(ide_drive_t *, int);     /* driver soft-power interface */
        byte            bus_state;      /* power state of the IDE bus */
 };
 
@@ -513,7 +512,6 @@ typedef enum {
  */
 typedef ide_startstop_t (ide_pre_handler_t)(ide_drive_t *, struct request *);
 typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
-typedef ide_startstop_t (ide_post_handler_t)(ide_drive_t *);
 
 /*
  * when ide_timer_expiry fires, invoke a handler of this type