Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Kernel v2.4.19-pre8-ac3 /ide-2.4.19-p8-ac1.all.convert.10.patch

Filename:/ide-2.4.19-p8-ac1.all.convert.10.patch
Lines Added:21421
Lines Deleted:0
Also changed in: (Previous)
(Following)

Location
[  2.4.19-pre8-ac3
   o  ide-2.4.19-p8-ac1.all.convert.10.patch

Patch

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.19pre8/ide-2.4.19-p8-ac1.all.convert.10.patch linux.19pre8-ac3/+
ide-2.4.19-p8-ac1.all.convert.10.patch
--- linux.19pre8/ide-2.4.19-p8-ac1.all.convert.10.patch   Thu Jan  1 01:00:00 1970
+++ linux.19pre8-ac3/ide-2.4.19-p8-ac1.all.convert.10.patch   Mon May 13 14:08:36 2002
@@ -0,0 +1,21421 @@
+diff -urN linux-2.4.19-p8-ac1-pristine/arch/cris/drivers/ide.c linux-2.4.19-p8-ac1/arch/cris/drivers/ide.c
+--- linux-2.4.19-p8-ac1-pristine/arch/cris/drivers/ide.c   Thu May  9 00:17:17 2002
++++ linux-2.4.19-p8-ac1/arch/cris/drivers/ide.c   Thu May  9 13:52:37 2002
+@@ -816,13 +816,13 @@
+          rq = HWGROUP(drive)->rq;
+          for (i = rq->nr_sectors; i > 0;) {
+             i -= rq->current_nr_sectors;
+-            ide_end_request(1, HWGROUP(drive));
++            DRIVER(drive)->end_request(drive, 1);
+          }
+          return ide_stopped;
+       }
+       printk("%s: bad DMA status\n", drive->name);
+    }
+-   return ide_error(drive, "dma_intr", stat);
++   return DRIVER(drive)->error(drive, "dma_intr", stat);
+ }
+ 
+ /*
+diff -urN linux-2.4.19-p8-ac1-pristine/arch/i386/kernel/pci-pc.c linux-2.4.19-p8-ac1/arch/i386/kernel/pci-pc.c
+--- linux-2.4.19-p8-ac1-pristine/arch/i386/kernel/pci-pc.c   Fri May 10 10:10:10 2002
++++ linux-2.4.19-p8-ac1/arch/i386/kernel/pci-pc.c   Thu May  9 13:52:37 2002
+@@ -1156,6 +1156,12 @@
+     */
+    if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+       return;
++   /*
++    * PCI IDE controllers who are not function 1 off the south bridge
++    * need to be skipped.
++    */
++   if (!(PCI_FUNC(d->devfn) & 1))
++      return;
+    DBG("PCI: IDE base address fixup for %s\n", d->slot_name);
+    for(i=0; i<4; i++) {
+       struct resource *r = &d->resource[i];
+@@ -1227,6 +1233,11 @@
+    pci_read_config_byte(d, PCI_REVISION_ID, &revision);
+    
+    if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
++      /* fix pci bus latency issues resulted by NB bios error
++         it appears on bug free^Wreduced kt266x's bios forces
++         NB latency to zero */
++      pci_write_config_byte(d, PCI_LATENCY_TIMER, 0);
++
+       where = 0x95; /* the memory write queue timer register is 
+              different for the KT266x's: 0x95 not 0x55 */
+    } else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&
+diff -urN linux-2.4.19-p8-ac1-pristine/arch/ppc/kernel/setup.c linux-2.4.19-p8-ac1/arch/ppc/kernel/setup.c
+--- linux-2.4.19-p8-ac1-pristine/arch/ppc/kernel/setup.c   Thu May  9 00:17:40 2002
++++ linux-2.4.19-p8-ac1/arch/ppc/kernel/setup.c   Thu May  9 13:52:37 2002
+@@ -687,14 +687,16 @@
+    id->cfs_enable_2   = __le16_to_cpu(id->cfs_enable_2);
+    id->csf_default    = __le16_to_cpu(id->csf_default);
+    id->dma_ultra      = __le16_to_cpu(id->dma_ultra);
+-   id->word89         = __le16_to_cpu(id->word89);
+-   id->word90         = __le16_to_cpu(id->word90);
++   id->trseuc         = __le16_to_cpu(id->trseuc);
++   id->trsEuc         = __le16_to_cpu(id->trsEuc);
+    id->CurAPMvalues   = __le16_to_cpu(id->CurAPMvalues);
+-   id->word92         = __le16_to_cpu(id->word92);
++   id->mprc           = __le16_to_cpu(id->mprc);
+    id->hw_config      = __le16_to_cpu(id->hw_config);
+    id->acoustic       = __le16_to_cpu(id->acoustic);
+-   for (i = 0; i < 5; i++)
+-      id->words95_99[i]  = __le16_to_cpu(id->words95_99[i]);
++   id->msrqs          = __le16_to_cpu(id->msrqs);
++   id->sxfert         = __le16_to_cpu(id->sxfert);
++   id->sal            = __le16_to_cpu(id->sal);
++   id->spg            = __le32_to_cpu(id->spg);
+    id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
+    for (i = 0; i < 22; i++)
+       id->words104_125[i]   = __le16_to_cpu(id->words104_125[i]);
+diff -urN linux-2.4.19-p8-ac1-pristine/arch/ppc64/kernel/setup.c linux-2.4.19-p8-ac1/arch/ppc64/kernel/setup.c
+--- linux-2.4.19-p8-ac1-pristine/arch/ppc64/kernel/setup.c   Thu May  9 00:17:44 2002
++++ linux-2.4.19-p8-ac1/arch/ppc64/kernel/setup.c   Thu May  9 15:35:56 2002
+@@ -607,17 +607,19 @@
+    id->cfs_enable_2   = __le16_to_cpu(id->cfs_enable_2);
+    id->csf_default    = __le16_to_cpu(id->csf_default);
+    id->dma_ultra      = __le16_to_cpu(id->dma_ultra);
+-   id->word89         = __le16_to_cpu(id->word89);
+-   id->word90         = __le16_to_cpu(id->word90);
++   id->trseuc         = __le16_to_cpu(id->trseuc);
++   id->trsEuc         = __le16_to_cpu(id->trsEuc);
+    id->CurAPMvalues   = __le16_to_cpu(id->CurAPMvalues);
+-   id->word92         = __le16_to_cpu(id->word92);
++   id->mprc           = __le16_to_cpu(id->mprc);
+    id->hw_config      = __le16_to_cpu(id->hw_config);
+    id->acoustic       = __le16_to_cpu(id->acoustic);
+-   for (i = 0; i < 5; i++)
+-      id->words95_99[i]  = __le16_to_cpu(id->words95_99[i]);
++   id->msrqs          = __le16_to_cpu(id->msrqs);
++   id->sxfert         = __le16_to_cpu(id->sxfert);
++   id->sal            = __le16_to_cpu(id->sal);
++   id->spg            = __le32_to_cpu(id->spg);
+    id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
+-   for (i = 0; i < 21; i++)
+-      id->words104_125[i]  = __le16_to_cpu(id->words104_125[i]);
++   for (i = 0; i < 22; i++)
++      id->words104_125[i]   = __le16_to_cpu(id->words104_125[i]);
+    id->last_lun       = __le16_to_cpu(id->last_lun);
+    id->word127        = __le16_to_cpu(id->word127);
+    id->dlf            = __le16_to_cpu(id->dlf);
+@@ -627,14 +629,14 @@
+    id->word156        = __le16_to_cpu(id->word156);
+    for (i = 0; i < 3; i++)
+       id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
+-   id->cfa_power=__le16_to_cpu(id->cfa_power);
+-   for (i = 0; i < 15; i++)
++   id->cfa_power      = __le16_to_cpu(id->cfa_power);
++   for (i = 0; i < 14; i++)
+       id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
+-   for (i = 0; i < 29; i++)
++   for (i = 0; i < 31; i++)
+       id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
+    for (i = 0; i < 48; i++)
+       id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
+-   id->integrity_word=__le16_to_cpu(id->integrity_word);
++   id->integrity_word  = __le16_to_cpu(id->integrity_word);
+ }
+ #endif
+ 
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/Config.in linux-2.4.19-p8-ac1/drivers/ide/Config.in
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/Config.in   Fri May 10 10:10:21 2002
++++ linux-2.4.19-p8-ac1/drivers/ide/Config.in   Thu May  9 16:18:51 2002
+@@ -82,10 +82,11 @@
+        dep_bool '    PROMISE PDC202{46|62|65|67|68|69|70} support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI
+        dep_bool '      Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX
+        dep_bool '      Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX
+-       dep_bool '    ServerWorks OSB4/CSB5 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
++       dep_bool '    RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
++       dep_bool '    ServerWorks OSB4/CSB5/CSB6 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI
+        dep_bool '    SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
+        dep_bool '    SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
+-       dep_bool '    Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERI+
MENTAL
++       dep_bool '    Tekram TRM290 chipset support' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
+        dep_bool '    VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
+        if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
+           bool '    Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/Makefile linux-2.4.19-p8-ac1/drivers/ide/Makefile
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/Makefile   Fri May 10 10:10:21 2002
++++ linux-2.4.19-p8-ac1/drivers/ide/Makefile   Thu May  9 16:21:34 2002
+@@ -10,7 +10,7 @@
+ 
+ O_TARGET := idedriver.o
+ 
+-export-objs      := ide-taskfile.o ide.o ide-features.o ide-probe.o ataraid.o
++export-objs      := ide-taskfile.o ide.o ide-probe.o ataraid.o
+ list-multi      := ide-mod.o ide-probe-mod.o
+ 
+ obj-y      :=
+@@ -76,7 +76,7 @@
+ 
+ ide-obj-$(CONFIG_PROC_FS)      += ide-proc.o
+ 
+-ide-mod-objs      := ide-taskfile.o ide.o ide-features.o $(ide-obj-y)
++ide-mod-objs      := ide-taskfile.o ide.o $(ide-obj-y)
+ ide-probe-mod-objs   := ide-probe.o ide-geometry.o
+ 
+ include $(TOPDIR)/Rules.make
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/aec62xx.c linux-2.4.19-p8-ac1/drivers/ide/aec62xx.c
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/aec62xx.c   Tue Jun 20 07:52:36 2000
++++ linux-2.4.19-p8-ac1/drivers/ide/aec62xx.c   Fri May 10 05:15:51 2002
+@@ -1,8 +1,7 @@
+ /*
+- * linux/drivers/ide/aec62xx.c      Version 0.09   June. 9, 2000
++ * linux/drivers/ide/aec62xx.c      Version 0.11   March 27, 2002
+  *
+- * Copyright (C) 1999-2000   Andre Hedrick (andre@linux-ide.org)
+- * May be copied or modified under the terms of the GNU General Public License
++ * Copyright (C) 1999-2002   Andre Hedrick <andre@linux-ide.org>
+  *
+  */
+ 
+@@ -48,154 +47,209 @@
+ 
+ static int aec62xx_get_info(char *, char **, off_t, int);
+ extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+-extern char *ide_media_verbose(ide_drive_t *);
+-static struct pci_dev *bmide_dev;
+ 
+-static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
+-{
+-   char *p = buffer;
+-
+-   u32 bibma = pci_resource_start(bmide_dev, 4);
+-   u8 c0 = 0, c1 = 0;
+-   u8 art = 0, uart = 0;
++#define AEC_MAX_DEVS      5
+ 
+-   switch(bmide_dev->device) {
+-      case PCI_DEVICE_ID_ARTOP_ATP850UF:
+-         p += sprintf(p, "\n                                AEC6210 Chipset.\n");
+-         break;
+-      case PCI_DEVICE_ID_ARTOP_ATP860:
+-         p += sprintf(p, "\n                                AEC6260 No Bios Chipset.\n");
+-         break;
+-      case PCI_DEVICE_ID_ARTOP_ATP860R:
+-         p += sprintf(p, "\n                                AEC6260 Chipset.\n");
+-         break;
+-      default:
+-         p += sprintf(p, "\n                                AEC62?? Chipset.\n");
+-         break;
+-   }
++static struct pci_dev *aec_devs[AEC_MAX_DEVS];
++static int n_aec_devs;
+ 
+-        /*
+-         * at that point bibma+0x2 et bibma+0xa are byte registers
+-         * to investigate:
+-         */
+-   c0 = inb_p((unsigned short)bibma + 0x02);
+-   c1 = inb_p((unsigned short)bibma + 0x0a);
+-
+-   p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+-   (void) pci_read_config_byte(bmide_dev, 0x4a, &art);
+-   p += sprintf(p, "                %sabled                         %sabled\n",
+-      (art&0x02)?" en":"dis",(art&0x04)?" en":"dis");
+-   p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+-   p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+-      (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
++#undef DEBUG_AEC_REGS
+ 
+-   switch(bmide_dev->device) {
+-      case PCI_DEVICE_ID_ARTOP_ATP850UF:
+-         (void) pci_read_config_byte(bmide_dev, 0x54, &art);
+-         p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)         %s(%s)           %s(%s)\n",
++static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
++{
++   char *p = buffer;
++   char *chipset_nums[] = {"error", "error", "error", "error",
++            "error", "error", "850UF",   "860",
++             "860R",   "865",  "865R", "error"  };
++//   char *modes_33[] = {};
++//   char *modes_34[] = {};
++   int i;
++
++   for (i = 0; i < n_aec_devs; i++) {
++      struct pci_dev *dev   = aec_devs[i];
++   //   u32 iobase      = dev->resource[4].start;
++      u32 iobase      = pci_resource_start(dev, 4);
++      u8 c0         = inb_p(iobase + 0x02);
++      u8 c1         = inb_p(iobase + 0x0a);
++      u8 art         = 0;
++#ifdef DEBUG_AEC_REGS
++      u8 uart         = 0;
++#endif /* DEBUG_AEC_REGS */
++
++      p += sprintf(p, "\nController: %d\n", i);
++      p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]);
++
++      p += sprintf(p, "--------------- Primary Channel "
++            "---------------- Secondary Channel "
++            "-------------\n");
++      (void) pci_read_config_byte(dev, 0x4a, &art);
++      p += sprintf(p, "                %sabled ",
++         (art&0x02)?" en":"dis");
++      p += sprintf(p, "                        %sabled\n",
++         (art&0x04)?" en":"dis");
++      p += sprintf(p, "--------------- drive0 --------- drive1 "
++            "-------- drive0 ---------- drive1 ------\n");
++      p += sprintf(p, "DMA enabled:    %s              %s ",
++         (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ");
++      p += sprintf(p, "            %s               %s\n",
++         (c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
++
++      if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
++         (void) pci_read_config_byte(dev, 0x54, &art);
++         p += sprintf(p, "DMA Mode:       %s(%s)",
+             (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO",
+-            (art&0x02)?"2":(art&0x01)?"1":"0",
++            (art&0x02)?"2":(art&0x01)?"1":"0");
++         p += sprintf(p, "          %s(%s)",
+             (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO",
+-            (art&0x08)?"2":(art&0x04)?"1":"0",
++            (art&0x08)?"2":(art&0x04)?"1":"0");
++         p += sprintf(p, "         %s(%s)",
+             (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO",
+-            (art&0x20)?"2":(art&0x10)?"1":"0",
++            (art&0x20)?"2":(art&0x10)?"1":"0");
++         p += sprintf(p, "           %s(%s)\n",
+             (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
+             (art&0x80)?"2":(art&0x40)?"1":"0");
+-         (void) pci_read_config_byte(bmide_dev, 0x40, &art);
++#ifdef DEBUG_AEC_REGS
++         (void) pci_read_config_byte(dev, 0x40, &art);
+          p += sprintf(p, "Active:         0x%02x", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x42, &art);
++         (void) pci_read_config_byte(dev, 0x42, &art);
+          p += sprintf(p, "             0x%02x", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x44, &art);
++         (void) pci_read_config_byte(dev, 0x44, &art);
+          p += sprintf(p, "            0x%02x", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x46, &art);
++         (void) pci_read_config_byte(dev, 0x46, &art);
+          p += sprintf(p, "              0x%02x\n", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x41, &art);
++         (void) pci_read_config_byte(dev, 0x41, &art);
+          p += sprintf(p, "Recovery:       0x%02x", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x43, &art);
++         (void) pci_read_config_byte(dev, 0x43, &art);
+          p += sprintf(p, "             0x%02x", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x45, &art);
++         (void) pci_read_config_byte(dev, 0x45, &art);
+          p += sprintf(p, "            0x%02x", art);
+-         (void) pci_read_config_byte(bmide_dev, 0x47, &art);
++         (void) pci_read_config_byte(dev, 0x47, &art);
+          p += sprintf(p, "              0x%02x\n", art);
+-         break;
+-      case PCI_DEVICE_ID_ARTOP_ATP860:
+-      case PCI_DEVICE_ID_ARTOP_ATP860R:
+-         (void) pci_read_config_byte(bmide_dev, 0x44, &art);
+-         p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)",
++#endif /* DEBUG_AEC_REGS */
++      } else {
++         /*
++          * case PCI_DEVICE_ID_ARTOP_ATP860:
++          * case PCI_DEVICE_ID_ARTOP_ATP860R:
++          * case PCI_DEVICE_ID_ARTOP_ATP865:
++          * case PCI_DEVICE_ID_ARTOP_ATP865R:
++          */
++         (void) pci_read_config_byte(dev, 0x44, &art);
++         p += sprintf(p, "DMA Mode:       %s(%s)",
+             (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
+-            ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((a+
rt&0x01)==0x01)?"0":"?",
++            ((art&0x07)==0x07)?"6":
++            ((art&0x06)==0x06)?"5":
++            ((art&0x05)==0x05)?"4":
++            ((art&0x04)==0x04)?"3":
++            ((art&0x03)==0x03)?"2":
++            ((art&0x02)==0x02)?"1":
++            ((art&0x01)==0x01)?"0":"?");
++         p += sprintf(p, "          %s(%s)",
+             (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
+-            ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((a+
rt&0x10)==0x10)?"0":"?");
+-         (void) pci_read_config_byte(bmide_dev, 0x45, &art);
+-         p += sprintf(p, "         %s(%s)           %s(%s)\n",
++            ((art&0x70)==0x70)?"6":
++            ((art&0x60)==0x60)?"5":
++            ((art&0x50)==0x50)?"4":
++            ((art&0x40)==0x40)?"3":
++            ((art&0x30)==0x30)?"2":
++            ((art&0x20)==0x20)?"1":
++            ((art&0x10)==0x10)?"0":"?");
++         (void) pci_read_config_byte(dev, 0x45, &art);
++         p += sprintf(p, "         %s(%s)",
+             (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
+-            ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((a+
rt&0x01)==0x01)?"0":"?",
++            ((art&0x07)==0x07)?"6":
++            ((art&0x06)==0x06)?"5":
++            ((art&0x05)==0x05)?"4":
++            ((art&0x04)==0x04)?"3":
++            ((art&0x03)==0x03)?"2":
++            ((art&0x02)==0x02)?"1":
++            ((art&0x01)==0x01)?"0":"?");
++         p += sprintf(p, "           %s(%s)\n",
+             (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
+-            ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((a+
rt&0x10)==0x10)?"0":"?");
+-         (void) pci_read_config_byte(bmide_dev, 0x40, &art);
++            ((art&0x70)==0x70)?"6":
++            ((art&0x60)==0x60)?"5":
++            ((art&0x50)==0x50)?"4":
++            ((art&0x40)==0x40)?"3":
++            ((art&0x30)==0x30)?"2":
++            ((art&0x20)==0x20)?"1":
++            ((art&0x10)==0x10)?"0":"?");
++#ifdef DEBUG_AEC_REGS
++         (void) pci_read_config_byte(dev, 0x40, &art);
+          p += sprintf(p, "Active:         0x%02x", HIGH_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x41, &art);
++         (void) pci_read_config_byte(dev, 0x41, &art);
+          p += sprintf(p, "             0x%02x", HIGH_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x42, &art);
++         (void) pci_read_config_byte(dev, 0x42, &art);
+          p += sprintf(p, "            0x%02x", HIGH_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x43, &art);
++         (void) pci_read_config_byte(dev, 0x43, &art);
+          p += sprintf(p, "              0x%02x\n", HIGH_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x40, &art);
++         (void) pci_read_config_byte(dev, 0x40, &art);
+          p += sprintf(p, "Recovery:       0x%02x", LOW_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x41, &art);
++         (void) pci_read_config_byte(dev, 0x41, &art);
+          p += sprintf(p, "             0x%02x", LOW_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x42, &art);
++         (void) pci_read_config_byte(dev, 0x42, &art);
+          p += sprintf(p, "            0x%02x", LOW_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x43, &art);
++         (void) pci_read_config_byte(dev, 0x43, &art);
+          p += sprintf(p, "              0x%02x\n", LOW_4(art));
+-         (void) pci_read_config_byte(bmide_dev, 0x49, &uart);
++         (void) pci_read_config_byte(dev, 0x49, &uart);
+          p += sprintf(p, "reg49h = 0x%02x ", uart);
+-         (void) pci_read_config_byte(bmide_dev, 0x4a, &uart);
++         (void) pci_read_config_byte(dev, 0x4a, &uart);
+          p += sprintf(p, "reg4ah = 0x%02x\n", uart);
+-         break;
+-      default:
+-         break;
++#endif /* DEBUG_AEC_REGS */
++      }
+    }
+-
+    return p-buffer;/* => must be less than 4k! */
+ }
+ #endif   /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */
+ 
+ byte aec62xx_proc = 0;
+ 
+-#ifdef CONFIG_AEC62XX_TUNING
+-
+ struct chipset_bus_clock_list_entry {
+    byte      xfer_speed;
+-
+-   byte      chipset_settings_34;
+-   byte      ultra_settings_34;
+-
+-   byte      chipset_settings_33;
+-   byte      ultra_settings_33;
++   byte      chipset_settings;
++   byte      ultra_settings;
+ };
+ 
+-struct chipset_bus_clock_list_entry aec62xx_base [] = {
++struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-   {   XFER_UDMA_4,   0x41,   0x04,   0x31,   0x05   },
+-   {   XFER_UDMA_3,   0x41,   0x03,   0x31,   0x04   },
+-   {   XFER_UDMA_2,   0x41,   0x02,   0x31,   0x03   },
+-   {   XFER_UDMA_1,   0x41,   0x01,   0x31,   0x02   },
+-   {   XFER_UDMA_0,   0x41,   0x01,   0x31,   0x01   },
+-
+-   {   XFER_MW_DMA_2,   0x41,   0x00,   0x31,   0x00   },
+-   {   XFER_MW_DMA_1,   0x42,   0x00,   0x31,   0x00   },
+-   {   XFER_MW_DMA_0,   0x7a,   0x00,   0x0a,   0x00   },
++   {   XFER_UDMA_6,   0x31,   0x07   },
++   {   XFER_UDMA_5,   0x31,   0x06   },
++   {   XFER_UDMA_4,   0x31,   0x05   },
++   {   XFER_UDMA_3,   0x31,   0x04   },
++   {   XFER_UDMA_2,   0x31,   0x03   },
++   {   XFER_UDMA_1,   0x31,   0x02   },
++   {   XFER_UDMA_0,   0x31,   0x01   },
++
++   {   XFER_MW_DMA_2,   0x31,   0x00   },
++   {   XFER_MW_DMA_1,   0x31,   0x00   },
++   {   XFER_MW_DMA_0,   0x0a,   0x00   },
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+-   {   XFER_PIO_4,   0x41,   0x00,   0x31,   0x00   },
+-   {   XFER_PIO_3,   0x43,   0x00,   0x33,   0x00   },
+-   {   XFER_PIO_2,   0x78,   0x00,   0x08,   0x00   },
+-   {   XFER_PIO_1,   0x7a,   0x00,   0x0a,   0x00   },
+-   {   XFER_PIO_0,   0x70,   0x00,   0x00,   0x00   },
+-   {   0,      0x00,   0x00,   0x00,   0x00   }
++   {   XFER_PIO_4,   0x31,   0x00   },
++   {   XFER_PIO_3,   0x33,   0x00   },
++   {   XFER_PIO_2,   0x08,   0x00   },
++   {   XFER_PIO_1,   0x0a,   0x00   },
++   {   XFER_PIO_0,   0x00,   0x00   },
++   {   0,      0x00,   0x00   }
+ };
+ 
+-extern char *ide_xfer_verbose (byte xfer_rate);
++struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   {   XFER_UDMA_6,   0x41,   0x06   },
++   {   XFER_UDMA_5,   0x41,   0x05   },
++   {   XFER_UDMA_4,   0x41,   0x04   },
++   {   XFER_UDMA_3,   0x41,   0x03   },
++   {   XFER_UDMA_2,   0x41,   0x02   },
++   {   XFER_UDMA_1,   0x41,   0x01   },
++   {   XFER_UDMA_0,   0x41,   0x01   },
++
++   {   XFER_MW_DMA_2,   0x41,   0x00   },
++   {   XFER_MW_DMA_1,   0x42,   0x00   },
++   {   XFER_MW_DMA_0,   0x7a,   0x00   },
++#endif /* CONFIG_BLK_DEV_IDEDMA */
++   {   XFER_PIO_4,   0x41,   0x00   },
++   {   XFER_PIO_3,   0x43,   0x00   },
++   {   XFER_PIO_2,   0x78,   0x00   },
++   {   XFER_PIO_1,   0x7a,   0x00   },
++   {   XFER_PIO_0,   0x70,   0x00   },
++   {   0,      0x00,   0x00   }
++};
+ 
+ /*
+  * TO DO: active tuning and correction of cards without a bios.
+@@ -203,31 +257,73 @@
+ 
+ static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+ {
+-   int bus_speed = system_bus_clock();
+-
+    for ( ; chipset_table->xfer_speed ; chipset_table++)
+       if (chipset_table->xfer_speed == speed) {
+-         return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
++         return chipset_table->chipset_settings;
+       }
+-   return 0x00;
++   return chipset_table->chipset_settings;
+ }
+ 
+ static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+ {
+-   int bus_speed = system_bus_clock();
+-
+    for ( ; chipset_table->xfer_speed ; chipset_table++)
+       if (chipset_table->xfer_speed == speed) {
+-         return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
++         return chipset_table->ultra_settings;
+       }
+-   return 0x00;
++   return chipset_table->ultra_settings;
++}
++
++static byte aec62xx_ratemask (ide_drive_t *drive)
++{
++   struct pci_dev *dev   = HWIF(drive)->pci_dev;
++   byte mode      = 0x00;
++
++   if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
++      mode |= 0x01;
++   } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP860) ||
++         (dev->device == PCI_DEVICE_ID_ARTOP_ATP860R)) {
++      mode |= 0x02;
++   } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
++         (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
++      u32 bmide = pci_resource_start(dev, 4);
++      if (IN_BYTE(bmide+2) & 0x10)
++         mode |= 0x04;
++      else
++         mode |= 0x03;
++   }
++   if (!eighty_ninty_three(drive)) {
++      mode &= ~0xFE;
++      mode |= 0x01;
++   }
++   return (mode &= ~0xF8);
++}
++
++static byte aec62xx_ratefilter (ide_drive_t *drive, byte speed)
++{
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   byte mode = aec62xx_ratemask(drive);
++
++   switch(mode) {
++      case 0x04:   while (speed > XFER_UDMA_6) speed--; break;
++      case 0x03:   while (speed > XFER_UDMA_5) speed--; break;
++      case 0x02:   while (speed > XFER_UDMA_4) speed--; break;
++      case 0x01:   while (speed > XFER_UDMA_2) speed--; break;
++      case 0x00:
++      default:   while (speed > XFER_MW_DMA_2) speed--; break;
++         break;
++   }
++#else
++   while (speed > XFER_PIO_4) speed--;
++#endif /* CONFIG_BLK_DEV_IDEDMA */
++//   printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed);
++   return speed;
+ }
+ 
+-static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
++static int aec6210_tune_chipset (ide_drive_t *drive, byte xferspeed)
+ {
+    ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev   = hwif->pci_dev;
+-   int err         = 0;
++   byte speed      = aec62xx_ratefilter(drive, xferspeed);
+    unsigned short d_conf   = 0x0000;
+    byte ultra      = 0x00;
+    byte ultra_conf      = 0x00;
+@@ -236,11 +332,10 @@
+    byte tmp2      = 0x00;
+    unsigned long flags;
+ 
+-   __save_flags(flags);   /* local CPU only */
+-   __cli();      /* local CPU only */
+-
++   local_irq_save(flags);
+    pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
+-   tmp0 = pci_bus_clock_list(speed, aec62xx_base);
++   tmp0 = pci_bus_clock_list(speed,
++      (struct chipset_bus_clock_list_entry *) dev->driver_data);
+    SPLIT_BYTE(tmp0,tmp1,tmp2);
+    MAKE_WORD(d_conf,tmp1,tmp2);
+    pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
+@@ -249,23 +344,21 @@
+    tmp2 = 0x00;
+    pci_read_config_byte(dev, 0x54, &ultra);
+    tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
+-   ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
++   ultra_conf = pci_bus_clock_list_ultra(speed,
++      (struct chipset_bus_clock_list_entry *) dev->driver_data);
+    tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
+    pci_write_config_byte(dev, 0x54, tmp2);
+-
+-   __restore_flags(flags);   /* local CPU only */
+-
+-   err = ide_config_drive_speed(drive, speed);
+-   return(err);
++   local_irq_restore(flags);
++   return(ide_config_drive_speed(drive, speed));
+ }
+ 
+-static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
++static int aec6260_tune_chipset (ide_drive_t *drive, byte xferspeed)
+ {
+    ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev   = hwif->pci_dev;
+    byte unit      = (drive->select.b.unit & 0x01);
+    byte ultra_pci      = hwif->channel ? 0x45 : 0x44;
+-   int err         = 0;
++   byte speed      = aec62xx_ratefilter(drive, xferspeed);
+    byte drive_conf      = 0x00;
+    byte ultra_conf      = 0x00;
+    byte ultra      = 0x00;
+@@ -273,143 +366,91 @@
+    byte tmp2      = 0x00;
+    unsigned long flags;
+ 
+-   __save_flags(flags);   /* local CPU only */
+-   __cli();      /* local CPU only */
+-
++   local_irq_save(flags);
+    pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
+-   drive_conf = pci_bus_clock_list(speed, aec62xx_base);
++   drive_conf = pci_bus_clock_list(speed,
++      (struct chipset_bus_clock_list_entry *) dev->driver_data);
+    pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
+ 
+    pci_read_config_byte(dev, ultra_pci, &ultra);
+    tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
+-   ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
++   ultra_conf = pci_bus_clock_list_ultra(speed,
++      (struct chipset_bus_clock_list_entry *) dev->driver_data);
+    tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
+    pci_write_config_byte(dev, ultra_pci, tmp2);
+-   __restore_flags(flags);   /* local CPU only */
+-
+-   if (!drive->init_speed)
+-      drive->init_speed = speed;
+-
+-   err = ide_config_drive_speed(drive, speed);
+-   drive->current_speed = speed;
+-   return(err);
++   local_irq_restore(flags);
++   return(ide_config_drive_speed(drive, speed));
+ }
+ 
+-
+ static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed)
+ {
+-   if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+-      return ((int) aec6210_tune_chipset(drive, speed));
+-   } else {
+-      return ((int) aec6260_tune_chipset(drive, speed));
++   switch (HWIF(drive)->pci_dev->device) {
++      case PCI_DEVICE_ID_ARTOP_ATP865:
++      case PCI_DEVICE_ID_ARTOP_ATP865R:
++      case PCI_DEVICE_ID_ARTOP_ATP860:
++      case PCI_DEVICE_ID_ARTOP_ATP860R:
++         return ((int) aec6260_tune_chipset(drive, speed));
++      case PCI_DEVICE_ID_ARTOP_ATP850UF:
++         return ((int) aec6210_tune_chipset(drive, speed));
++      default:
++         return -1;
+    }
+ }
+ 
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
++static int config_chipset_for_dma (ide_drive_t *drive)
+ {
+    struct hd_driveid *id   = drive->id;
+-   ide_hwif_t *hwif   = HWIF(drive);
+-   byte unit      = (drive->select.b.unit & 0x01);
+-   unsigned long dma_base   = hwif->dma_base;
+-   byte speed      = -1;
+-
+-   if (drive->media != ide_disk)
+-      return ((int) ide_dma_off_quietly);
+-
+-   if (((id->dma_ultra & 0x0010) ||
+-        (id->dma_ultra & 0x0008) ||
+-        (id->dma_ultra & 0x0004)) && (ultra)) {
+-      speed = XFER_UDMA_2;
+-   } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+-      speed = XFER_UDMA_1;
+-   } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+-      speed = XFER_UDMA_0;
+-   } else if (id->dma_mword & 0x0004) {
+-      speed = XFER_MW_DMA_2;
+-   } else if (id->dma_mword & 0x0002) {
+-      speed = XFER_MW_DMA_1;
+-   } else if (id->dma_mword & 0x0001) {
+-      speed = XFER_MW_DMA_0;
+-   } else if (id->dma_1word & 0x0004) {
+-      speed = XFER_SW_DMA_2;
+-   } else if (id->dma_1word & 0x0002) {
+-      speed = XFER_SW_DMA_1;
+-   } else if (id->dma_1word & 0x0001) {
+-      speed = XFER_SW_DMA_0;
+-   } else {
+-       return ((int) ide_dma_off_quietly);
+-    }
+-
+-   outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+-   (void) aec6210_tune_chipset(drive, speed);
+-
+-   return ((int)   ((id->dma_ultra >> 11) & 3) ? ide_dma_off :
+-         ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+-         ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+-         ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+-                       ide_dma_off_quietly);
+-}
+-
+-static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra)
+-{
+-   struct hd_driveid *id   = drive->id;
+-   ide_hwif_t *hwif   = HWIF(drive);
+-   byte unit      = (drive->select.b.unit & 0x01);
+-   unsigned long dma_base   = hwif->dma_base;
+-   byte speed      = -1;
+-   byte ultra66      = eighty_ninty_three(drive);
++   byte mode      = aec62xx_ratemask(drive);
++   byte speed;
+ 
+    if (drive->media != ide_disk)
+       return ((int) ide_dma_off_quietly);
+-
+-   if ((id->dma_ultra & 0x0010) && (ultra) && (ultra66)) {
+-      speed = XFER_UDMA_4;
+-   } else if ((id->dma_ultra & 0x0008) && (ultra) && (ultra66)) {
+-      speed = XFER_UDMA_3;
+-   } else if ((id->dma_ultra & 0x0004) && (ultra)) {
+-      speed = XFER_UDMA_2;
+-   } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+-      speed = XFER_UDMA_1;
+-   } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+-      speed = XFER_UDMA_0;
+-   } else if (id->dma_mword & 0x0004) {
+-      speed = XFER_MW_DMA_2;
+-   } else if (id->dma_mword & 0x0002) {
+-      speed = XFER_MW_DMA_1;
+-   } else if (id->dma_mword & 0x0001) {
+-      speed = XFER_MW_DMA_0;
+-   } else if (id->dma_1word & 0x0004) {
+-      speed = XFER_SW_DMA_2;
+-   } else if (id->dma_1word & 0x0002) {
+-      speed = XFER_SW_DMA_1;
+-   } else if (id->dma_1word & 0x0001) {
+-      speed = XFER_SW_DMA_0;
+-   } else {
+-      return ((int) ide_dma_off_quietly);
++   
++   switch(mode) {
++      case 0x04:
++         if (id->dma_ultra & 0x0040)
++            { speed = XFER_UDMA_6; break; }
++      case 0x03:
++         if (id->dma_ultra & 0x0020)
++            { speed = XFER_UDMA_5; break; }
++      case 0x02:
++         if (id->dma_ultra & 0x0010)
++            { speed = XFER_UDMA_4; break; }
++         if (id->dma_ultra & 0x0008)
++            { speed = XFER_UDMA_3; break; }
++      case 0x01:
++         if (id->dma_ultra & 0x0004)
++            { speed = XFER_UDMA_2; break; }
++         if (id->dma_ultra & 0x0002)
++            { speed = XFER_UDMA_1; break; }
++         if (id->dma_ultra & 0x0001)
++            { speed = XFER_UDMA_0; break; }
++      case 0x00:
++         if (id->dma_mword & 0x0004)
++            { speed = XFER_MW_DMA_2; break; }
++         if (id->dma_mword & 0x0002)
++            { speed = XFER_MW_DMA_1; break; }
++         if (id->dma_mword & 0x0001)
++            { speed = XFER_MW_DMA_0; break; }
++         if (id->dma_1word & 0x0004)
++            { speed = XFER_SW_DMA_2; break; }
++         if (id->dma_1word & 0x0002)
++            { speed = XFER_SW_DMA_1; break; }
++         if (id->dma_1word & 0x0001)
++            { speed = XFER_SW_DMA_0; break; }
++      default:
++         return ((int) ide_dma_off_quietly);
+    }
+ 
+-   outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+-   (void) aec6260_tune_chipset(drive, speed);
++   (void) aec62xx_tune_chipset(drive, speed);
+ 
+-   return ((int)   ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
++   return ((int)   ((id->dma_ultra >> 11) & 15) ? ide_dma_on :
+          ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+          ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+          ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+                        ide_dma_off_quietly);
+-}
+-
+-static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+-{
+-   switch(HWIF(drive)->pci_dev->device) {   
+-      case PCI_DEVICE_ID_ARTOP_ATP850UF:
+-         return config_aec6210_chipset_for_dma(drive, ultra);
+-      case PCI_DEVICE_ID_ARTOP_ATP860:
+-      case PCI_DEVICE_ID_ARTOP_ATP860R:
+-         return config_aec6260_chipset_for_dma(drive, ultra);
+-      default:
+-         return ((int) ide_dma_off_quietly);
+-   }
++//   return ((int) ide_dma_on);
+ }
+ 
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+@@ -427,16 +468,7 @@
+       case 1:      speed = XFER_PIO_1; break;
+       default:   speed = XFER_PIO_0; break;
+    }
+-
+-   switch(HWIF(drive)->pci_dev->device) {
+-      case PCI_DEVICE_ID_ARTOP_ATP850UF:
+-         (void) aec6210_tune_chipset(drive, speed);
+-      case PCI_DEVICE_ID_ARTOP_ATP860:
+-      case PCI_DEVICE_ID_ARTOP_ATP860R:
+-         (void) aec6260_tune_chipset(drive, speed);
+-      default:
+-         break;
+-        }
++   (void) aec62xx_tune_chipset(drive, speed);
+ }
+ 
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+@@ -453,9 +485,9 @@
+       }
+       dma_func = ide_dma_off_quietly;
+       if (id->field_valid & 4) {
+-         if (id->dma_ultra & 0x001F) {
++         if (id->dma_ultra & 0x007F) {
+             /* Force if Capable UltraDMA */
+-            dma_func = config_chipset_for_dma(drive, 1);
++            dma_func = config_chipset_for_dma(drive);
+             if ((id->field_valid & 2) &&
+                 (dma_func != ide_dma_on))
+                goto try_dma_modes;
+@@ -465,7 +497,7 @@
+          if ((id->dma_mword & 0x0007) ||
+              (id->dma_1word & 0x0007)) {
+             /* Force if Capable regular DMA modes */
+-            dma_func = config_chipset_for_dma(drive, 0);
++            dma_func = config_chipset_for_dma(drive);
+             if (dma_func != ide_dma_on)
+                goto no_dma_set;
+          }
+@@ -474,7 +506,7 @@
+             goto no_dma_set;
+          }
+          /* Consult the list of known "good" drives */
+-         dma_func = config_chipset_for_dma(drive, 0);
++         dma_func = config_chipset_for_dma(drive);
+          if (dma_func != ide_dma_on)
+             goto no_dma_set;
+       } else {
+@@ -494,49 +526,81 @@
+  */
+ int aec62xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+ {
++   ide_hwif_t *hwif   = HWIF(drive);
++   struct pci_dev *dev   = hwif->pci_dev;
++
+    switch (func) {
+       case ide_dma_check:
+          return config_drive_xfer_rate(drive);
+       case ide_dma_lostirq:
+       case ide_dma_timeout:
+-         switch(HWIF(drive)->pci_dev->device) {
++         switch(dev->device) {
+             case PCI_DEVICE_ID_ARTOP_ATP860:
+             case PCI_DEVICE_ID_ARTOP_ATP860R:
+-//               {
+-//                  int i = 0;
+-//                  byte reg49h = 0;
+-//                  pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h);
+-//                  for (i=0;i<256;i++)
+-//                     pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10);
+-//                  pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10);
+-//               }
+-//               return 0;
++            case PCI_DEVICE_ID_ARTOP_ATP865:
++            case PCI_DEVICE_ID_ARTOP_ATP865R:
++               printk(" AEC62XX time out ");
++#if 0
++               {
++                  int i = 0;
++                  byte reg49h = 0;
++                  pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h);
++                  for (i=0;i<256;i++)
++                     pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10);
++                  pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10);
++               }
++               return 0;
++#endif
+             default:
+                break;
+          }
+       default:
+          break;
+    }
++#if 0
++   {
++      ide_hwif_t *hwif   = HWIF(drive);
++      struct pci_dev *dev   = hwif->pci_dev;
++      unsigned long dma_base   = hwif->dma_base;
++      byte tmp1      = 0x00;
++      byte tmp2      = 0x00;
++
++      pci_read_config_byte(dev, 0x44, &tmp1);
++      pci_read_config_byte(dev, 0x45, &tmp2);
++      printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2);
++      if (hwif->channel)
++         dma_base -= 0x08;
++      tmp1=IN_BYTE(dma_base+2) & 0x10;
++      printk(" AEC6280 133=%x ",tmp1);
++   }
++#endif
+    return ide_dmaproc(func, drive);   /* use standard DMA stuff */
+ }
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+-#endif /* CONFIG_AEC62XX_TUNING */
+ 
+ unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name)
+ {
++   int bus_speed = system_bus_clock();
++
+    if (dev->resource[PCI_ROM_RESOURCE].start) {
+       pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+       printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
+    }
+ 
++   aec_devs[n_aec_devs++] = dev;
++
+ #if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
+    if (!aec62xx_proc) {
+       aec62xx_proc = 1;
+-      bmide_dev = dev;
+       aec62xx_display_info = &aec62xx_get_info;
+    }
+ #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
+ 
++   if (bus_speed <= 33)
++      dev->driver_data = (void *) aec6xxx_33_base;
++   else
++      dev->driver_data = (void *) aec6xxx_34_base;
++
+    return dev->irq;
+ }
+ 
+@@ -551,32 +615,56 @@
+ 
+ void __init ide_init_aec62xx (ide_hwif_t *hwif)
+ {
+-#ifdef CONFIG_AEC62XX_TUNING
++   hwif->autodma = 0;
+    hwif->tuneproc = &aec62xx_tune_drive;
+    hwif->speedproc = &aec62xx_tune_chipset;
+-#ifdef CONFIG_BLK_DEV_IDEDMA
+-   if (hwif->dma_base)
+-      hwif->dmaproc = &aec62xx_dmaproc;
+-#else /* !CONFIG_BLK_DEV_IDEDMA */
+    hwif->drives[0].autotune = 1;
+    hwif->drives[1].autotune = 1;
++
++   if (!hwif->dma_base)
++      return;
++
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   hwif->dmaproc = &aec62xx_dmaproc;
++#ifdef CONFIG_IDEDMA_AUTO
++   if (!noautodma)
++      hwif->autodma = 1;
++#endif /* CONFIG_IDEDMA_AUTO */
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+-#endif /* CONFIG_AEC62XX_TUNING */
++
++
+ }
+ 
+ void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
+ {
+-#ifdef CONFIG_AEC62XX_TUNING
++   struct pci_dev *dev   = hwif->pci_dev;
++   byte reg54h      = 0;
+    unsigned long flags;
+-   byte reg54h = 0;
+ 
+-   __save_flags(flags);   /* local CPU only */
+-   __cli();      /* local CPU only */
++   spin_lock_irqsave(&io_request_lock, flags);
++   pci_read_config_byte(dev, 0x54, ®54h);
++   pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
++   spin_unlock_irqrestore(&io_request_lock, flags);
++   ide_setup_dma(hwif, dmabase, 8);
++}
+ 
+-   pci_read_config_byte(hwif->pci_dev, 0x54, ®54h);
+-   pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
++extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+ 
+-   __restore_flags(flags);   /* local CPU only */
+-#endif /* CONFIG_AEC62XX_TUNING */
+-   ide_setup_dma(hwif, dmabase, 8);
++void __init fixup_device_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d)
++{
++   u32 bar4reg = pci_resource_start(dev, 4);
++
++   if (IN_BYTE(bar4reg+2) & 0x10) {
++      strcpy(d->name, "AEC6880");
++      if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
++         strcpy(d->name, "AEC6880R");
++   } else {
++      strcpy(d->name, "AEC6280");
++      if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
++         strcpy(d->name, "AEC6280R");
++   }
++
++   printk("%s: IDE controller on PCI bus %02x dev %02x\n",
++      d->name, dev->bus->number, dev->devfn);
++   ide_setup_pci_device(dev, d);
+ }
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/ali14xx.c linux-2.4.19-p8-ac1/drivers/ide/ali14xx.c
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/ali14xx.c   Sun Jul 15 16:22:23 2001
++++ linux-2.4.19-p8-ac1/drivers/ide/ali14xx.c   Fri May 10 05:15:51 2002
+@@ -95,7 +95,7 @@
+ static inline byte inReg (byte reg)
+ {
+    outb_p(reg, regPort);
+-   return inb(dataPort);
++   return IN_BYTE(dataPort);
+ }
+ 
+ /*
+@@ -137,15 +137,14 @@
+ 
+    /* stuff timing parameters into controller registers */
+    driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+-   save_flags(flags);   /* all CPUs */
+-   cli();         /* all CPUs */
++   spin_lock_irqsave(&io_request_lock, flags);
+    outb_p(regOn, basePort);
+    outReg(param1, regTab[driveNum].reg1);
+    outReg(param2, regTab[driveNum].reg2);
+    outReg(param3, regTab[driveNum].reg3);
+    outReg(param4, regTab[driveNum].reg4);
+    outb_p(regOff, basePort);
+-   restore_flags(flags);   /* all CPUs */
++   spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ 
+ /*
+@@ -157,19 +156,18 @@
+    byte t;
+    unsigned long flags;
+ 
+-   __save_flags(flags);   /* local CPU only */
+-   __cli();      /* local CPU only */
++   local_irq_save(flags);
+    for (i = 0; i < ALI_NUM_PORTS; ++i) {
+       basePort = ports[i];
+-      regOff = inb(basePort);
++      regOff = IN_BYTE(basePort);
+       for (regOn = 0x30; regOn <= 0x33; ++regOn) {
+          outb_p(regOn, basePort);
+-         if (inb(basePort) == regOn) {
++         if (IN_BYTE(basePort) == regOn) {
+             regPort = basePort + 4;
+             dataPort = basePort + 8;
+             t = inReg(0) & 0xf0;
+             outb_p(regOff, basePort);
+-            __restore_flags(flags);   /* local CPU only */
++            local_irq_restore(flags);
+             if (t != 0x50)
+                return 0;
+             return 1;  /* success */
+@@ -177,7 +175,7 @@
+       }
+       outb_p(regOff, basePort);
+    }
+-   __restore_flags(flags);   /* local CPU only */
++   local_irq_restore(flags);
+    return 0;
+ }
+ 
+@@ -189,15 +187,14 @@
+    byte t;
+    unsigned long flags;
+ 
+-   __save_flags(flags);   /* local CPU only */
+-   __cli();      /* local CPU only */
++   local_irq_save(flags);
+    outb_p(regOn, basePort);
+    for (p = initData; p->reg != 0; ++p)
+       outReg(p->data, p->reg);
+    outb_p(0x01, regPort);
+-   t = inb(regPort) & 0x01;
++   t = IN_BYTE(regPort) & 0x01;
+    outb_p(regOff, basePort);
+-   __restore_flags(flags);   /* local CPU only */
++   local_irq_restore(flags);
+    return t;
+ }
+ 
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/alim15x3.c linux-2.4.19-p8-ac1/drivers/ide/alim15x3.c
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/alim15x3.c   Fri May 10 10:10:21 2002
++++ linux-2.4.19-p8-ac1/drivers/ide/alim15x3.c   Fri May 10 05:15:51 2002
+@@ -89,8 +89,8 @@
+     * at that point bibma+0x2 et bibma+0xa are byte
+     * registers to investigate:
+     */
+-   c0 = inb((unsigned short)bibma + 0x02);
+-   c1 = inb((unsigned short)bibma + 0x0a);
++   c0 = IN_BYTE((unsigned short)bibma + 0x02);
++   c1 = IN_BYTE((unsigned short)bibma + 0x0a);
+ 
+    p += sprintf(p,
+       "\n                                Ali M15x3 Chipset.\n");
+@@ -112,16 +112,20 @@
+       (reg53h & 0x80) ? " OVERRD." : "." );
+ 
+    p += sprintf(p,
+-      "-------------------primary channel-------------------secondary channel---------\n\n");
++      "-------------------primary channel"
++      "-------------------secondary channel"
++      "---------\n\n");
+ 
+    pci_read_config_byte(bmide_dev, 0x09, ®53h);
+    p += sprintf(p,
+-      "channel status:       %s                               %s\n",
++      "channel status:       %s"
++      "                               %s\n",
+       (reg53h & 0x20) ? "On " : "Off",
+       (reg53h & 0x10) ? "On " : "Off" );
+ 
+    p += sprintf(p,
+-      "both channels togth:  %s                               %s\n",
++      "both channels togth:  %s"
++      "                               %s\n",
+       (c0&0x80) ? "No " : "Yes",
+       (c1&0x80) ? "No " : "Yes" );
+ 
+@@ -134,24 +138,29 @@
+    pci_read_config_byte(bmide_dev, 0x58, ®5xh);
+    pci_read_config_byte(bmide_dev, 0x5c, ®5yh);
+    p += sprintf(p,
+-      "Add. Setup Timing:    %dT                                %dT\n",
++      "Add. Setup Timing:    %dT"
++      "                                %dT\n",
+       (reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
+       (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
+ 
+    pci_read_config_byte(bmide_dev, 0x59, ®5xh);
+    pci_read_config_byte(bmide_dev, 0x5d, ®5yh);
+    p += sprintf(p,
+-      "Command Act. Count:   %dT                                %dT\n"
+-      "Command Rec. Count:   %dT                               %dT\n\n",
++      "Command Act. Count:   %dT"
++      "                                %dT\n"
++      "Command Rec. Count:   %dT"
++      "                               %dT\n\n",
+       (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+       (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, 
+       (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+       (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
+ 
+    p += sprintf(p,
+-      "----------------drive0-----------drive1------------drive0-----------drive1------\n\n");
++      "----------------drive0-----------drive1"
++      "------------drive0-----------drive1------\n\n");
+    p += sprintf(p,
+-      "DMA enabled:      %s              %s               %s              %s\n",
++      "DMA enabled:      %s              %s"
++      "               %s              %s\n",
+       (c0&0x20) ? "Yes" : "No ",
+       (c0&0x40) ? "Yes" : "No ",
+       (c1&0x20) ? "Yes" : "No ",
+@@ -159,7 +168,8 @@
+ 
+    pci_read_config_byte(bmide_dev, 0x54, ®5xh);
+    pci_read_config_byte(bmide_dev, 0x55, ®5yh);
+-   q = "FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n";
++   q = "FIFO threshold:   %2d Words         %2d Words"
++      "          %2d Words         %2d Words\n";
+    if (rev < 0xc1) {
+       if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {
+          p += sprintf(p, q, 8, 8, 8, 8);
+@@ -180,7 +190,8 @@
+ 
+ #if 0
+    p += sprintf(p, 
+-      "FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n",
++      "FIFO threshold:   %2d Words         %2d Words"
++      "          %2d Words         %2d Words\n",
+       (reg5xh & 0x03) + 12,
+       ((reg5xh & 0x30)>>4) + 12,
+       (reg5yh & 0x03) + 12,
+@@ -200,9 +211,12 @@
+    pci_read_config_byte(bmide_dev, 0x5f, ®5yh1);
+ 
+    p += sprintf(p,/*
+-      "------------------drive0-----------drive1------------drive0-----------drive1------\n")*/
+-      "Dt RW act. Cnt    %2dT              %2dT               %2dT              %2dT\n"
+-      "Dt RW rec. Cnt    %2dT              %2dT               %2dT              %2dT\n\n",
++      "------------------drive0-----------drive1"
++      "------------drive0-----------drive1------\n")*/
++      "Dt RW act. Cnt    %2dT              %2dT"
++      "               %2dT              %2dT\n"
++      "Dt RW rec. Cnt    %2dT              %2dT"
++      "               %2dT              %2dT\n\n",
+       (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+       (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
+       (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
+@@ -213,13 +227,16 @@
+       (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
+ 
+    p += sprintf(p,
+-      "-----------------------------------UDMA Timings--------------------------------\n\n");
++      "-----------------------------------UDMA Timings"
++      "--------------------------------\n\n");
+ 
+    pci_read_config_byte(bmide_dev, 0x56, ®5xh);
+    pci_read_config_byte(bmide_dev, 0x57, ®5yh);
+    p += sprintf(p,
+-      "UDMA:             %s               %s                %s               %s\n"
+-      "UDMA timings:     %s             %s              %s             %s\n\n",
++      "UDMA:             %s               %s"
++      "                %s               %s\n"
++      "UDMA timings:     %s             %s"
++      "              %s             %s\n\n",
+       (reg5xh & 0x08) ? "OK" : "No",
+       (reg5xh & 0x80) ? "OK" : "No",
+       (reg5yh & 0x08) ? "OK" : "No",
+@@ -272,21 +289,20 @@
+       if (r_clc >= 16)
+          r_clc = 0;
+    }
+-   __save_flags(flags);
+-   __cli();
++   local_irq_save(flags);
+    
+    /* 
+     * PIO mode => ATA FIFO on, ATAPI FIFO off
+     */
+    pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);
+    if (drive->media==ide_disk) {
+-      if (hwif->index) {
++      if (hwif->channel) {
+          pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);
+       } else {
+          pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);
+       }
+    } else {
+-      if (hwif->index) {
++      if (hwif->channel) {
+          pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);
+       } else {
+          pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);
+@@ -295,7 +311,7 @@
+    
+    pci_write_config_byte(dev, port, s_clc);
+    pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
+-   __restore_flags(flags);
++   local_irq_restore(flags);
+ 
+    /*
+     * setup   active  rec
+@@ -309,14 +325,79 @@
+ 
+ }
+ 
+-static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed)
++static byte ali15x3_can_ultra (ide_drive_t *drive)
+ {
+-   ide_hwif_t *hwif = HWIF(drive);
++#ifndef CONFIG_WDC_ALI15X3
++   struct hd_driveid *id   = drive->id;
++#endif /* CONFIG_WDC_ALI15X3 */
++
++   if (m5229_revision <= 0x20) {
++      return 0;
++   } else if ((m5229_revision < 0xC2) &&
++#ifndef CONFIG_WDC_ALI15X3
++         ((chip_is_1543c_e && strstr(id->model, "WDC ")) ||
++          (drive->media!=ide_disk))) {
++#else /* CONFIG_WDC_ALI15X3 */
++         (drive->media!=ide_disk)) {
++#endif /* CONFIG_WDC_ALI15X3 */
++      return 0;
++   } else {
++      return 1;
++   }
++}
++
++static byte ali15x3_ratemask (ide_drive_t *drive)
++{
++//   struct pci_dev *dev   = HWIF(drive)->pci_dev;
++   byte mode      = 0x00;
++   byte can_ultra      = ali15x3_can_ultra(drive);
++
++   if ((m5229_revision >= 0xC4) && (can_ultra)) {
++      mode |= 0x03;
++   } else if ((m5229_revision >= 0xC2) && (can_ultra)) {
++      mode |= 0x02;
++   } else if (can_ultra) {
++      mode |= 0x01;
++   } else {
++      return (mode &= ~0xFF);
++   }
++
++   if (!eighty_ninty_three(drive)) {
++      mode &= ~0xFE;
++      mode |= 0x01;
++   }
++   return (mode &= ~0xF8);
++}
++
++static byte ali15x3_ratefilter (ide_drive_t *drive, byte speed)
++{
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   byte mode = ali15x3_ratemask(drive);
++
++   switch(mode) {
++      case 0x04:   while (speed > XFER_UDMA_6) speed--; break;
++      case 0x03:   while (speed > XFER_UDMA_5) speed--; break;
++      case 0x02:   while (speed > XFER_UDMA_4) speed--; break;
++      case 0x01:   while (speed > XFER_UDMA_2) speed--; break;
++      case 0x00:
++      default:   while (speed > XFER_MW_DMA_2) speed--; break;
++         break;
++   }
++#else
++   while (speed > XFER_PIO_4) speed--;
++#endif /* CONFIG_BLK_DEV_IDEDMA */
++//   printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed);
++   return speed;
++}
++
++static int ali15x3_tune_chipset (ide_drive_t *drive, byte xferspeed)
++{
++   ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev   = hwif->pci_dev;
++   byte speed      = ali15x3_ratefilter(drive, xferspeed);
+    byte unit      = (drive->select.b.unit & 0x01);
+    byte tmpbyte      = 0x00;
+-   int m5229_udma      = hwif->channel? 0x57 : 0x56;
+-   int err         = 0;
++   int m5229_udma      = (hwif->channel) ? 0x57 : 0x56;
+ 
+    if (speed < XFER_UDMA_0) {
+       byte ultra_enable   = (unit) ? 0x7f : 0xf7;
+@@ -326,18 +407,11 @@
+       pci_read_config_byte(dev, m5229_udma, &tmpbyte);
+       tmpbyte &= ultra_enable;
+       pci_write_config_byte(dev, m5229_udma, tmpbyte);
+-   }
+-
+-   err = ide_config_drive_speed(drive, speed);
+ 
++      if (speed < XFER_SW_DMA_0)
++         ali15x3_tune_drive(drive, speed);
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-   if (speed >= XFER_SW_DMA_0) {
+-      unsigned long dma_base = hwif->dma_base;
+-
+-      outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+-   }
+-
+-   if (speed >= XFER_UDMA_0) {
++   } else {
+       pci_read_config_byte(dev, m5229_udma, &tmpbyte);
+       tmpbyte &= (0x0f << ((1-unit) << 2));
+       /*
+@@ -350,89 +424,58 @@
+          tmpbyte |= 1;
+          pci_write_config_byte(dev, 0x4b, tmpbyte);
+       }
+-   }
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+-
+-   drive->current_speed = speed;
+-
+-   return (err);
+-}
+-
+-static void config_chipset_for_pio (ide_drive_t *drive)
+-{
+-   ali15x3_tune_drive(drive, 5);
++   }
++   return (ide_config_drive_speed(drive, speed));
+ }
+ 
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33)
++static int config_chipset_for_dma (ide_drive_t *drive)
+ {
+    struct hd_driveid *id   = drive->id;
+-   byte speed      = 0x00;
+-   byte ultra66      = eighty_ninty_three(drive);
+-   byte ultra100      = (m5229_revision>=0xc4) ? 1 : 0;
+-   int  rval;
+-
+-   if ((id->dma_ultra & 0x0020) && (ultra100) && (ultra66) && (ultra33)) {
+-      speed = XFER_UDMA_5;
+-   } else if ((id->dma_ultra & 0x0010) && (ultra66) && (ultra33)) {
+-      speed = XFER_UDMA_4;
+-   } else if ((id->dma_ultra & 0x0008) && (ultra66) && (ultra33)) {
+-      speed = XFER_UDMA_3;
+-   } else if ((id->dma_ultra & 0x0004) && (ultra33)) {
+-      speed = XFER_UDMA_2;
+-   } else if ((id->dma_ultra & 0x0002) && (ultra33)) {
+-      speed = XFER_UDMA_1;
+-   } else if ((id->dma_ultra & 0x0001) && (ultra33)) {
+-      speed = XFER_UDMA_0;
+-   } else if (id->dma_mword & 0x0004) {
+-      speed = XFER_MW_DMA_2;
+-   } else if (id->dma_mword & 0x0002) {
+-      speed = XFER_MW_DMA_1;
+-   } else if (id->dma_mword & 0x0001) {
+-      speed = XFER_MW_DMA_0;
+-   } else if (id->dma_1word & 0x0004) {
+-      speed = XFER_SW_DMA_2;
+-   } else if (id->dma_1word & 0x0002) {
+-      speed = XFER_SW_DMA_1;
+-   } else if (id->dma_1word & 0x0001) {
+-      speed = XFER_SW_DMA_0;
+-   } else {
+-      return ((int) ide_dma_off_quietly);
++   byte mode      = ali15x3_ratemask(drive);
++   byte speed      = 0;
++
++   switch(mode) {
++      case 0x03:
++         if (id->dma_ultra & 0x0020)
++            { speed = XFER_UDMA_5; break; }
++      case 0x02:
++         if (id->dma_ultra & 0x0010)
++            { speed = XFER_UDMA_4; break; }
++         if (id->dma_ultra & 0x0008)
++            { speed = XFER_UDMA_3; break; }
++      case 0x01:
++         if (id->dma_ultra & 0x0004)
++            { speed = XFER_UDMA_2; break; }
++         if (id->dma_ultra & 0x0002)
++            { speed = XFER_UDMA_1; break; }
++         if (id->dma_ultra & 0x0001)
++            { speed = XFER_UDMA_0; break; }
++      case 0x00:
++         if (id->dma_mword & 0x0004)
++            { speed = XFER_MW_DMA_2; break; }
++         if (id->dma_mword & 0x0002)
++            { speed = XFER_MW_DMA_1; break; }
++         if (id->dma_mword & 0x0001)
++            { speed = XFER_MW_DMA_0; break; }
++         if (id->dma_1word & 0x0004)
++            { speed = XFER_SW_DMA_2; break; }
++         if (id->dma_1word & 0x0002)
++            { speed = XFER_SW_DMA_1; break; }
++         if (id->dma_1word & 0x0001)
++            { speed = XFER_SW_DMA_0; break; }
++      default:
++         return ((int) ide_dma_off_quietly);
+    }
+ 
+    (void) ali15x3_tune_chipset(drive, speed);
+-
+-   if (!drive->init_speed)
+-      drive->init_speed = speed;
+-
+-   rval = (int)(   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
++//   return ((int)   (dma) ? ide_dma_on : ide_dma_off_quietly);
++   return ((int)   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+          ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+          ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+          ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+                        ide_dma_off_quietly);
+-
+-   return rval;
+-}
+-
+-static byte ali15x3_can_ultra (ide_drive_t *drive)
+-{
+-#ifndef CONFIG_WDC_ALI15X3
+-   struct hd_driveid *id   = drive->id;
+-#endif /* CONFIG_WDC_ALI15X3 */
+-
+-   if (m5229_revision <= 0x20) {
+-      return 0;
+-   } else if ((m5229_revision < 0xC2) &&
+-#ifndef CONFIG_WDC_ALI15X3
+-         ((chip_is_1543c_e && strstr(id->model, "WDC ")) ||
+-          (drive->media!=ide_disk))) {
+-#else /* CONFIG_WDC_ALI15X3 */
+-         (drive->media!=ide_disk)) {
+-#endif /* CONFIG_WDC_ALI15X3 */
+-      return 0;
+-   } else {
+-      return 1;
+-   }
+ }
+ 
+ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
+@@ -440,11 +483,12 @@
+    struct hd_driveid *id      = drive->id;
+    ide_hwif_t *hwif      = HWIF(drive);
+    ide_dma_action_t dma_func   = ide_dma_on;
+-   byte can_ultra_dma      = ali15x3_can_ultra(drive);
+ 
+    if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
+       return hwif->dmaproc(ide_dma_off_quietly, drive);
+ 
++   drive->init_speed = 0;
++
+    if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) {
+       /* Consult the list of known "bad" drives */
+       if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+@@ -453,9 +497,9 @@
+       }
+       dma_func = ide_dma_off_quietly;
+       if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
+-         if (id->dma_ultra & 0x002F) {
++         if (id->dma_ultra & 0x003F) {
+             /* Force if Capable UltraDMA */
+-            dma_func = config_chipset_for_dma(drive, can_ultra_dma);
++            dma_func = config_chipset_for_dma(drive);
+             if ((id->field_valid & 2) &&
+                 (dma_func != ide_dma_on))
+                goto try_dma_modes;
+@@ -465,7 +509,7 @@
+          if ((id->dma_mword & 0x0007) ||
+              (id->dma_1word & 0x0007)) {
+             /* Force if Capable regular DMA modes */
+-            dma_func = config_chipset_for_dma(drive, can_ultra_dma);
++            dma_func = config_chipset_for_dma(drive);
+             if (dma_func != ide_dma_on)
+                goto no_dma_set;
+          }
+@@ -474,7 +518,7 @@
+             goto no_dma_set;
+          }
+          /* Consult the list of known "good" drives */
+-         dma_func = config_chipset_for_dma(drive, can_ultra_dma);
++         dma_func = config_chipset_for_dma(drive);
+          if (dma_func != ide_dma_on)
+             goto no_dma_set;
+       } else {
+@@ -484,7 +528,7 @@
+ fast_ata_pio:
+       dma_func = ide_dma_off_quietly;
+ no_dma_set:
+-      config_chipset_for_pio(drive);
++      hwif->tuneproc(drive, 5);
+    }
+    return hwif->dmaproc(dma_func, drive);
+ }
+@@ -495,7 +539,8 @@
+       case ide_dma_check:
+          return ali15x3_config_drive_for_dma(drive);
+       case ide_dma_write:
+-         if ((m5229_revision < 0xC2) && (drive->media != ide_disk))
++         if ((m5229_revision < 0xC2) &&
++             (drive->media != ide_disk))
+             return 1;   /* try PIO instead of DMA */
+          break;
+       default:
+@@ -505,10 +550,17 @@
+ }
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+ 
++#define ALI_INIT_CODE_TEST
++
+ unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name)
+ {
+    unsigned long fixdma_base = pci_resource_start(dev, 4);
+ 
++#ifdef ALI_INIT_CODE_TEST
++   unsigned long flags;
++   byte tmpbyte;
++#endif /* ALI_INIT_CODE_TEST */
++
+    pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
+ 
+    isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+@@ -521,9 +573,9 @@
+       /*
+        * enable DMA capable bit, and "not" simplex only
+        */
+-      outb(inb(fixdma_base+2) & 0x60, fixdma_base+2);
++      OUT_BYTE(IN_BYTE(fixdma_base+2) & 0x60, fixdma_base+2);
+ 
+-      if (inb(fixdma_base+2) & 0x80)
++      if (IN_BYTE(fixdma_base+2) & 0x80)
+          printk("%s: simplex device: DMA will fail!!\n", name);
+    }
+ 
+@@ -535,6 +587,55 @@
+    }
+ #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
+ 
++#ifdef ALI_INIT_CODE_TEST
++   local_irq_save(flags);
++
++   if (m5229_revision >= 0xC2) {
++      /*
++       * 1543C-B?, 1535, 1535D, 1553
++       * Note 1: not all "motherboard" support this detection
++       * Note 2: if no udma 66 device, the detection may "error".
++       *         but in this case, we will not set the device to
++       *         ultra 66, the detection result is not important
++       */
++
++      /*
++       * enable "Cable Detection", m5229, 0x4b, bit3
++       */
++      pci_read_config_byte(dev, 0x4b, &tmpbyte);
++      pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08);
++
++      /*
++       * set south-bridge's enable bit, m1533, 0x79
++       */
++      pci_read_config_byte(isa_dev, 0x79, &tmpbyte);
++      if (m5229_revision == 0xC2) {
++         /*
++          * 1543C-B0 (m1533, 0x79, bit 2)
++          */
++         pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04);
++      } else if (m5229_revision >= 0xC3) {
++         /*
++          * 1553/1535 (m1533, 0x79, bit 1)
++          */
++         pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
++      }
++   } else {
++      /*
++       * revision 0x20 (1543-E, 1543-F)
++       * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E)
++       * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7
++       */
++      pci_read_config_byte(dev, 0x4b, &tmpbyte);
++      /*
++       * clear bit 7
++       */
++      pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
++   }
++
++   local_irq_save(flags);
++#endif /* ALI_INIT_CODE_TEST */
++
+    return 0;
+ }
+ 
+@@ -552,10 +653,10 @@
+    unsigned long flags;
+    byte tmpbyte;
+ 
+-   __save_flags(flags);
+-   __cli();
++   local_irq_save(flags);
+ 
+    if (m5229_revision >= 0xC2) {
++#ifndef ALI_INIT_CODE_TEST
+       /*
+        * 1543C-B?, 1535, 1535D, 1553
+        * Note 1: not all "motherboard" support this detection
+@@ -585,6 +686,7 @@
+           */
+          pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
+       }
++#endif /* ALI_INIT_CODE_TEST */
+       /*
+        * Ultra66 cable detection (from Host View)
+        * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
+@@ -605,6 +707,7 @@
+        */
+       ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+    } else {
++#ifndef ALI_INIT_CODE_TEST
+       /*
+        * revision 0x20 (1543-E, 1543-F)
+        * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E)
+@@ -615,6 +718,7 @@
+        * clear bit 7
+        */
+       pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
++#endif /* ALI_INIT_CODE_TEST */
+       /*
+        * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
+        */
+@@ -633,7 +737,7 @@
+ 
+    pci_write_config_byte(dev, 0x53, tmpbyte);
+ 
+-   __restore_flags(flags);
++   local_irq_restore(flags);
+ 
+    return(ata66);
+ }
+@@ -657,7 +761,8 @@
+       ideic = ideic & 0x03;
+ 
+       /* get IRQ for IDE Controller */
+-      if ((hwif->channel && ideic == 0x03) || (!hwif->channel && !ideic)) {
++      if ((hwif->channel && ideic == 0x03) ||
++          (!hwif->channel && !ideic)) {
+          /*
+           * get SIRQ1 routing table
+           */
+@@ -675,24 +780,26 @@
+    }
+ #endif /* CONFIG_SPARC64 */
+ 
++   hwif->autodma = 0;
+    hwif->tuneproc = &ali15x3_tune_drive;
+    hwif->drives[0].autotune = 1;
+    hwif->drives[1].autotune = 1;
+    hwif->speedproc = &ali15x3_tune_chipset;
+ 
++   if (!hwif->dma_base)
++      return;
++
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-   if ((hwif->dma_base) && (m5229_revision >= 0x20)) {
++   if (m5229_revision >= 0x20) {
+       /*
+        * M1543C or newer for DMAing
+        */
+       hwif->dmaproc = &ali15x3_dmaproc;
+-      hwif->autodma = 1;
++#ifdef CONFIG_IDEDMA_AUTO
++      if (!noautodma)
++         hwif->autodma = 1;
++#endif /* CONFIG_IDEDMA_AUTO */
+    }
+-
+-   if (noautodma)
+-      hwif->autodma = 0;
+-#else
+-   hwif->autodma = 0;
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+ }
+ 
+@@ -703,3 +810,16 @@
+    }
+    ide_setup_dma(hwif, dmabase, 8);
+ }
++
++extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d);
++
++void __init fixup_device_ali15x3 (struct pci_dev *dev, ide_pci_device_t *d)
++{
++   if (dev->resource[0].start != 0x01F1)
++      ide_register_xp_fix(dev);
++
++   printk("%s: IDE controller on PCI bus %02x dev %02x\n",
++      d->name, dev->bus->number, dev->devfn);
++   ide_setup_pci_device(dev, d);
++}
++
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/amd74xx.c linux-2.4.19-p8-ac1/drivers/ide/amd74xx.c
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/amd74xx.c   Fri May 10 10:10:21 2002
++++ linux-2.4.19-p8-ac1/drivers/ide/amd74xx.c   Fri May 10 05:15:51 2002
+@@ -34,7 +34,6 @@
+ 
+ static int amd74xx_get_info(char *, char **, off_t, int);
+ extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+-extern char *ide_media_verbose(ide_drive_t *);
+ static struct pci_dev *bmide_dev;
+ 
+ static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count)
+@@ -47,16 +46,22 @@
+     * at that point bibma+0x2 et bibma+0xa are byte registers
+     * to investigate:
+     */
+-   c0 = inb_p((unsigned short)bibma + 0x02);
+-   c1 = inb_p((unsigned short)bibma + 0x0a);
++   c0 = IN_BYTE((unsigned short)bibma + 0x02);
++   c1 = IN_BYTE((unsigned short)bibma + 0x0a);
+ 
+-   p += sprintf(p, "\n                                AMD %04X VIPER Chipset.\n", bmide_dev->device);
+-   p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+-   p += sprintf(p, "                %sabled                         %sabled\n",
++   p += sprintf(p, "\n                                "
++         "AMD %04X VIPER Chipset.\n", bmide_dev->device);
++   p += sprintf(p, "--------------- Primary Channel "
++         "---------------- Secondary Channel "
++         "-------------\n");
++   p += sprintf(p, "                %sabled "
++         "                        %sabled\n",
+          (c0&0x80) ? "dis" : " en",
+          (c1&0x80) ? "dis" : " en");
+-   p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+-   p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
++   p += sprintf(p, "--------------- drive0 --------- drive1 "
++         "-------- drive0 ---------- drive1 ------\n");
++   p += sprintf(p, "DMA enabled:    %s              %s "
++         "            %s               %s\n",
+          (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
+          (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
+    p += sprintf(p, "UDMA\n");
+@@ -69,40 +74,85 @@
+ 
+ byte amd74xx_proc = 0;
+ 
+-extern char *ide_xfer_verbose (byte xfer_rate);
++static int amd74xx_mode5_check (struct pci_dev *dev)
++{
++   switch(dev->device) {
++      case PCI_DEVICE_ID_AMD_VIPER_7411:
++      case PCI_DEVICE_ID_AMD_VIPER_7441:
++         return 1;
++      default:
++         return 0;
++   }
++}
+ 
+ static unsigned int amd74xx_swdma_check (struct pci_dev *dev)
+ {
+    unsigned int class_rev;
+ 
+-   if ((dev->device == PCI_DEVICE_ID_AMD_VIPER_7411) ||
+-       (dev->device == PCI_DEVICE_ID_AMD_VIPER_7441))
+-      return 0;
++   if (amd74xx_mode5_check(dev))
++      return 1;
+ 
+    pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+    class_rev &= 0xff;
+    return ((int) (class_rev >= 7) ? 1 : 0);
+ }
+ 
+-static int amd74xx_swdma_error(ide_drive_t *drive)
++static int amd74xx_swdma_error (ide_drive_t *drive)
+ {
+    printk("%s: single-word DMA not support (revision < C4)\n", drive->name);
+    return 0;
+ }
+ 
++static byte amd74xx_ratemask (ide_drive_t *drive)
++{
++   struct pci_dev *dev = HWIF(drive)->pci_dev;
++   byte mode = 0x00;
++
++        switch(dev->device) {
++      case PCI_DEVICE_ID_AMD_VIPER_7441:
++      case PCI_DEVICE_ID_AMD_VIPER_7411:   { mode |= 0x03; break; }
++      case PCI_DEVICE_ID_AMD_VIPER_7409:   { mode |= 0x02; break; }
++      case PCI_DEVICE_ID_AMD_COBRA_7401:   { mode |= 0x01; break; }
++      default:
++         return (mode &= ~0xFF);
++   }
++
++   if (!eighty_ninty_three(drive)) {
++      mode &= ~0xFE;
++      mode |= 0x01;
++   }
++   return (mode &= ~0xF8);
++}
++
++static byte amd74xx_ratefilter (ide_drive_t *drive, byte speed)
++{
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   byte mode = amd74xx_ratemask(drive);
++
++   switch(mode) {
++      case 0x04:   // while (speed > XFER_UDMA_6) speed--; break;
++      case 0x03:   while (speed > XFER_UDMA_5) speed--; break;
++      case 0x02:   while (speed > XFER_UDMA_4) speed--; break;
++      case 0x01:   while (speed > XFER_UDMA_2) speed--; break;
++      case 0x00:
++      default:   while (speed > XFER_MW_DMA_2) speed--; break;
++         break;
++   }
++#else
++   while (speed > XFER_PIO_4) speed--;
++#endif /* CONFIG_BLK_DEV_IDEDMA */
++//   printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed);
++   return speed;
++}
++
+ /*
+  * Here is where all the hard work goes to program the chipset.
+- *
+  */
+-static int amd74xx_tune_chipset (ide_drive_t *drive, byte speed)
++static int amd74xx_tune_chipset (ide_drive_t *drive, byte xferspeed)
+ {
+    ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev   = hwif->pci_dev;
+-   int err         = 0;
+-   byte unit      = (drive->select.b.unit & 0x01);
+-#ifdef CONFIG_BLK_DEV_IDEDMA
+-   unsigned long dma_base   = hwif->dma_base;
+-#endif /* CONFIG_BLK_DEV_IDEDMA */
++   byte speed      = amd74xx_ratefilter(drive, xferspeed);
+    byte drive_pci      = 0x00;
+    byte drive_pci2      = 0x00;
+    byte ultra_timing   = 0x00;
+@@ -122,20 +172,10 @@
+    pci_read_config_byte(dev, drive_pci2, &dma_pio_timing);
+    pci_read_config_byte(dev, 0x4c, &pio_timing);
+ 
+-#ifdef DEBUG
+-   printk("%s:%d: Speed 0x%02x UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+-      drive->name, drive->dn, speed, ultra_timing, dma_pio_timing, pio_timing);
+-#endif
+-
+    ultra_timing   &= ~0xC7;
+    dma_pio_timing   &= ~0xFF;
+    pio_timing   &= ~(0x03 << drive->dn);
+ 
+-#ifdef DEBUG
+-   printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+-      drive->name, ultra_timing, dma_pio_timing, pio_timing);
+-#endif
+-
+    switch(speed) {
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+       case XFER_UDMA_7:
+@@ -162,7 +202,7 @@
+          dma_pio_timing |= 0x20;
+          break;
+       case XFER_UDMA_0:
+-      ultra_timing |= 0x42;
++         ultra_timing |= 0x42;
+          dma_pio_timing |= 0x20;
+          break;
+       case XFER_MW_DMA_2:
+@@ -210,75 +250,19 @@
+ 
+    pio_timing |= (0x03 << drive->dn);
+ 
+-   if (!drive->init_speed)
+-      drive->init_speed = speed;
+-
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+    pci_write_config_byte(dev, drive_pci, ultra_timing);
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+    pci_write_config_byte(dev, drive_pci2, dma_pio_timing);
+    pci_write_config_byte(dev, 0x4c, pio_timing);
+ 
+-#ifdef DEBUG
+-   printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+-      drive->name, ultra_timing, dma_pio_timing, pio_timing);
+-#endif
+-
+-#ifdef CONFIG_BLK_DEV_IDEDMA
+-   if (speed > XFER_PIO_4) {
+-      outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+-   } else {
+-      outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+-   }
+-#endif /* CONFIG_BLK_DEV_IDEDMA */
+-
+-   err = ide_config_drive_speed(drive, speed);
+-   drive->current_speed = speed;
+-   return (err);
+-}
+-
+-static void config_chipset_for_pio (ide_drive_t *drive)
+-{
+-   unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+-   unsigned short xfer_pio   = drive->id->eide_pio_modes;
+-   byte         timing, speed, pio;
+-
+-   pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+-
+-   if (xfer_pio> 4)
+-      xfer_pio = 0;
+-
+-   if (drive->id->eide_pio_iordy > 0) {
+-      for (xfer_pio = 5;
+-         xfer_pio>0 &&
+-         drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+-         xfer_pio--);
+-   } else {
+-      xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+-            (drive->id->eide_pio_modes & 2) ? 0x04 :
+-            (drive->id->eide_pio_modes & 1) ? 0x03 :
+-            (drive->id->tPIO & 2) ? 0x02 :
+-            (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+-   }
+-
+-   timing = (xfer_pio >= pio) ? xfer_pio : pio;
+-
+-   switch(timing) {
+-      case 4: speed = XFER_PIO_4;break;
+-      case 3: speed = XFER_PIO_3;break;
+-      case 2: speed = XFER_PIO_2;break;
+-      case 1: speed = XFER_PIO_1;break;
+-      default:
+-         speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+-         break;
+-   }
+-   (void) amd74xx_tune_chipset(drive, speed);
+-   drive->current_speed = speed;
++   return (ide_config_drive_speed(drive, speed));
+ }
+ 
+ static void amd74xx_tune_drive (ide_drive_t *drive, byte pio)
+ {
+    byte speed;
++   pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+    switch(pio) {
+       case 4:      speed = XFER_PIO_4;break;
+       case 3:      speed = XFER_PIO_3;break;
+@@ -297,58 +281,69 @@
+  */
+ static int config_chipset_for_dma (ide_drive_t *drive)
+ {
+-   ide_hwif_t *hwif   = HWIF(drive);
+-   struct pci_dev *dev   = hwif->pci_dev;
+-   struct hd_driveid *id   = drive->id;
+-   byte udma_66      = eighty_ninty_three(drive);
+-   byte udma_100      = ((dev->device==PCI_DEVICE_ID_AMD_VIPER_7411)||
+-               (dev->device==PCI_DEVICE_ID_AMD_VIPER_7441)) ? 1 : 0;
+-   byte speed      = 0x00;
++   struct hd_driveid *id   = drive->id;
++   byte mode      = amd74xx_ratemask(drive);
++   byte swdma      = amd74xx_swdma_check(HWIF(drive)->pci_dev);
++   byte speed      = 0;
+    int  rval;
+ 
+-   if (udma_100)
+-      udma_66 = eighty_ninty_three(drive);
+-
+-   if ((id->dma_ultra & 0x0020) && (udma_66) && (udma_100)) {
+-      speed = XFER_UDMA_5;
+-   } else if ((id->dma_ultra & 0x0010) && (udma_66)) {
+-      speed = XFER_UDMA_4;
+-   } else if ((id->dma_ultra & 0x0008) && (udma_66)) {
+-      speed = XFER_UDMA_3;
+-   } else if (id->dma_ultra & 0x0004) {
+-      speed = XFER_UDMA_2;
+-   } else if (id->dma_ultra & 0x0002) {
+-      speed = XFER_UDMA_1;
+-   } else if (id->dma_ultra & 0x0001) {
+-      speed = XFER_UDMA_0;
+-   } else if (id->dma_mword & 0x0004) {
+-      speed = XFER_MW_DMA_2;
+-   } else if (id->dma_mword & 0x0002) {
+-      speed = XFER_MW_DMA_1;
+-   } else if (id->dma_mword & 0x0001) {
+-      speed = XFER_MW_DMA_0;
+-   } else {
+-      return ((int) ide_dma_off_quietly);
++   amd74xx_tune_drive(drive, 5);
++   
++   switch(mode) {
++      case 0x04:
++         if (id->dma_ultra & 0x0040)
++            { speed = XFER_UDMA_6; break; }
++      case 0x03:
++         if (id->dma_ultra & 0x0020)
++            { speed = XFER_UDMA_5; break; }
++      case 0x02:
++         if (id->dma_ultra & 0x0010)
++            { speed = XFER_UDMA_4; break; }
++         if (id->dma_ultra & 0x0008)
++            { speed = XFER_UDMA_3; break; }
++      case 0x01:
++         if (id->dma_ultra & 0x0004)
++            { speed = XFER_UDMA_2; break; }
++         if (id->dma_ultra & 0x0002)
++            { speed = XFER_UDMA_1; break; }
++         if (id->dma_ultra & 0x0001)
++            { speed = XFER_UDMA_0; break; }
++      case 0x00:
++         if (id->dma_mword & 0x0004)
++            { speed = XFER_MW_DMA_2; break; }
++         if (id->dma_mword & 0x0002)
++            { speed = XFER_MW_DMA_1; break; }
++         if (id->dma_mword & 0x0001)
++            { speed = XFER_MW_DMA_0; break; }
++         if ((id->dma_1word & 0x0004) && (swdma))
++            { speed = XFER_SW_DMA_2; break; }
++         if ((id->dma_1word & 0x0002) && (swdma))
++            { speed = XFER_SW_DMA_1; break; }
++         if ((id->dma_1word & 0x0001) && (swdma))
++            { speed = XFER_SW_DMA_0; break; }
++      default:
++         return ((int) ide_dma_off_quietly);
+    }
+ 
+    (void) amd74xx_tune_chipset(drive, speed);
+-
+-   rval = (int)(   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+-         ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+-         ((id->dma_mword >> 8) & 7) ? ide_dma_on :
++//   return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly);
++   rval = (int)(   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
++          ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
++          ((id->dma_mword >> 8) & 7) ? ide_dma_on :
++          (((id->dma_1word >> 8) & 7) && (swdma)) ? ide_dma_on :
+                        ide_dma_off_quietly);
+-
+    return rval;
+ }
+ 
+ static int config_drive_xfer_rate (ide_drive_t *drive)
+ {
+-   struct hd_driveid *id = drive->id;
++   struct hd_driveid *id   = drive->id;
++   ide_hwif_t *hwif   = HWIF(drive);
+    ide_dma_action_t dma_func = ide_dma_on;
+ 
+-   config_chipset_for_pio(drive);
+-         
+-   if (id && (id->capability & 1) && HWIF(drive)->autodma) {
++   drive->init_speed = 0;
++
++   if (id && (id->capability & 1) && hwif->autodma) {
+       /* Consult the list of known "bad" drives */
+       if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+          dma_func = ide_dma_off;
+@@ -389,8 +384,7 @@
+ fast_ata_pio:
+       dma_func = ide_dma_off_quietly;
+ no_dma_set:
+-
+-      config_chipset_for_pio(drive);
++      amd74xx_tune_drive(drive, 5);
+    }
+    return HWIF(drive)->dmaproc(dma_func, drive);
+ }
+@@ -428,9 +422,9 @@
+       /*
+        * enable DMA capable bit, and "not" simplex only
+        */
+-      outb(inb(fixdma_base+2) & 0x60, fixdma_base+2);
++      OUT_BYTE(IN_BYTE(fixdma_base+2) & 0x60, fixdma_base+2);
+ 
+-      if (inb(fixdma_base+2) & 0x80)
++      if (IN_BYTE(fixdma_base+2) & 0x80)
+          printk("%s: simplex device: DMA will fail!!\n", name);
+    }
+ #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+@@ -490,22 +484,19 @@
+    hwif->tuneproc = &amd74xx_tune_drive;
+    hwif->speedproc = &amd74xx_tune_chipset;
+ 
+-#ifndef CONFIG_BLK_DEV_IDEDMA
+-   hwif->drives[0].autotune = 1;
+-   hwif->drives[1].autotune = 1;
+-   hwif->autodma = 0;
+-   return;
+-#else
+-
+-   if (hwif->dma_base) {
+-      hwif->dmaproc = &amd74xx_dmaproc;
+-      if (!noautodma)
+-         hwif->autodma = 1;
+-   } else {
+-      hwif->autodma = 0;
++   if (!hwif->dma_base) {
+       hwif->drives[0].autotune = 1;
+       hwif->drives[1].autotune = 1;
++      hwif->autodma = 0;
++      return;
+    }
++
++#ifndef CONFIG_BLK_DEV_IDEDMA
++   hwif->dmaproc = &amd74xx_dmaproc;
++#ifdef CONFIG_IDEDMA_AUTO
++   if (!noautodma)
++      hwif->autodma = 1;
++#endif /* CONFIG_IDEDMA_AUTO */
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+ }
+ 
+@@ -513,3 +504,16 @@
+ {
+    ide_setup_dma(hwif, dmabase, 8);
+ }
++
++extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d);
++
++void __init fixup_device_amd74xx (struct pci_dev *dev, ide_pci_device_t *d)
++{
++   if (dev->resource[0].start != 0x01F1)
++      ide_register_xp_fix(dev);
++
++   printk("%s: IDE controller on PCI bus %02x dev %02x\n",
++      d->name, dev->bus->number, dev->devfn);
++   ide_setup_pci_device(dev, d);
++}
++
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/cmd640.c linux-2.4.19-p8-ac1/drivers/ide/cmd640.c
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/cmd640.c   Fri May 10 10:10:21 2002
++++ linux-2.4.19-p8-ac1/drivers/ide/cmd640.c   Fri May 10 05:15:51 2002
+@@ -217,11 +217,10 @@
+ {
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
+-   outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
++   spin_lock_irqsave(&io_request_lock, flags);
++   outb_p((reg & 0xfc) | cmd640_key, 0xcf8);
+    outb_p(val, (reg & 3) | 0xcfc);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ 
+ static byte get_cmd640_reg_pci1 (unsigned short reg)
+@@ -229,11 +228,10 @@
+    byte b;
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
+-   outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
++   spin_lock_irqsave(&io_request_lock, flags);
++   outb_p((reg & 0xfc) | cmd640_key, 0xcf8);
+    b = inb_p((reg & 3) | 0xcfc);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+    return b;
+ }
+ 
+@@ -243,12 +241,11 @@
+ {
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+    outb_p(0x10, 0xcf8);
+    outb_p(val, cmd640_key + reg);
+    outb_p(0, 0xcf8);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ 
+ static byte get_cmd640_reg_pci2 (unsigned short reg)
+@@ -256,12 +253,11 @@
+    byte b;
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+    outb_p(0x10, 0xcf8);
+    b = inb_p(cmd640_key + reg);
+    outb_p(0, 0xcf8);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+    return b;
+ }
+ 
+@@ -271,11 +267,10 @@
+ {
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+    outb_p(reg, cmd640_key);
+    outb_p(val, cmd640_key + 4);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ 
+ static byte get_cmd640_reg_vlb (unsigned short reg)
+@@ -283,11 +278,10 @@
+    byte b;
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+    outb_p(reg, cmd640_key);
+    b = inb_p(cmd640_key + 4);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+    return b;
+ }
+ 
+@@ -315,7 +309,9 @@
+ {
+    get_cmd640_reg = get_cmd640_reg_pci1;
+    put_cmd640_reg = put_cmd640_reg_pci1;
+-   for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) {
++   for (cmd640_key = 0x80000000;
++        cmd640_key <= 0x8000f800;
++        cmd640_key += 0x800) {
+       if (match_pci_cmd640_device())
+          return 1; /* success */
+    }
+@@ -364,8 +360,7 @@
+ {
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+ 
+    outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET);   /* select drive0 */
+    udelay(100);
+@@ -373,11 +368,11 @@
+       outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
+       udelay(100);
+       if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
+-         restore_flags(flags);
++         spin_unlock_irqrestore(&io_request_lock, flags);
+          return 0; /* nothing responded */
+       }
+    }
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+    return 1; /* success */
+ }
+ 
+@@ -458,8 +453,7 @@
+    byte b;
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+    b = get_cmd640_reg(reg);
+    if (mode) {   /* want prefetch on? */
+ #if CMD640_PREFETCH_MASKS
+@@ -475,7 +469,7 @@
+       b |= prefetch_masks[index];   /* disable prefetch */
+    }
+    put_cmd640_reg(reg, b);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ 
+ /*
+@@ -576,8 +570,7 @@
+    /*
+     * Now that everything is ready, program the new timings
+     */
+-   save_flags (flags);
+-   cli();
++   spin_lock_irqsave(&io_request_lock, flags);
+    /*
+     * Program the address_setup clocks into ARTTIM reg,
+     * and then the active/recovery counts into the DRWTIM reg
+@@ -586,7 +579,7 @@
+    setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f;
+    put_cmd640_reg(arttim_regs[index], setup_count);
+    put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+ }
+ 
+ /*
+@@ -697,19 +690,17 @@
+    u32 tmp;
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   __cli();
+-   outb(0x01, 0xCFB);
++   spin_lock_irqsave(&io_request_lock, flags);
++   OUT_BYTE(0x01, 0xCFB);
+    tmp = inl(0xCF8);
+    outl(0x80000000, 0xCF8);
+-   if(inl(0xCF8) == 0x80000000)
+-   {
++   if (inl(0xCF8) == 0x80000000) {
+       outl(tmp, 0xCF8);
+-      restore_flags(flags);
++      spin_unlock_irqrestore(&io_request_lock, flags);
+       return 1;
+    }
+    outl(tmp, 0xCF8);
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+    return 0;
+ }
+ 
+@@ -717,17 +708,15 @@
+ {
+    unsigned long flags;
+ 
+-   save_flags(flags);
+-   __cli();
+-   outb(0x00, 0xCFB);
+-   outb(0x00, 0xCF8);
+-   outb(0x00, 0xCFA);
+-   if(inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00)
+-   {
+-      restore_flags(flags);
++   spin_lock_irqsave(&io_request_lock, flags);
++   OUT_BYTE(0x00, 0xCFB);
++   OUT_BYTE(0x00, 0xCF8);
++   OUT_BYTE(0x00, 0xCFA);
++   if (IN_BYTE(0xCF8) == 0x00 && IN_BYTE(0xCF8) == 0x00) {
++      spin_unlock_irqrestore(&io_request_lock, flags);
+       return 1;
+    }
+-   restore_flags(flags);
++   spin_unlock_irqrestore(&io_request_lock, flags);
+    return 0;
+ }
+ 
+@@ -748,10 +737,8 @@
+       bus_type = "VLB";
+    } else {
+       cmd640_vlb = 0;
+-      /*
+-       * Don't leak I/O cycles on the PCI bus by blindly attempting
+-       * a configuration cycle type that is not supported by the hardware.
+-       */
++      /* Find out what kind of PCI probing is supported otherwise
++         Justin Gibbs will sulk.. */
+       if (pci_conf1() && probe_for_cmd640_pci1())
+          bus_type = "PCI (type1)";
+       else if (pci_conf2() && probe_for_cmd640_pci2())
+diff -urN linux-2.4.19-p8-ac1-pristine/drivers/ide/cmd64x.c linux-2.4.19-p8-ac1/drivers/ide/cmd64x.c
+--- linux-2.4.19-p8-ac1-pristine/drivers/ide/cmd64x.c   Fri May 10 10:10:21 2002
++++ linux-2.4.19-p8-ac1/drivers/ide/cmd64x.c   Fri May 10 05:15:51 2002
+@@ -8,9 +8,10 @@
+  *           Due to massive hardware bugs, UltraDMA is only supported
+  *           on the 646U2 and not on the 646U.
+  *
+- * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
+- * Copyright (C) 1998       David S. Miller (davem@redhat.com)
+- * Copyright (C) 1999-2000  Andre Hedrick <andre@linux-ide.org>
++ * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
++ * Copyright (C) 1998      David S. Miller (davem@redhat.com)
++ *
++ * Copyright (C) 1999-2002   Andre Hedrick <andre@linux-ide.org>
+  */
+ 
+ #include <linux/config.h>
+@@ -32,7 +33,7 @@
+ #define CMD_DEBUG 0
+ 
+ #if CMD_DEBUG
+-#define cmdprintk(x...)   printk(##x)
++#define cmdprintk(x...)   printk(x)
+ #else
+ #define cmdprintk(x...)
+ #endif
+@@ -85,82 +86,97 @@
+ #include <linux/stat.h>
+ #include <linux/proc_fs.h>
+ 
++static char * print_cmd64x_get_info(char *, struct pci_dev *, int);
++static char * print_sii_get_info(char *, struct pci_dev *, int);
+ static int cmd64x_get_info(char *, char **, off_t, int);
+-static int cmd680_get_info(char *, char **, off_t, int);
+ extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+-extern char *ide_media_verbose(ide_drive_t *);
+-static struct pci_dev *bmide_dev;
+ 
+-static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
++byte cmd64x_proc = 0;
++
++#define CMD_MAX_DEVS      5
++
++static struct pci_dev *cmd_devs[CMD_MAX_DEVS];
++static int n_cmd_devs;
++
++#undef DEBUG_CMD_REGS
++
++static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
+ {
+-   char *p = buffer;
++   char *p = buf;
++
+    u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0;   /* primary */
+    u8 reg57 = 0, reg58 = 0, reg5b;         /* secondary */
+    u8 reg72 = 0, reg73 = 0;         /* primary */
+    u8 reg7a = 0, reg7b = 0;         /* secondary */
+    u8 reg50 = 0, reg71 = 0;         /* extra */
++#ifdef DEBUG_CMD_REGS
+    u8 hi_byte = 0, lo_byte = 0;
++#endif /* DEBUG_CMD_REGS */
+ 
+-   switch(bmide_dev->device) {
+-      case PCI_DEVICE_ID_CMD_649:
+-         p += sprintf(p, "\n                                CMD649 Chipset.\n");
+-         break;
+-      case PCI_DEVICE_ID_CMD_648:
+-         p += sprintf(p, "\n                                CMD648 Chipset.\n");
+-         break;
+-      case PCI_DEVICE_ID_CMD_646:
+-         p += sprintf(p, "\n                                CMD646 Chipset.\n");
+-         break;
+-      case PCI_DEVICE_ID_CMD_643:
+-         p += sprintf(p, "\n                                CMD643 Chipset.\n");
+-         break;
+-      default:
+-         p += sprintf(p, "\n                                CMD64? Chipse.\n");
+-         break;
+-   }
+-   (void) pci_read_config_byte(bmide_dev, CFR,       ®50);
+-   (void) pci_read_config_byte(bmide_dev, ARTTIM0,   ®53);
+-   (void) pci_read_config_byte(bmide_dev, DRWTIM0,   ®54);
+-   (void) pci_read_config_byte(bmide_dev, ARTTIM1,   ®55);
+-   (void) pci_read_config_byte(bmide_dev, DRWTIM1,   ®56);
+-   (void) pci_read_config_byte(bmide_dev, ARTTIM2,   ®57);
+-   (void) pci_read_config_byte(bmide_dev, DRWTIM2,   ®58);
+-   (void) pci_read_config_byte(bmide_dev, DRWTIM3,   ®5b);
+-   (void) pci_read_config_byte(bmide_dev, MRDMODE,   ®71);
+-   (void) pci_read_config_byte(bmide_dev, BMIDESR0,  ®72);
+-   (void) pci_read_config_byte(bmide_dev, UDIDETCR0, ®73);
+-   (void) pci_read_config_byte(bmide_dev, BMIDESR1,  ®7a);
+-   (void) pci_read_config_byte(bmide_dev, UDIDETCR1, ®7b);
+-
+-   p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+-   p += sprintf(p, "                %sabled                         %sabled\n",
+-      (reg72&0x80)?"dis":" en",(reg7a&0x80)?"dis":" en");
+-   p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+-   p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+-      (reg72&0x20)?"yes":"no ",(reg72&0x40)?"yes":"no ",(reg7a&0x20)?"yes":"no ",(reg7a&0x40)?"yes":"no ");
+-   p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)         %s(%s)           %s(%s)\n",
++   p += sprintf(p, "\nController: %d\n", index);
++   p += sprintf(p, "CMD%x Chipset.\n", dev->device);
++   (void) pci_read_config_byte(dev, CFR,       ®50);
++   (void) pci_read_config_byte(dev, ARTTIM0,   ®53);
++   (void) pci_read_config_byte(dev, DRWTIM0,   ®54);
++   (void) pci_read_config_byte(dev, ARTTIM1,   ®55);
++   (void) pci_read_config_byte(dev, DRWTIM1,   ®56);
++   (void) pci_read_config_byte(dev, ARTTIM2,   ®57);
++   (void) pci_read_config_byte(dev, DRWTIM2,   ®58);
++   (void) pci_read_config_byte(dev, DRWTIM3,   ®5b);
++   (void) pci_read_config_byte(dev, MRDMODE,   ®71);
++   (void) pci_read_config_byte(dev, BMIDESR0,  ®72);
++   (void) pci_read_config_byte(dev, UDIDETCR0, ®73);
++   (void) pci_read_config_byte(dev, BMIDESR1,  ®7a);
++   (void) pci_read_config_byte(dev, UDIDETCR1, ®7b);
++
++   p += sprintf(p, "--------------- Primary Channel "
++         "---------------- Secondary Channel "
++         "-------------\n");
++   p += sprintf(p, "                %sabled           "
++         "              %sabled\n",
++      (reg72&0x80)?"dis":" en",
++      (reg7a&0x80)?"dis":" en");
++   p += sprintf(p, "--------------- drive0 "
++      "--------- drive1 -------- drive0 "
++      "---------- drive1 ------\n");
++   p += sprintf(p, "DMA enabled:    %s              %s"
++         "             %s               %s\n",
++      (reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ",
++      (reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no ");
++
++   p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)",
+       (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO",
+-      (reg72&0x20)?(  ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"):
+-            ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"):
+-            ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"):
+-            ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):"X"):"?",
++      (reg72&0x20)?(
++         ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"):
++         ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"):
++         ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"):
++         ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):
++         "X"):"?",
+       (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO",
+-      (reg72&0x40)?(   ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"):
+-            ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"):
+-            ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"):
+-            ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):"X"):"?",
++      (reg72&0x40)?(
++         ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"):
++         ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"):
++         ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"):
++         ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):
++         "X"):"?");
++   p += sprintf(p, "         %s(%s)           %s(%s)\n",
+       (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO",
+-      (reg7a&0x20)?(   ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"):
+-            ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"):
+-            ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"):
+-            ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):"X"):"?",
++      (reg7a&0x20)?(
++         ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"):
++         ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"):
++         ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"):
++         ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):
++         "X"):"?",
+       (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO",
+-      (reg7a&0x40)?(   ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"):
+-            ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"):
+-            ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"):
+-            ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):"X"):"?" );
+-   p += sprintf(p, "PIO Mode:       %s                %s               %s                 %s\n",
+-      "?", "?", "?", "?");
++      (reg7a&0x40)?(
++         ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"):
++         ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"):
++         ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"):
++         ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):
++         "X"):"?" );
++   p += sprintf(p, "PIO Mode:       %s                %s"
++         "               %s                 %s\n",
++         "?", "?", "?", "?");
+    p += sprintf(p, "                %s                     %s\n",
+       (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling     ",
+       (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling");
+@@ -171,32 +187,58 @@
+       (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled",
+       (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled");
+ 
++#ifdef DEBUG_CMD_REGS
+    SPLIT_BYTE(reg50, hi_byte, lo_byte);
+-   p += sprintf(p, "CFR       = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg50, hi_byte, lo_byte);
++   p += sprintf(p, "CFR       = 0x%02x, HI = 0x%02x, "
++         "LOW = 0x%02x\n", reg50, hi_byte, lo_byte);
+    SPLIT_BYTE(reg57, hi_byte, lo_byte);
+-   p += sprintf(p, "ARTTIM23  = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg57, hi_byte, lo_byte);
++   p += sprintf(p, "ARTTIM23  = 0x%02x, HI = 0x%02x, "
++         "LOW = 0x%02x\n", reg57, hi_byte, lo_byte);
+    SPLIT_BYTE(reg71, hi_byte, lo_byte);
+-   p += sprintf(p, "MRDMODE   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg71, hi_byte, lo_byte);
++   p += sprintf(p, "MRDMODE   = 0x%02x, HI = 0x%02x, "
++         "LOW = 0x%02x\n", reg71, hi_byte, lo_byte);
++#endif /* DEBUG_CMD_REGS */
+ 
+-   return p-buffer;   /* => must be less than 4k! */
++   return (char *)p;
+ }
+ 
+-static int cmd680_get_info (char *buffer, char **addr, off_t offset, int count)
++static char * print_sii_get_info (char *buf, struct pci_dev *dev, int index)
++{
++   char *p = buf;
++
++   p += sprintf(p, "\nController: %d\n", index);
++   p += sprintf(p, "SII%x Chipset.\n", dev->device);
++
++   p += sprintf(p, "--------------- Primary Channel "
++         "---------------- Secondary Channel "
++         "-------------\n");
++   p += sprintf(p, "--------------- drive0 --------- drive1 "
++         "-------- drive0 ---------- drive1 ------\n");
++   p += sprintf(p, "PIO Mode:       %s                %s"
++         "               %s                 %s\n",
++         "?", "?", "?", "?");
++   return (char *)p;
++}
++
++static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
+ {
+    char *p = buffer;
+-   p += sprintf(p, "\n                                CMD680 Chipset.\n");
+-   p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+-   p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+-   p += sprintf(p, "PIO Mode:       %s                %s               %s                 %s\n",
+-      "?", "?", "?", "?");
++   int i;
++
++   p += sprintf(p, "\n");
++   for (i = 0; i < n_cmd_devs; i++) {
++      struct pci_dev *dev   = cmd_devs[i];
++
++      if (dev->device <= PCI_DEVICE_ID_CMD_649)
++         p = print_cmd64x_get_info(p, dev, i);
++      else
++         p = print_sii_get_info(p, dev, i);
++   }
+    return p-buffer;   /* => must be less than 4k! */
+ }
+ 
+ #endif   /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
+ 
+-byte cmd64x_proc = 0;
+-byte cmd680_proc = 0;
+-
+ /*
+  * Registers and masks for easy access by drive index:
+  */
+@@ -212,6 +254,7 @@
+ static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count)
+ {
+    unsigned long flags;
++   struct pci_dev *dev = HWIF(drive)->pci_dev;
+    ide_drive_t *drives = HWIF(drive)->drives;
+    byte temp_b;
+    static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+@@ -250,25 +293,29 @@
+    active_count &= 0xf; /* Remember, max value is 16 */
+    recovery_count = (int) recovery_counts[recovery_count];
+ 
+-   cmdprintk("Final values = %d,%d,%d\n", setup_count, active_count, recovery_count);
++   cmdprintk("Final values = %d,%d,%d\n",
++      setup_count, active_count, recovery_count);
+ 
+    /*
+     * Now that everything is ready, program the new timings
+     */
+-   __save_flags (flags);
+-   __cli();
++   local_irq_save(flags);
+    /*
+     * Program the address_setup clocks into ARTTIM reg,
+     * and then the active/recovery counts into the DRWTIM reg
+     */
+-   (void) pci_read_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], &temp_b);
+-   (void) pci_write_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave],
++   (void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b);
++   (void) pci_write_config_byte(dev, arttim_regs[channel][slave],
+       ((byte) setup_count) | (temp_b & 0x3f));
+-   (void) pci_write_config_byte(HWIF(drive)->pci_dev, drwtim_regs[channel][slave],
++   (void) pci_write_config_byte(dev, drwtim_regs[channel][slave],
+       (byte) ((active_count << 4) | recovery_count));
+-   cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]);
+-   cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]);
+-   __restore_flags(flags);
++   cmdprintk ("Write %x to %x\n",
++      ((byte) setup_count) | (temp_b & 0x3f),
++      arttim_regs[channel][slave]);
++   cmdprintk ("Write %x to %x\n",
++      (byte) ((active_count << 4) | recovery_count),
++      drwtim_regs[channel][slave]);
++   local_irq_restore(flags);
+ }
+ 
+ /*
+@@ -292,7 +339,8 @@
+       case 9: /* set prefetch on */
+          mode_wanted &= 1;
+          /*set_prefetch_mode(index, mode_wanted);*/
+-         cmdprintk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis");
++         cmdprintk("%s: %sabled cmd640 prefetch\n",
++            drive->name, mode_wanted ? "en" : "dis");
+          return;
+    }
+ 
+@@ -301,8 +349,8 @@
+    cycle_time = d.cycle_time;
+ 
+    /*
+-    * I copied all this complicated stuff from cmd640.c and made a few minor changes.
+-    * For now I am just going to pray that it is correct.
++    * I copied all this complicated stuff from cmd640.c and made a few
++    * minor changes.  For now I am just going to pray that it is correct.
+     */
+    if (pio_mode > 5)
+       pio_mode = 5;
+@@ -332,17 +380,85 @@
+     * (using WIN_SETFEATURE) before continuing.
+     *
+     * But we do not, because:
+-    *   1) this is the wrong place to do it (proper is do_special() in ide.c)
++    *   1) this is the wrong place to do it
++    *      (proper is do_special() in ide.c)
+     *    2) in practice this is rarely, if ever, necessary
+     */
+    program_drive_counts (drive, setup_count, active_count, recovery_count);
+ 
+-   cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, clocks=%d/%d/%d\n",
++   cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, "
++      "clocks=%d/%d/%d\n",
+       drive->name, pio_mode, mode_wanted, cycle_time,
+       d.overridden ? " (overriding vendor mode)" : "",
+       setup_count, active_count, recovery_count);
+ }
+ 
++static byte cmd64x_ratemask (ide_drive_t *drive)
++{
++   struct pci_dev *dev   = HWIF(drive)->pci_dev;
++   byte mode      = 0x00;
++
++   switch(dev->device) {
++      case PCI_DEVICE_ID_CMD_680:   { mode |= 0x04; break; }
++      case PCI_DEVICE_ID_CMD_649:   { mode |= 0x03; break; }
++      case PCI_DEVICE_ID_CMD_648:   { mode |= 0x02; break; }
++      case PCI_DEVICE_ID_CMD_643:   { mode |= 0x01; break; }
++
++      case PCI_DEVICE_ID_CMD_646:
++      {
++         unsigned int class_rev   = 0;
++         pci_read_config_dword(dev,
++            PCI_CLASS_REVISION, &class_rev);
++         class_rev &= 0xff;
++      /*
++       * UltraDMA only supported on PCI646U and PCI646U2, which
++       * correspond to revisions 0x03, 0x05 and 0x07 respectively.
++       * Actually, although the CMD tech support people won't
++       * tell me the details, the 0x03 revision cannot support
++       * UDMA correctly without hardware modifications, and even
++       * then it only works with Quantum disks due to some
++       * hold time assumptions in the 646U part which are fixed
++       * in the 646U2.
++       *
++       * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
++       */
++         switch(class_rev) {
++            case 0x07:
++            case 0x05:   { mode |= 0x01; break; }
++            case 0x03:
++            case 0x01:
++            default:   { mode |= 0x00; break; }
++         }
++      }
++   }
++   if (!eighty_ninty_three(drive)) {
++      mode &= ~0xFE;
++      mode |= 0x01;
++   }
++   return (mode &= ~0xF8);
++}
++
++static byte cmd64x_ratefilter (ide_drive_t *drive, byte speed)
++{
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   byte mode = cmd64x_ratemask(drive);
++
++   switch(mode) {
++      case 0x04:   while (speed > XFER_UDMA_6) speed--; break;
++      case 0x03:   while (speed > XFER_UDMA_5) speed--; break;
++      case 0x02:   while (speed > XFER_UDMA_4) speed--; break;
++      case 0x01:   while (speed > XFER_UDMA_2) speed--; break;
++      case 0x00:
++      default:   while (speed > XFER_MW_DMA_2) speed--; break;
++         break;
++   }
++#else
++   while (speed > XFER_PIO_4) speed--;
++#endif /* CONFIG_BLK_DEV_IDEDMA */
++//   printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed);
++   return speed;
++}
++
+ static byte cmd680_taskfile_timing (ide_hwif_t *hwif)
+ {
+    struct pci_dev *dev   = hwif->pci_dev;
+@@ -422,35 +538,40 @@
+ 
+    cmd680_tuneproc(drive, set_pio);
+    speed = XFER_PIO_0 + set_pio;
+-   if (set_speed) {
++   if (set_speed)
+       (void) ide_config_drive_speed(drive, speed);
+-      drive->current_speed = speed;
+-   }
+ }
+ 
+ static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
+ {
+-        if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) {
+-      config_cmd680_chipset_for_pio(drive, set_speed);
+-   } else {
+-      config_cmd64x_chipset_for_pio(drive, set_speed);
++   switch(HWIF(drive)->pci_dev->device) {
++      case PCI_DEVICE_ID_CMD_680:
++         config_cmd680_chipset_for_pio(drive, set_speed);
++         return;
++      default:
++         break;
+    }
++   config_cmd64x_chipset_for_pio(drive, set_speed);
+ }
+ 
+-static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed)
++static int cmd64x_tune_chipset (ide_drive_t *drive, byte xferspeed)
+ {
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+    ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev   = hwif->pci_dev;
+-   int err         = 0;
+ 
+    u8 unit         = (drive->select.b.unit & 0x01);
+    u8 pciU         = (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
+    u8 pciD         = (hwif->channel) ? BMIDESR1 : BMIDESR0;
+    u8 regU         = 0;
+    u8 regD         = 0;
++#endif /* CONFIG_BLK_DEV_IDEDMA */
+ 
+-   if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))   return 1;
++   u8 speed      = cmd64x_ratefilter(drive, xferspeed);
++
++#ifdef CONFIG_BLK_DEV_IDEDMA
++   if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))
++      return 1;
+ 
+    (void) pci_read_config_byte(dev, pciD, ®D);
+    (void) pci_read_config_byte(dev, pciU, ®U);
+@@ -458,10 +579,12 @@
+    regU &= ~(unit ? 0xCA : 0x35);
+    (void) pci_write_config_byte(dev, pciD, regD);
+    (void) pci_write_config_byte(dev, pciU, regU);
+-
+    (void) pci_read_config_byte(dev, pciD, ®D);
+    (void) pci_read_config_byte(dev, pciU, ®U);
++#endif /* CONFIG_BLK_DEV_IDEDMA */
++
+    switch(speed) {
++#ifdef CONFIG_BLK_DEV_IDEDMA
+       case XFER_UDMA_5:   regU |= (unit ? 0x0A : 0x05); break;
+       case XFER_UDMA_4:   regU |= (unit ? 0x4A : 0x15); break;
+       case XFER_UDMA_3:   regU |= (unit ? 0x8A : 0x25); break;
+@@ -474,10 +597,6 @@
+       case XFER_SW_DMA_2:   regD |= (unit ? 0x40 : 0x10); break;
+       case XFER_SW_DMA_1:   regD |= (unit ? 0x80 : 0x20); break;
+       case XFER_SW_DMA_0:   regD |= (unit ? 0xC0 : 0x30); break;
+-#else
+-   int err         = 0;
+-
+-      switch(speed) {
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+       case XFER_PIO_4:   cmd64x_tuneproc(drive, 4); break;
+       case XFER_PIO_3:   cmd64x_tuneproc(drive, 3); break;
+@@ -491,33 +610,26 @@
+ 
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+    (void) pci_write_config_byte(dev, pciU, regU);
+-#endif /* CONFIG_BLK_DEV_IDEDMA */
+-
+-   err = ide_config_drive_speed(drive, speed);
+-
+-   drive->current_speed = speed;
+-
+-#ifdef CONFIG_BLK_DEV_IDEDMA
+    regD |= (unit ? 0x40 : 0x20);
+    (void) pci_write_config_byte(dev, pciD, regD);
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+ 
+-   return err;
++   return (ide_config_drive_speed(drive, speed));
+ }
+ 
+-static int cmd680_tune_chipset (ide_drive_t *drive, byte speed)
++static int cmd680_tune_chipset (ide_drive_t *drive, byte xferspeed)
+ {
+    ide_hwif_t *hwif   = HWIF(drive);
+    struct pci_dev *dev   = hwif->pci_dev;
+    u8 addr_mask      = (hwif->channel) ? 0x84 : 0x80;
+    u8 unit         = (drive->select.b.unit & 0x01);
++   u8 speed      = cmd64x_ratefilter(drive, xferspeed);
+    u8 dma_pci      = 0;
+    u8 udma_pci      = 0;
+    u8 mode_pci      = 0;
+    u8 scsc         = 0;
+    u16 ultra      = 0;
+    u16 multi      = 0;
+-   int err         = 0;
+ 
+         pci_read_config_byte(dev, addr_mask, &mode_pci);
+    pci_read_config_byte(dev, 0x8A, &scsc);
+@@ -604,7 +716,6 @@
+       default:
+          return 1;
+    }
+-
+    
+    if (speed >= XFER_MW_DMA_0) 
+       config_cmd680_chipset_for_pio(drive, 0);
+@@ -620,117 +731,59 @@
+    pci_write_config_word(dev, dma_pci, multi);
+    pci_write_config_word(dev, udma_pci, ultra);
+ 
+-   err = ide_config_drive_speed(drive, speed);
+-   drive->current_speed = speed;
+-   return err;
++   return (ide_config_drive_speed(drive, speed));
+ }
+ 
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
++static int config_chipset_for_dma (ide_drive_t *drive)
+ {
+    struct hd_driveid *id   = drive->id;
+    ide_hwif_t *hwif   = HWIF(drive);
+-   struct pci_dev *dev   = hwif->pci_dev;
+-
++   byte mode               = cmd64x_ratemask(drive);
+    byte speed      = 0x00;
+    byte set_pio      = 0x00;
+-   byte udma_33      = ((rev >= 0x05) || (ultra_66)) ? 1 : 0;
+-   byte udma_66      = eighty_ninty_three(drive);
+-   byte udma_100      = 0;
+    int rval;
+ 
+-   switch(dev->device) {
+-      case PCI_DEVICE_ID_CMD_649: udma_100 = 1; break;
+-      case PCI_DEVICE_ID_CMD_648:
+-      case PCI_DEVICE_ID_CMD_646:
+-      case PCI_DEVICE_ID_CMD_643:
+-      default:
+-         break;
+-   }
+-
+    if (drive->media != ide_disk) {
+-      cmdprintk("CMD64X: drive->media != ide_disk at double check, inital check failed!!\n");
++      cmdprintk("CMD64X: drive->media != ide_disk at double check,"
++         " inital check failed!!\n");
+       return ((int) ide_dma_off);
+    }
+ 
+-   /* UltraDMA only supported on PCI646U and PCI646U2,
+-    * which correspond to revisions 0x03, 0x05 and 0x07 respectively.
+-    * Actually, although the CMD tech support people won't
+-    * tell me the details, the 0x03 revision cannot support
+-    * UDMA correctly without hardware modifications, and even
+-    * then it only works with Quantum disks due to some
+-    * hold time assumptions in the 646U part which are fixed
+-    * in the 646U2.
+-    * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
+-    */
+-   if ((id->dma_ultra & 0x0020) && (udma_100) && (udma_66) && (udma_33)) {
+-      speed = XFER_UDMA_5;
+-   } else if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) {
+-      speed = XFER_UDMA_4;
+-   } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) {
+-      speed = XFER_UDMA_3;
+-   } else if ((id->dma_ultra & 0x0004) && (udma_33)) {
+-      speed = XFER_UDMA_2;
+-   } else if ((id->dma_ultra & 0x0002) && (udma_33)) {
+-      speed = XFER_UDMA_1;
+-   } else if ((id->dma_ultra & 0x0001) && (udma_33)) {
+-      speed = XFER_UDMA_0;
+-   } else if (id->dma_mword & 0x0004) {
+-      speed = XFER_MW_DMA_2;
+-   } else if (id->dma_mword & 0x0002) {
+-      speed = XFER_MW_DMA_1;
+-   } else if (id->dma_mword & 0x0001) {
+-      speed = XFER_MW_DMA_0;
+-   } else if (id->dma_1word & 0x0004) {
+-      speed = XFER_SW_DMA_2;
+-   } else if (id->dma_1word & 0x0002) {
+-      speed = XFER_SW_DMA_1;
+-   } else if (id->dma_1word & 0x0001) {
+-      speed = XFER_SW_DMA_0;
+-   } else {
+-      set_pio = 1;
+-   }
+-
+-   if (!drive->init_speed)
+-      drive->init_speed = speed;
+-
+-   config_chipset_for_pio(drive, set_pio);
+-
+-   if (set_pio)
+-      return ((int) ide_dma_off_quietly);
+-
+-   if (cmd64x_tune_chipset(drive, speed))
+-      return ((int) ide_dma_off);
+-
+-   rval = (int)(   ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+-         ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+-         ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+-         ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+-                       ide_dma_off_quietly);
+-
+-   return rval;
+-}
+-
+-static int config_cmd680_chipset_for_dma (ide_drive_t *drive)
+-{
+-   struct hd_driveid *id   = drive->id;
+-   byte udma_66      = eighty_ninty_three(drive);
+-   byte speed      = 0x00;
+-   byte set_pio      = 0x00;
+-   int rval;
+-
+-   if ((id->dma_ultra & 0x0040) && (udma_66))   speed = XFER_UDMA_6;
+-   else if ((id->dma_ultra & 0x0020) && (udma_66))   speed = XFER_UDMA_5;
+-   else if ((id->dma_ultra & 0x0010) && (udma_66))   speed = XFER_UDMA_4;
+-   else if ((id->dma_ultra & 0x0008) && (udma_66))   speed = XFER_UDMA_3;
+-   else if (id->dma_ultra & 0x0004)      speed = XFER_UDMA_2;
+-   else if (id->dma_ultra & 0x0002)      speed = XFER_UDMA_1;
+-   else if (id->dma_ultra & 0x0001)      speed = XFER_UDMA_0;
+-   else if (id->dma_mword & 0x0004)      speed = XFER_MW_DMA_2;
+-   else if (id->dma_mword & 0x0002)      speed = XFER_MW_DMA_1;
+-   else if (id->dma_mword & 0x0001)      speed = XFER_MW_DMA_0;
+-   else {
+-      set_pio = 1;
++   switch(mode) {
++      case 0x04:
++         if (id->dma_ultra & 0x0040)
++            { speed = XFER_UDMA_6; break; }
++      case 0x03:
++         if (id->dma_ultra & 0x0020)
++            { speed = XFER_UDMA_5; break; }
++      case 0x02:
++         if (id->dma_ultra & 0x0010)
++            { speed = XFER_UDMA_4; break; }
++         if (id->dma_ultra & 0x0008)
++            { speed = XFER_UDMA_3; break; }
++      case 0x01:
++         if (id->dma_ultra & 0x0004)
++            { speed = XFER_UDMA_2; break; }
++         if (id->dma_ultra & 0x0002)
++            { speed = XFER_UDMA_1; break; }
++         if (id->dma_ultra & 0x0001)
++            { speed = XFER_UDMA_0; break; }
++      case 0x00:
++         if (id->dma_mword & 0x0004)
++            { speed = XFER_MW_DMA_2; break; }
++         if (id->dma_mword & 0x0002)
++            { speed = XFER_MW_DMA_1; break; }
++         if (id->dma_mword & 0x0001)
++            { speed = XFER_MW_DMA_0; break; }
++         if (id->dma_1word & 0x0004)
++            { speed = XFER_SW_DMA_2; break; }
++         if (id->dma_1word & 0x0002)
++            { speed = XFER_SW_DMA_1; break; }
++         if (id->dma_1word & 0x0001)
++            { speed = XFER_SW_DMA_0; break; }
++      default:
++         { set_pio = 1; break; }
+    }
+ 
+    if (!drive->init_speed)
+@@ -741,7 +794,7 @@
+    if (set_pio)
+       return ((int) ide_dma_off_quietly);
+ 
+-   if (cmd680_tune_chipset(drive, speed))
++   if (hwif->speedproc(drive, speed))
+       return ((int) ide_dma_off);
+ 
+    rval = (int)(   ((id->dma_ultra >> 14) & 3) ? ide_dma_on :
+@@ -750,50 +803,16 @@
+          ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+          ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+                        ide_dma_off_quietly);
+-   return rval;
+-}
+ 
+-static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
+-{
+-   if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680)
+-      return (config_cmd680_chipset_for_dma(drive));
+-   return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66));
++   return rval;
+ }
+ 
+ static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
+ {
+    struct hd_driveid *id   = drive->id;
+    ide_hwif_t *hwif   = HWIF(drive);
+-   struct pci_dev *dev   = hwif->pci_dev;
+-   unsigned int class_rev   = 0;
+-   byte can_ultra_33   = 0;
+-   byte can_ultra_66   = 0;
+-   byte can_ultra_100   = 0;
+-   byte can_ultra_133   = 0;
+    ide_dma_action_t dma_func = ide_dma_on;
+ 
+-   pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+-   class_rev &= 0xff;   
+-
+-   switch(dev->device) {
+-      case PCI_DEVICE_ID_CMD_680:
+-         can_ultra_133 = 1;
+-      case PCI_DEVICE_ID_CMD_649:
+-         can_ultra_100 = 1;
+-      case PCI_DEVICE_ID_CMD_648:
+-         can_ultra_66  = 1;
+-      case PCI_DEVICE_ID_CMD_643:
+-         can_ultra_33  = 1;
+-         break;
+-      case PCI_DEVICE_ID_CMD_646:
+-         can_ultra_33  = (class_rev >= 0x05) ? 1 : 0;
+-         can_ultra_66  = 0;
+-         can_ultra_100 = 0;
+-         break;
+-      default:
+-         return hwif->dmaproc(ide_dma_off, drive);
+-   }
+-
+    if ((id != NULL) && ((id->capability & 1) != 0) &&
+        hwif->autodma && (drive->media == ide_disk)) {
+       /* Consult the list of known "bad" drives */
+@@ -802,10 +821,10 @@
+          goto fast_ata_pio;
+       }
+       dma_func = ide_dma_off_quietly;
+-      if ((id->field_valid & 4) && (can_ultra_33)) {
++      if ((id->field_valid & 4) && cmd64x_ratemask(drive)) {
+          if (id->dma_ultra & 0x007F) {
+             /* Force if Capable UltraDMA */
+-            dma_func = config_chipset_for_dma(drive, class_rev, can_ultra_66);
++            dma_func = config_chipset_for_dma(drive);
+             if ((id->field_valid & 2) &&
+                 (dma_func != ide_dma_on))
+                goto try_dma_modes;
+@@ -815,7 +834,7 @@
+          if ((id->dma_mword & 0x0007) ||
+              (id->dma_1word & 0x0007)) {
+             /* Force if Capable regular DMA modes */
+-            dma_func = config_chipset_for_dma(drive, class_rev, 0);
++            dma_func = config_chipset_for_dma(drive);
+             if (dma_func != ide_dma_on)
+                goto no_dma_set;
+          }
+@@ -824,7 +843,7 @@
+             goto no_dma_set;
+          }
+          /* Consult the list of known "good" drives */
+-         dma_func = config_chipset_for_dma(drive, class_rev, 0);
++         dma_func = config_chi