| 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) |
 2.4.19-pre8-ac3
 ide-2.4.19-p8-ac1.all.convert.10.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 |