diff -urN linux-2.2.10-pristine/CREDITS linux/CREDITS
--- linux-2.2.10-pristine/CREDITS	Tue Jul 20 19:11:29 1999
+++ linux/CREDITS	Thu Jul 22 20:38:42 1999
@@ -91,6 +91,11 @@
 S: Cambridge, Massachusetts 02139
 S: USA
 
+N: Michel Aubry
+E: giovanni <giovanni@sudfr.com>
+D: Aladdin 1533/1543(C) chipset IDE
+D: VIA MVP-3/TX Pro III chipset IDE
+
 N: Jens Axboe
 E: axboe@image.dk
 D: Linux CD-ROM maintainer
@@ -779,6 +784,17 @@
 E: ajh@primag.co.uk
 D: Selection mechanism
 
+N: Andre Hedrick
+E: hedrick@astro.dyer.vanderbilt.edu
+D: Uniform Multi-Platform E-IDE driver
+D: Aladdin 1533/1543(C) chipset IDE
+D: HighPoint HPT343/5 chipset IDE
+D: PIIX chipset IDE
+D: Promise Ultra/33 chipset IDE
+D: Promise Ultra/66 chipset IDE
+S: Nashville, TN
+S: USA
+
 N: Jochen Hein
 E: jochen.hein@delphi.central.de
 P: 1024/4A27F015 25 72 FB E3 85 9F DE 3B  CB 0A DA DA 40 77 05 6C
@@ -942,6 +958,10 @@
 S: 160 00 Praha 6
 S: Czech Republic
 
+N: Andreas S. Krebs
+E: akrebs@altavista.net
+D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
+
 N: Niels Kristian Bech Jensen
 E: nkbj@image.dk
 W: http://www.image.dk/~nkbj
@@ -952,6 +972,15 @@
 S: DK-8230 Åbyhøj
 S: Denmark
 
+N: Andrzej M. Krzysztofowicz
+E: ankry@mif.pg.gda.pl
+D: XT disk driver
+D: Aladdin 1533/1543(C) chipset IDE
+D: PIIX chipset IDE
+S: ul. Matemblewska 1B/10
+S: 80-283 Gdansk
+S: Poland
+
 N: Michael K. Johnson
 E: johnsonm@redhat.com
 W: http://www.redhat.com/~johnsonm
@@ -1743,6 +1772,10 @@
 D: added PCI support to the serial driver
 S: Buckenhof, Germany
 
+N: Michael Schmitz
+E:
+D: Macintosh IDE Driver
+
 N: Martin Schulze
 E: joey@linux.de
 W: http://home.pages.de/~joey/
@@ -2029,6 +2062,9 @@
 D: Frame buffer device and XF68_FBDev maintainer
 D: m68k IDE maintainer
 D: Amiga Zorro maintainer
+D: Amiga Buddha and Catweasel chipset IDE
+D: Atari Falcon chipset IDE
+D: Amiga Gayle chipset IDE
 S: C. Huysmansstraat 12
 S: B-3128 Baal
 S: Belgium
diff -urN linux-2.2.10-pristine/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.10-pristine/Documentation/Configure.help	Tue Jul 20 19:12:15 1999
+++ linux/Documentation/Configure.help	Fri Jul 23 01:14:17 1999
@@ -289,9 +289,9 @@
 Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
 CONFIG_BLK_DEV_IDE
   If you say Y here, you will use the full-featured IDE driver to
-  control up to four IDE interfaces, each being able to serve a
-  "master" and a "slave" device, for a total of up to eight IDE
-  disk/cdrom/tape/floppy drives. People with SCSI-only systems
+  control up to eight IDE interfaces, each being able to serve a
+  "master" and a "slave" device, for a total of up to sixteen (16)
+  IDE disk/cdrom/tape/floppy drives.  People with SCSI-only systems
   can say N here.
 
   Useful information about large (>540 MB) IDE disks, multiple
@@ -370,6 +370,15 @@
   root filesystem (the one containing the directory /) is located on
   the IDE disk. If unsure, say Y.
 
+Use multi-mode by default
+CONFIG_IDEDISK_MULTI_MODE
+  If you get this error, try to enable this option.
+
+  hda: set_multmode: status=0x51 { DriveReady SeekComplete Error }
+  hda: set_multmode: error=0x04 { DriveStatusError }
+
+  If in doubt, say N.
+
 Include IDE/ATAPI CDROM support
 CONFIG_BLK_DEV_IDECD
   If you have a CDROM drive using the ATAPI protocol, say Y. ATAPI is
@@ -396,6 +405,17 @@
   say M here and read Documentation/modules.txt. The module will be
   called ide-cd.o.
 
+Include CD-Changer Reporting
+CONFIG_IDECD_SLOTS
+  If you have an IDE/ATAPI multi-slot cd-changer and you want
+  to report which slots have disk-present, say Y.  If you say Y
+  and there is not a multi-slot cdrom present, this code is skipped.
+
+  This could be the bases of multi-disk access based on multi-mounts.
+  This is still pie-in-the-sky.
+
+  If unsure, say N.
+
 Include IDE/ATAPI TAPE support
 CONFIG_BLK_DEV_IDETAPE
   If you have an IDE tape drive using the ATAPI protocol, say Y.
@@ -526,6 +546,15 @@
 
   It is safe to say Y to this question.
 
+Good-Bad DMA Model-Firmware (EXPERIMENTAL)
+IDEDMA_NEW_DRIVE_LISTINGS
+  This test compares both the model and firmware revision for buggy drives
+  that claim to (U)DMA capable.  This is a blanket on/off test with no speed
+  limit options.  Straight GNU GCC 2.7.3/2.8.X compilers are known to be safe;
+  whereas, many versions of EGCS have a problem and miscompile.
+
+  If in doubt, say N.
+
 Winbond SL82c105 support
 CONFIG_BLK_DEV_SL82C105
   If you have a Winbond SL82c105 IDE controller, say Y here to enable
@@ -542,6 +571,9 @@
   improve the usability of some boot managers such as LILO when
   booting from a drive on an off-board controller.
 
+  Requires that all onboard ide controllers be disabled or calling
+  "pci=reverse" to invert the device scan order.
+
   Note that, if you say Y here, the order of the hd* devices will be
   rearranged which may require modification of fstab and other files.
 
@@ -638,14 +670,28 @@
 
   Please read the comments at the top of drivers/block/ns87415.c.
 
+CY82C693 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_CY82C693
+
+  This driver adds detection and support for the CY82C693 chipset
+  used on Digital's PC-Alpha 164SX boards.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/cy82c693.c
+
 VIA82C586 chipset support (EXPERIMENTAL)
 CONFIG_BLK_DEV_VIA82C586
-  This adds initial timing settings for VIA (U)DMA onboard ide
-  controllers that are ATA3 compliant. May work with ATA4 systems, but
-  not tested to date.
+  This allows you to to configure your chipset for a better use while
+  running (U)DMA: it will allow you to enable efficiently the second
+  channel dma usage, as it is may not be set by BIOS. It allows you to
+  run a kernel command line at boot time in order to set fifo config.
+  If no command line is provided, it will try to set fifo configuration
+  at its best. It will allow you to get a proc/ide/via display
+  (while running a "cat") provided you enabled "proc" support and
+  set DISPLAY_APOLLO_TIMINGS in via82c586.c
 
-  If you say Y here, you also need to say Y to "Use DMA by default
-  when available", above.
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
 
   If unsure, say N.
 
@@ -653,6 +699,134 @@
 CONFIG_BLK_DEV_CMD646
   Say Y here if you have an IDE controller like this.
 
+ALI M15x3 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_ALI15X3
+  This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C
+  onboard chipsets.  It also tests for Simplex mode and enables
+  normal dual channel support.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/alim15x3.c
+
+  If unsure, say N.
+
+PROMISE PDC20246/PDC20262 support
+CONFIG_BLK_DEV_PDC202XX
+  Promise Ultra33 or PDC20246.
+  This driver adds up to 4 more eide devices sharing a single interrupt.
+  This add-on card is a bootable PCI UDMA controller.
+  Since multiple cards can be installed and there are BIOS ROM problems
+  that happen if the BIOS revisions of all installed cards (three-max)
+  do not match.  Should you be unable to make new BIOS chips with a burner,
+  the driver attempts to dynamic tuning of the chipset at boot-time
+  for max-speed.  Ultra33 BIOS 1.25 or new required for more than one card.
+  This card may require "PDC202XX Special UDMA Feature (EXPERIMENTAL)".
+
+  Promise Ultra66 or PDC20262.
+  This driver adds up to 4 more eide devices sharing a single interrupt.
+  This add-on card is a bootable PCI UDMA ATA-66 controller.
+  The driver attempts to dynamic tuning of the chipset at boot-time
+  for max-speed.  Note tested limits are UDMA-2.
+  Ultra66 BIOS 1.11 or newer required.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/pdc202xx.c
+
+  If unsure, say N.
+
+Special UDMA Feature (EXPERIMENTAL)
+PDC202XX_FORCE_BURST_BIT
+  For PDC20246 and PDC20262 Ultra DMA chipsets.
+  Designed originally for PDC20246/Ultra33 that has BIOS setup failures
+  when using 3 or more cards.
+
+   Please read the comments at the top of drivers/block/pdc202xx.c
+
+   If unsure, say N.
+
+Special Mode Feature (DANGEROUS)
+PDC202XX_FORCE_MASTER_MODE
+  For PDC20246 and PDC20262 Ultra DMA chipsets.
+  This is reserved for possible Hardware RAID 0,1 for the FastTrak Series.
+
+  Say N.
+
+AEC6210 chipset support
+CONFIG_BLK_DEV_AEC6210
+  This driver adds up to 4 more eide devices sharing a single interrupt.
+  This add-on card is a bootable PCI UDMA controller.  In order to get this
+  card to initialize correctly in some cases, you should include this driver.
+
+  This prefers CONFIG_IDEDMA_AUTO to be enabled, regardless.
+
+  Please read the comments at the top of drivers/block/aec6210.c
+
+Intel PIIXn chipsets support
+CONFIG_BLK_DEV_PIIX
+  This driver adds PIO mode setting and tuning for all PIIX IDE
+  controllers by Intel.  Since the BIOS can sometimes improperly tune
+  PIO 0-4 mode settings, this allows dynamic tuning of the chipset
+  via the standard end-user tool 'hdparm'.
+
+  Please read the comments at the top of drivers/block/piix.c
+
+  If unsure, say N.
+
+PIIXn Tuning support (EXPERIMENTAL)
+CONFIG_BLK_DEV_PIIX_TUNING
+  This driver extension adds DMA mode setting and tuning for all PIIX IDE
+  controllers by Intel.  Since the BIOS can sometimes improperly setup
+  the device/adapter combination and speed limits, It has become a necessity
+  to back/forward speed devices as needed.
+
+  Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode 2
+  if the BIOS can to perform this task at INIT.
+
+  If unsure, say N.
+
+HPT34X chipset support
+CONFIG_BLK_DEV_HPT34X
+  This driver adds up to 4 more EIDE devices sharing a single
+  interrupt. The HPT343 chipset in its current form is a non-bootable or
+  HPT345/HPT363 chipset is bootable (needs BIOS FIX) PCI UDMA controllers.
+  This driver requires dynamic tuning of the chipset during the ide-probe
+  at boot. It is reported to support DVD II drives, by the manufacturer.
+
+  Please read the comments at the top of drivers/block/hpt34x.c
+
+  If unsure, say N.
+
+HPT34X DMA support (DANGEROUS)
+CONFIG_BLK_DEV_HPT34X_DMA
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/hpt34x.c
+
+  If unsure, say N.
+
+HPT366 chipset support
+CONFIG_BLK_DEV_HPT366
+  This is an Ultra DMA chipset for ATA-66.
+  This driver adds up to 4 more EIDE devices sharing a single
+  interrupt. The HPT366 chipset in its current form is a non-bootable.
+  This driver requires dynamic tuning of the chipset during the ide-probe
+  at boot. It is reported to support DVD II drives, by the manufacturer.
+
+  Please read the comments at the top of drivers/block/hpt366.c
+
+SiS5513 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_SIS5513
+  This driver ensures (U)DMA support for SIS5513 chipset based mainboards.
+  SiS620 UDMA mode 4, SiS5600/5597 UDMA mode 2, all other DMA mode 2 limited
+  chipsets are unsupported to date.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/sis5513.c
+
 QDI QD6580 support
 CONFIG_BLK_DEV_QD6580
   This driver is enabled at runtime using the "ide0=qd6580" kernel
@@ -675,6 +849,68 @@
   of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
   I/O speeds to be set as well. See the files Documentation/ide.txt
   and drivers/block/ali14xx.c for more info.
+
+Amiga builtin Gayle IDE interface support
+CONFIG_BLK_DEV_GAYLE
+  This is the IDE driver for the builtin IDE interface on some Amiga
+  models.  It supports both the `A1200 style' (used in A600 and A1200)
+  and `A4000 style' (used in A4000 and A4000T) of the Gayle IDE interface.
+  Say Y if you have such an Amiga model and want to use IDE devices
+  (hard disks, CD-ROM drives, etc.) that are connected to the builtin
+  IDE interface.
+
+Falcon IDE interface support
+CONFIG_BLK_DEV_FALCON_IDE
+  This is the IDE driver for the builtin IDE interface on the Atari Falcon.
+  Say Y if you have a Falcon and want to use IDE devices (hard disks,
+  CD-ROM drives, etc.) that are connected to the builtin IDE interface.
+
+Amiga Buddha/Catweasel IDE interface support (EXPERIMENTAL)
+CONFIG_BLK_DEV_BUDDHA
+  This is the IDE driver for the IDE interfaces on the Buddha and
+  Catweasel expansion boards.  It supports up to two interfaces on the
+  Buddha and three on the Catweasel.
+  Say Y if you have a Buddha or Catweasel expansion board and want to
+  use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
+  to one of its IDE interfaces.
+
+Amiga IDE Doubler support (EXPERIMENTAL)
+CONFIG_BLK_DEV_IDEDOUBLER
+  This driver provides support for the so called `IDE doublers' (made by
+  various manufacturers, e.g. Eyetech) that can be connected to the
+  builtin IDE interface of some Amiga models. Using such an IDE doubler,
+  you can connect up to four instead of two IDE devices on the Amiga's
+  builtin IDE interface.
+  Note that the normal Amiga Gayle IDE driver may not work correctly if
+  you have an IDE doubler and don't enable this driver!
+  Say Y if you have an IDE doubler.  The driver is enabled at kernel
+  runtime using the "ide=doubler" kernel boot parameter.
+
+ Support for PowerMac IDE devices (must also enable IDE)
+ CONFIG_BLK_DEV_IDE_PMAC
+   No help for CONFIG_BLK_DEV_IDE_PMAC
+
+ PowerMac IDE DMA support
+ CONFIG_BLK_DEV_IDEDMA_PMAC
+   No help for CONFIG_BLK_DEV_IDEDMA_PMAC
+
+ Use DMA by default
+ CONFIG_PMAC_IDEDMA_AUTO
+   No help for CONFIG_PMAC_IDEDMA_AUTO
+
+Macintosh Quadra/Powerbook IDE interface support
+CONFIG_BLK_DEV_MAC_IDE
+  This is the IDE driver for the builtin IDE interface on the some m68k
+  Macintosh models. It supports both the `Quadra style' (used in Quadra/
+  Centris 630 and Performa 588 models) and `Powerbook style' (used in the
+  Powerbook 150 and 190 models) IDE interface.
+  Say Y if you have such an Macintosh model and want to use IDE devices
+  (hard disks, CD-ROM drives, etc.) that are connected to the builtin
+  IDE interface.
+
+ RapIDE interface support
+ CONFIG_BLK_DEV_IDE_RAPIDE
+   No help for CONFIG_BLK_DEV_IDE_RAPIDE
 
 XT hard disk support
 CONFIG_BLK_DEV_XD
diff -urN linux-2.2.10-pristine/Documentation/devices.tex linux/Documentation/devices.tex
--- linux-2.2.10-pristine/Documentation/devices.tex	Tue Jul 20 19:12:14 1999
+++ linux/Documentation/devices.tex	Thu Jul 22 20:38:43 1999
@@ -254,7 +254,9 @@
 \major{86}{}{char }{SCSI media changer}
 \major{87}{}{char }{Sony Control-A1 stereo control bus}
 \major{88}{}{char }{COMX synchronous serial card}
+\major{  }{}{block}{Sixth IDE hard disk/CD-ROM interface}
 \major{89}{}{char }{I$^2$C bus interface}
+\major{  }{}{block}{Seventh IDE hard disk/CD-ROM interface}
 \major{90}{}{char }{Memory Technology Device (RAM, ROM, Flash)}
 \major{91}{}{char }{CAN-Bus controller}
 \major{92}{}{char }{Reserved for ith Kommunikationstechnik MIC ISDN card}
@@ -1746,11 +1748,31 @@
 \end{devicelist}
 
 \begin{devicelist}
+\major{  }{}{block}{Sixth IDE hard disk/CD-ROM interface}
+        \minor{0}{/dev/hdm}{Master: whole disk (or CD-ROM)}
+        \minor{64}{/dev/hdn}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\noindent
+Partitions are handled the same way as for the first interface (see
+major number 3).
+
+\begin{devicelist}
 \major{89}{}{char }{I$^2$C bus interface}
 	\minor{0}{/dev/i2c0}{First I$^2$C adapter}
 	\minor{1}{/dev/i2c1}{Second I$^2$C adapter}
 	\minordots
 \end{devicelist}
+
+\begin{devicelist}
+\major{  }{}{block}{Seventh IDE hard disk/CD-ROM interface}
+        \minor{0}{/dev/hdo}{Master: whole disk (or CD-ROM)}
+        \minor{64}{/dev/hdp}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\noindent
+Partitions are handled the same way as for the first interface (see
+major number 3).
 
 \begin{devicelist}
 \major{90}{}{char }{Memory Technology Device (RAM, ROM, Flash)}
diff -urN linux-2.2.10-pristine/Documentation/devices.txt linux/Documentation/devices.txt
--- linux-2.2.10-pristine/Documentation/devices.txt	Tue Jul 20 19:12:14 1999
+++ linux/Documentation/devices.txt	Thu Jul 22 20:38:43 1999
@@ -1215,10 +1215,24 @@
 		  1 = /dev/comx1	COMX channel 1
 		    ...
 
+    block	Sixth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdm		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdn		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
  89 char	I2C bus interface
 		  0 = /dev/i2c0		First I2C adapter
 		  1 = /dev/i2c1		Second I2C adapter
 		    ...
+
+    block	Seventh IDE hard disk/CD-ROM interface
+		  0 = /dev/hdo		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdp		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
 
  90 char	Memory Technology Device (RAM, ROM, Flash)
 		  0 = /dev/mtd0		First MTD (rw)
diff -urN linux-2.2.10-pristine/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c
--- linux-2.2.10-pristine/arch/mips/lib/ide-no.c	Tue Jul 20 19:12:03 1999
+++ linux/arch/mips/lib/ide-no.c	Thu Jul 22 20:38:43 1999
@@ -11,6 +11,7 @@
  */
 #include <linux/hdreg.h>
 #include <linux/kernel.h>
+#include <asm/hdreg.h>
 #include <asm/ptrace.h>
 #include <asm/ide.h>
 
@@ -24,8 +25,10 @@
 	return 0;
 }
 
-static void no_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
-                                     int *irq)
+static void no_ide_init_hwif_ports (	hw_regs_t *hw,
+					ide_ioreg_t data_port,
+					ide_ioreg_t ctrl_port,
+					int *irq)
 {
 }
 
diff -urN linux-2.2.10-pristine/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c
--- linux-2.2.10-pristine/arch/mips/lib/ide-std.c	Tue Jul 20 19:12:03 1999
+++ linux/arch/mips/lib/ide-std.c	Thu Jul 22 20:38:43 1999
@@ -11,6 +11,7 @@
  */
 #include <linux/hdreg.h>
 #include <asm/ptrace.h>
+#include <asm/hdreg.h>
 #include <asm/ide.h>
 
 static int std_ide_default_irq(ide_ioreg_t base)
@@ -41,15 +42,23 @@
 	}
 }
 
-static void std_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
-                                     int *irq)
+static void std_ide_init_hwif_ports (	hw_regs_t *hw,
+					ide_ioreg_t data_port,
+					ide_ioreg_t ctrl_port,
+					int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- linux-2.2.10-pristine/arch/ppc/kernel/apus_setup.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/apus_setup.c	Thu Jul 22 20:38:43 1999
@@ -561,9 +561,9 @@
 }
 
 __initfunc(void
-apus_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq))
 {
-        m68k_ide_init_hwif_ports(p, base, irq);
+        m68k_ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
 }
 #endif
 
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- linux-2.2.10-pristine/arch/ppc/kernel/chrp_setup.c	Tue Jul 20 19:12:10 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Thu Jul 22 20:38:43 1999
@@ -38,6 +38,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/prom.h>
 #include <asm/gg2.h>
@@ -558,16 +559,23 @@
         ppc_generic_ide_fix_driveid(id);
 }
 
-void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-        ide_ioreg_t port = base;
-        int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-        while (i--)
-                *p++ = port++;
-        *p++ = port;
-        if (irq != NULL)
-                *irq = chrp_ide_irq;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+	}
+	if (irq != NULL)
+		hw->irq = chrp_ide_irq;
 }
 
 EXPORT_SYMBOL(chrp_ide_irq);
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- linux-2.2.10-pristine/arch/ppc/kernel/mbx_setup.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/mbx_setup.c	Thu Jul 22 20:38:43 1999
@@ -380,23 +380,35 @@
         ppc_generic_ide_fix_driveid(id);
 }
 
-void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+mbx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
+
+	*irq = 0;
+
+	if (data_port != 0)	/* Only map the first ATA flash drive */
+		return;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
-	if (irq != NULL)
-		*irq = 0;
 #ifdef ATA_FLASH
-	base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
-	for (i = 0; i < 8; ++i)
-		*p++ = base++;
-	*p = ++base;		/* Does not matter */
+
+	reg = (ide_ioreg_t) ioremap(PCMCIA_MEM_ADDR, 0x200);
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+
+	/* Does not matter */
+
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = reg;
+	}
 	if (irq)
-		*irq = 13;
+		hw->irq = 13;
 #endif
 }
 #endif
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux-2.2.10-pristine/arch/ppc/kernel/pmac_setup.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/pmac_setup.c	Thu Jul 22 20:38:43 1999
@@ -365,7 +365,7 @@
 #ifdef CONFIG_BLK_DEV_IDE_PMAC
 extern int pmac_ide_count;
 extern struct device_node *pmac_ide_node[];
-static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89 };
 
 __initfunc(kdev_t find_ide_boot(void))
 {
@@ -544,7 +544,16 @@
 }
 
 /* This is declared in drivers/block/ide-pmac.c */
-void pmac_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+void pmac_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+void
+ide_init_default_hwifs(void)
+{
+}
 #endif
 
 __initfunc(void
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.2.10-pristine/arch/ppc/kernel/ppc_ksyms.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Thu Jul 22 20:38:43 1999
@@ -13,6 +13,7 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/atomic.h>
 #include <asm/bitops.h>
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- linux-2.2.10-pristine/arch/ppc/kernel/prep_setup.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Thu Jul 22 20:38:43 1999
@@ -39,6 +39,7 @@
 #include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/cache.h>
 #include <asm/dma.h>
@@ -691,14 +692,20 @@
 }
 
 __initfunc(void
-prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq))
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] =  hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- linux-2.2.10-pristine/arch/ppc/kernel/residual.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/residual.c	Thu Jul 22 20:38:43 1999
@@ -46,6 +46,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 
 
diff -urN linux-2.2.10-pristine/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux-2.2.10-pristine/arch/ppc/kernel/setup.c	Tue Jul 20 19:12:11 1999
+++ linux/arch/ppc/kernel/setup.c	Thu Jul 22 20:38:43 1999
@@ -17,6 +17,7 @@
 #include <asm/pmu.h>
 #include <asm/residual.h>
 #include <asm/io.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -160,10 +161,10 @@
 }
   
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 	if (ppc_ide_md.ide_init_hwif != NULL) {
-		ppc_ide_md.ide_init_hwif(p, base, irq);
+		ppc_ide_md.ide_init_hwif(hw, data_port, ctrl_port, irq);
 	}
 }
 #endif
diff -urN linux-2.2.10-pristine/drivers/block/Config.in linux/drivers/block/Config.in
--- linux-2.2.10-pristine/drivers/block/Config.in	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/Config.in	Fri Jul 23 01:12:38 1999
@@ -19,7 +19,13 @@
 else
   bool '   Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE
   dep_tristate '   Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
+  if [ "$CONFIG_BLK_DEV_IDEDISK" != "n" ]; then
+    bool '     Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE
+  fi
   dep_tristate '   Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
+  if [ "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
+    bool '     Include CD-Changer Reporting' CONFIG_IDECD_SLOTS
+  fi
   dep_tristate '   Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
   dep_tristate '   Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
   dep_tristate '   SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
@@ -33,19 +39,52 @@
       bool '   Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI
       if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
         bool '     Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA
-        bool '     Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
         if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
           bool '     Use DMA by default when available' CONFIG_IDEDMA_AUTO
+          if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+            bool '       Good-Bad DMA Model-Firmware (EXPERIMENTAL)' IDEDMA_NEW_DRIVE_LISTINGS
+            define_bool IDEDMA_PCI_EXPERIMENTAL y
+          else
+            define_bool IDEDMA_PCI_EXPERIMENTAL n
+          fi
+        fi
+        bool '     Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
+        bool '     AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210
+        if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
+          bool '     ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
+          bool '     CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
+          bool '     CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693
+        fi
+        bool '     HPT34X chipset support' CONFIG_BLK_DEV_HPT34X
+        if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \
+             "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then
+          bool '       HPT34X DMA support (DANGEROUS)' CONFIG_BLK_DEV_HPT34X_DMA
+        fi
+        bool '     HPT366 chipset support' CONFIG_BLK_DEV_HPT366
+        bool '     Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
+        if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \
+             "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
+          bool '       PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING
+        fi
+        if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
+          bool '     NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
         fi
         if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
           bool '     OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621
-          if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
-            bool '     Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
-            bool '     NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
-            bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
-            bool '     CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
+        fi
+        if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
+          bool '     PROMISE PDC20246/PDC20262 support' CONFIG_BLK_DEV_PDC202XX
+          if [ "$CONFIG_EXPERIMENTAL" = "y" -a \
+               "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then
+            bool '       Special UDMA Feature (EXPERIMENTAL)' PDC202XX_FORCE_BURST_BIT
+            bool '       Special Mode Feature (DANGEROUS)' PDC202XX_FORCE_MASTER_MODE
           fi
         fi
+        if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
+          bool '     SiS5513 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_SIS5513
+          bool '     Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
+          bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+        fi
       fi
       if [ "$CONFIG_PPC" = "y" ]; then
           bool '   Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
@@ -68,14 +107,28 @@
       bool '     ALI M14xx support' CONFIG_BLK_DEV_ALI14XX
       bool '     DTC-2278 support' CONFIG_BLK_DEV_DTC2278
       bool '     Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
+      if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a \
+           "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool '     PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
+      fi
       bool '     QDI QD6580 support' CONFIG_BLK_DEV_QD6580
       bool '     UMC-8672 support' CONFIG_BLK_DEV_UMC8672
+    fi
+    if [ "$CONFIG_AMIGA" = "y" ]; then
+      bool '   Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-        if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" ]; then
-        bool '     PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
-	 fi
+        bool '   Amiga IDE Doubler support' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE
       fi
     fi
+    if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool '   Buddha/Catweasel IDE interface support' CONFIG_BLK_DEV_BUDDHA
+    fi
+    if [ "$CONFIG_ATARI" = "y" ]; then
+      bool '   Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE
+    fi
+    if [ "$CONFIG_MAC" = "y" ]; then
+      bool '   Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE
+    fi
   fi
 fi
 if [ "$CONFIG_MCA" = "y" ]; then
@@ -127,6 +180,21 @@
 dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARIDE_PARPORT
 if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   source drivers/block/paride/Config.in
+fi
+
+if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
+     "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
+     "$CONFIG_BLK_DEV_CMD640" = "y" -o \
+     "$CONFIG_BLK_DEV_CY82C693" = "y" -o \
+     "$CONFIG_BLK_DEV_HPT34X" = "y" -o \
+     "$CONFIG_BLK_DEV_HPT366" = "y" -o \
+     "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \
+     "$CONFIG_BLK_DEV_OPTI621" = "y" -o \
+     "$CONFIG_BLK_DEV_PIIX" = "y" -o \
+     "$CONFIG_BLK_DEV_SIS5513" = "y" ]; then
+  define_bool CONFIG_BLK_DEV_IDE_MODES y
+else
+  define_bool CONFIG_BLK_DEV_IDE_MODES n
 fi
 
 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
diff -urN linux-2.2.10-pristine/drivers/block/MAKEDEV-IDE45 linux/drivers/block/MAKEDEV-IDE45
--- linux-2.2.10-pristine/drivers/block/MAKEDEV-IDE45	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/MAKEDEV-IDE45	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,99 @@
+#!/bin/sh
+#
+#	Andre Hedrick <hedrick@astro.dyer.vanderbilt.edu>
+#
+#	The song goes, "I did it the hard way..........."
+#
+
+if [ ! -f /dev/hdi ]; then \
+	echo "Making IDE4 Primary Devices hdi's"; \
+	mknod /dev/hdi b 56 0; \
+	mknod /dev/hdi1 b 56 1; \
+	mknod /dev/hdi2 b 56 2; \
+	mknod /dev/hdi3 b 56 3; \
+	mknod /dev/hdi4 b 56 4; \
+	mknod /dev/hdi5 b 56 5; \
+	mknod /dev/hdi6 b 56 6; \
+	mknod /dev/hdi7 b 56 7; \
+	mknod /dev/hdi8 b 56 8; \
+	mknod /dev/hdi9 b 56 9; \
+	mknod /dev/hdi10 b 56 10; \
+	mknod /dev/hdi11 b 56 11; \
+	mknod /dev/hdi12 b 56 12; \
+	mknod /dev/hdi13 b 56 13; \
+	mknod /dev/hdi14 b 56 14; \
+	mknod /dev/hdi15 b 56 15; \
+	mknod /dev/hdi16 b 56 16; \
+	chown root.disk /dev/hdi*; \
+	chmod 660 /dev/hdi*; \
+fi
+
+if [ ! -f /dev/hdj ]; then \
+	echo "Making IDE4 Secondary Devices hdj's"; \
+	mknod /dev/hdj b 56 64; \
+	mknod /dev/hdj1 b 56 65; \
+	mknod /dev/hdj2 b 56 66; \
+	mknod /dev/hdj3 b 56 67; \
+	mknod /dev/hdj4 b 56 68; \
+	mknod /dev/hdj5 b 56 69; \
+	mknod /dev/hdj6 b 56 70; \
+	mknod /dev/hdj7 b 56 71; \
+	mknod /dev/hdj8 b 56 72; \
+	mknod /dev/hdj9 b 56 73; \
+	mknod /dev/hdj10 b 56 74; \
+	mknod /dev/hdj11 b 56 75; \
+	mknod /dev/hdj12 b 56 76; \
+	mknod /dev/hdj13 b 56 77; \
+	mknod /dev/hdj14 b 56 78; \
+	mknod /dev/hdj15 b 56 79; \
+	mknod /dev/hdj16 b 56 80; \
+	chown root.disk /dev/hdj*; \
+	chmod 660 /dev/hdj*; \
+fi
+
+if [ ! -f /dev/hdk ]; then \
+	echo "Making IDE5 Primary Devices hdk's"; \
+	mknod /dev/hdk b 57 0; \
+	mknod /dev/hdk1 b 57 1; \
+	mknod /dev/hdk2 b 57 2; \
+	mknod /dev/hdk3 b 57 3; \
+	mknod /dev/hdk4 b 57 4; \
+	mknod /dev/hdk5 b 57 5; \
+	mknod /dev/hdk6 b 57 6; \
+	mknod /dev/hdk7 b 57 7; \
+	mknod /dev/hdk8 b 57 8; \
+	mknod /dev/hdk9 b 57 9; \
+	mknod /dev/hdk10 b 57 10; \
+	mknod /dev/hdk11 b 57 11; \
+	mknod /dev/hdk12 b 57 12; \
+	mknod /dev/hdk13 b 57 13; \
+	mknod /dev/hdk14 b 57 14; \
+	mknod /dev/hdk15 b 57 15; \
+	mknod /dev/hdk16 b 57 16; \
+	chown root.disk /dev/hdk*; \
+	chmod 660 /dev/hdk*; \
+fi
+
+if [ ! -f /dev/hdl ]; then \
+	echo "Making IDE5 Secondary Devices hdl's"; \
+	mknod /dev/hdl b 57 64; \
+	mknod /dev/hdl1 b 57 65; \
+	mknod /dev/hdl2 b 57 66; \
+	mknod /dev/hdl3 b 57 67; \
+	mknod /dev/hdl4 b 57 68; \
+	mknod /dev/hdl5 b 57 69; \
+	mknod /dev/hdl6 b 57 70; \
+	mknod /dev/hdl7 b 57 71; \
+	mknod /dev/hdl8 b 57 72; \
+	mknod /dev/hdl9 b 57 73; \
+	mknod /dev/hdl10 b 57 74; \
+	mknod /dev/hdl11 b 57 75; \
+	mknod /dev/hdl12 b 57 76; \
+	mknod /dev/hdl13 b 57 77; \
+	mknod /dev/hdl14 b 57 78; \
+	mknod /dev/hdl15 b 57 79; \
+	mknod /dev/hdl16 b 57 80; \
+	chown root.disk /dev/hdl*; \
+	chmod 660 /dev/hdl*; \
+fi
+
diff -urN linux-2.2.10-pristine/drivers/block/MAKEDEV-IDE67 linux/drivers/block/MAKEDEV-IDE67
--- linux-2.2.10-pristine/drivers/block/MAKEDEV-IDE67	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/MAKEDEV-IDE67	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,99 @@
+#!/bin/sh
+#
+#	Andre Hedrick <hedrick@astro.dyer.vanderbilt.edu>
+#
+#	The song goes, "I did it the hard way..........."
+#
+
+if [ ! -f /dev/hdm ]; then \
+	echo "Making IDE6 Primary Devices hdm's"; \
+	mknod /dev/hdm b 88 0; \
+	mknod /dev/hdm1 b 88 1; \
+	mknod /dev/hdm2 b 88 2; \
+	mknod /dev/hdm3 b 88 3; \
+	mknod /dev/hdm4 b 88 4; \
+	mknod /dev/hdm5 b 88 5; \
+	mknod /dev/hdm6 b 88 6; \
+	mknod /dev/hdm7 b 88 7; \
+	mknod /dev/hdm8 b 88 8; \
+	mknod /dev/hdm9 b 88 9; \
+	mknod /dev/hdm10 b 88 10; \
+	mknod /dev/hdm11 b 88 11; \
+	mknod /dev/hdm12 b 88 12; \
+	mknod /dev/hdm13 b 88 13; \
+	mknod /dev/hdm14 b 88 14; \
+	mknod /dev/hdm15 b 88 15; \
+	mknod /dev/hdm16 b 88 16; \
+	chown root.disk /dev/hdm*; \
+	chmod 660 /dev/hdm*; \
+fi
+
+if [ ! -f /dev/hdn ]; then \
+	echo "Making IDE6 Secondary Devices hdn's"; \
+	mknod /dev/hdn b 88 64; \
+	mknod /dev/hdn1 b 88 65; \
+	mknod /dev/hdn2 b 88 66; \
+	mknod /dev/hdn3 b 88 67; \
+	mknod /dev/hdn4 b 88 68; \
+	mknod /dev/hdn5 b 88 69; \
+	mknod /dev/hdn6 b 88 70; \
+	mknod /dev/hdn7 b 88 71; \
+	mknod /dev/hdn8 b 88 72; \
+	mknod /dev/hdn9 b 88 73; \
+	mknod /dev/hdn10 b 88 74; \
+	mknod /dev/hdn11 b 88 75; \
+	mknod /dev/hdn12 b 88 76; \
+	mknod /dev/hdn13 b 88 77; \
+	mknod /dev/hdn14 b 88 78; \
+	mknod /dev/hdn15 b 88 79; \
+	mknod /dev/hdn16 b 88 80; \
+	chown root.disk /dev/hdn*; \
+	chmod 660 /dev/hdn*; \
+fi
+
+if [ ! -f /dev/hdo ]; then \
+	echo "Making IDE7 Primary Devices hdo's"; \
+	mknod /dev/hdo b 89 0; \
+	mknod /dev/hdo1 b 89 1; \
+	mknod /dev/hdo2 b 89 2; \
+	mknod /dev/hdo3 b 89 3; \
+	mknod /dev/hdo4 b 89 4; \
+	mknod /dev/hdo5 b 89 5; \
+	mknod /dev/hdo6 b 89 6; \
+	mknod /dev/hdo7 b 89 7; \
+	mknod /dev/hdo8 b 89 8; \
+	mknod /dev/hdo9 b 89 9; \
+	mknod /dev/hdo10 b 89 10; \
+	mknod /dev/hdo11 b 89 11; \
+	mknod /dev/hdo12 b 89 12; \
+	mknod /dev/hdo13 b 89 13; \
+	mknod /dev/hdo14 b 89 14; \
+	mknod /dev/hdo15 b 89 15; \
+	mknod /dev/hdo16 b 89 16; \
+	chown root.disk /dev/hdo*; \
+	chmod 660 /dev/hdo*; \
+fi
+
+if [ ! -f /dev/hdp ]; then \
+	echo "Making IDE7 Secondary Devices hdp's"; \
+	mknod /dev/hdp b 89 64; \
+	mknod /dev/hdp1 b 89 65; \
+	mknod /dev/hdp2 b 89 66; \
+	mknod /dev/hdp3 b 89 67; \
+	mknod /dev/hdp4 b 89 68; \
+	mknod /dev/hdp5 b 89 69; \
+	mknod /dev/hdp6 b 89 70; \
+	mknod /dev/hdp7 b 89 71; \
+	mknod /dev/hdp8 b 89 72; \
+	mknod /dev/hdp9 b 89 73; \
+	mknod /dev/hdp10 b 89 74; \
+	mknod /dev/hdp11 b 89 75; \
+	mknod /dev/hdp12 b 89 76; \
+	mknod /dev/hdp13 b 89 77; \
+	mknod /dev/hdp14 b 89 78; \
+	mknod /dev/hdp15 b 89 79; \
+	mknod /dev/hdp16 b 89 80; \
+	chown root.disk /dev/hdp*; \
+	chmod 660 /dev/hdp*; \
+fi
+
diff -urN linux-2.2.10-pristine/drivers/block/Makefile linux/drivers/block/Makefile
--- linux-2.2.10-pristine/drivers/block/Makefile	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/Makefile	Thu Jul 22 20:38:43 1999
@@ -158,12 +158,60 @@
 IDE_OBJS += via82c586.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_GAYLE),y)
+IDE_OBJS += gayle.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y)
+IDE_OBJS += falconide.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_MAC_IDE),y)
+IDE_OBJS += macide.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_BUDDHA),y)
+IDE_OBJS += buddha.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_CMD646),y)
 IDE_OBJS += cmd646.o
 endif
 
 ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
 IDE_OBJS += sl82c105.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_ALI15X3),y)
+IDE_OBJS += alim15x3.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_CY82C693),y)
+IDE_OBJS += cy82c693.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_PIIX),y)
+IDE_OBJS += piix.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_PDC202XX),y)
+IDE_OBJS += pdc202xx.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_AEC6210),y)
+IDE_OBJS += aec6210.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_HPT34X),y)
+IDE_OBJS += hpt34x.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_HPT366),y)
+IDE_OBJS += hpt366.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_SIS5513),y)
+IDE_OBJS += sis5513.o
 endif
 
 ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
diff -urN linux-2.2.10-pristine/drivers/block/aec6210.c linux/drivers/block/aec6210.c
--- linux-2.2.10-pristine/drivers/block/aec6210.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/aec6210.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,63 @@
+/*
+ * linux/drivers/block/aec6210.c	Version 0.01	Nov 17, 1998
+ *
+ * Copyright (C) 1998	Andre Hedrick (hedrick@astro.dyer.vanderbilt.edu)
+ *
+ *  pio 0 ::       40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02
+ *  pio 1 ::       40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
+ *  pio 2 ::       40: 08 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
+ *  pio 3 ::       40: 03 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  pio 4 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  dma 0 ::       40: 0a 07 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  dma 1 ::       40: 02 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  dma 2 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 00 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * udma 0 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * udma 1 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * udma 2 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * auto   ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * auto   ::       40: 01 04 01 04 01 04 01 04 02 05 a6 cf 00 02 00 02
+ *                 50: ff ff ff ff aa 06 04 00 00 00 00 00 00 00 00 00
+ *
+ *                 NO-Devices
+ *                 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02
+ *                 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00
+ */
+
+#include <linux/config.h>	/* for CONFIG_BLK_DEV_IDEPCI */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+__initfunc(unsigned int pci_init_aec6210 (struct pci_dev *dev, const char *name))
+{
+	if (dev->rom_address) {
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS,
+			dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+		printk("%s: ROM enabled at 0x%08lx\n",
+			name, dev->rom_address);
+	}
+	return dev->irq;
+}
diff -urN linux-2.2.10-pristine/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c
--- linux-2.2.10-pristine/drivers/block/ali14xx.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ali14xx.c	Thu Jul 22 20:38:43 1999
@@ -47,8 +47,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /* port addresses for auto-detection */
diff -urN linux-2.2.10-pristine/drivers/block/alim15x3.c linux/drivers/block/alim15x3.c
--- linux-2.2.10-pristine/drivers/block/alim15x3.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/alim15x3.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,409 @@
+/*
+ * linux/drivers/block/alim15x3.c	Version 0.05	Jun. 29, 1999
+ *
+ *  Copyright (C) 1998-99 Michel Aubry, Maintainer
+ *  Copyright (C) 1998-99 Andrzej Krzysztofowicz, Maintainer
+ *  Copyright (C) 1998-99 Andre Hedrick, Integrater and Maintainer
+ *
+ *  (U)DMA capable version of ali 1533/1543(C)
+ *
+ *  Default disable (U)DMA on all devices execpt hard disks.
+ *  This measure of overkill is needed to stablize the chipset code.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define DISPLAY_ALI_TIMINGS
+
+#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy);
+extern int (*ali_display_info)(char *, char **, off_t, int, int);  /* ide-proc.c */
+struct pci_dev *bmide_dev;
+
+char *fifo[4] = {
+	"FIFO Off",
+	"FIFO On ",
+	"DMA mode",
+	"PIO mode" };
+
+char *udmaT[8] = {
+	"1.5T",
+	"  2T",
+	"2.5T",
+	"  3T",
+	"3.5T",
+	"  4T",
+	"  6T",
+	"  8T"
+};
+
+char *channel_status[8] = {
+	"OK            ",
+	"busy          ",
+	"DRQ           ",
+	"DRQ busy      ",
+	"error         ",
+	"error busy    ",
+	"error DRQ     ",
+	"error DRQ busy"
+};
+#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+static void ali15x3_tune_drive (ide_drive_t *drive, byte pio)
+{
+	ide_pio_data_t d;
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = hwif->pci_dev;
+	int s_time, a_time, c_time;
+	byte s_clc, a_clc, r_clc;
+	unsigned long flags;
+	int bus_speed = ide_system_bus_speed();
+	int port = hwif->index ? 0x5c : 0x58;
+
+	pio = ide_get_best_pio_mode(drive, pio, 5, &d);
+	s_time = ide_pio_timings[pio].setup_time;
+	a_time = ide_pio_timings[pio].active_time;
+	if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
+		s_clc = 0;
+	if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
+		a_clc = 0;
+	c_time = ide_pio_timings[pio].cycle_time;
+
+#if 0
+	if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16)
+		r_clc = 0;
+#endif
+
+	if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
+		r_clc = 1;
+	} else {
+		if (r_clc >= 16)
+		r_clc = 0;
+	}
+	save_flags(flags);
+	cli();
+	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);
+
+	/*
+	 * setup   active  rec
+	 * { 70,   165,    365 },   PIO Mode 0
+	 * { 50,   125,    208 },   PIO Mode 1
+	 * { 30,   100,    110 },   PIO Mode 2
+	 * { 30,   80,     70  },   PIO Mode 3 with IORDY
+	 * { 25,   70,     25  },   PIO Mode 4 with IORDY  ns
+	 * { 20,   50,     30  }    PIO Mode 5 with IORDY (nonstandard)
+	 */
+
+}
+
+__initfunc(unsigned int pci_init_ali15x3 (struct pci_dev *dev, const char *name))
+{
+	byte confreg0 = 0, confreg1 =0, progif = 0;
+	int errors = 0;
+
+	if (pci_read_config_byte(dev, 0x50, &confreg1))
+		goto veryspecialsettingserror;
+	if (!(confreg1 & 0x02))
+		if (pci_write_config_byte(dev, 0x50, confreg1 | 0x02))
+			goto veryspecialsettingserror;
+
+	if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif))
+		goto veryspecialsettingserror;
+	if (!(progif & 0x40)) {
+		/*
+		 * The way to enable them is to set progif
+		 * writable at 0x4Dh register, and set bit 6
+		 * of progif to 1:
+		 */
+		if (pci_read_config_byte(dev, 0x4d, &confreg0))
+			goto veryspecialsettingserror;
+		if (confreg0 & 0x80)
+			if (pci_write_config_byte(dev, 0x4d, confreg0 & ~0x80))
+				goto veryspecialsettingserror;
+		if (pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x40))
+			goto veryspecialsettingserror;
+		if (confreg0 & 0x80)
+			if (pci_write_config_byte(dev, 0x4d, confreg0))
+				errors++;
+	}
+
+	if ((pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) || (!(progif & 0x40)))
+		goto veryspecialsettingserror;
+
+	printk("%s: enabled read of IDE channels state (en/dis-abled) %s.\n",
+		name, errors ? "with Error(s)" : "Succeeded" );
+	return 0;
+
+veryspecialsettingserror:
+	printk("%s: impossible to enable read of IDE channels state (en/dis-abled)!\n", name);
+	return 0;
+}
+
+int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			if (drive->media == ide_cdrom) {
+				ide_hwif_t *hwif	= HWIF(drive);
+				struct pci_dev *dev	= hwif->pci_dev;
+				struct hd_driveid *id	= drive->id;
+				byte cd_dma_fifo	= 0;
+
+				pci_read_config_byte(dev, 0x53, &cd_dma_fifo);
+
+				if (((id->field_valid & 4) || (id->field_valid & 2)) &&
+				    (id->capability & 1) && hwif->autodma) {
+					unsigned long dma_set_bit  = hwif->dma_base + 2;
+#if 0
+					if (cd_dma_fifo & 0x02)
+						pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x02);
+					pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01);
+#else
+					pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01|0x02);
+#endif
+					if (drive->select.b.unit & 0x01) {
+						outb(inb(dma_set_bit)|0x40, dma_set_bit);
+					} else {
+						outb(inb(dma_set_bit)|0x20, dma_set_bit);
+					}
+				} else {
+					if (cd_dma_fifo & 0x01)
+						pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x01);
+					pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x02);
+				}
+			} else if (drive->media != ide_disk) {
+				return ide_dmaproc(ide_dma_off_quietly, drive);
+			}
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+__initfunc(void ide_init_ali15x3 (ide_hwif_t *hwif))
+{
+	struct pci_dev *dev;
+	byte ideic, inmir, iderev;
+	byte irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
+				      1, 11, 0, 12, 0, 14, 0, 15 };
+
+	pci_read_config_byte(hwif->pci_dev, PCI_REVISION_ID, &iderev);
+
+	hwif->irq = hwif->channel ? 15 : 14;
+	for (dev = pci_devices; dev; dev=dev->next) /* look for ISA bridge */
+		if (dev->vendor==PCI_VENDOR_ID_AL &&
+		    dev->device==PCI_DEVICE_ID_AL_M1533)
+			break;
+	if (dev) {			
+		pci_read_config_byte(dev, 0x58, &ideic);
+		ideic = ideic & 0x03;
+		if ((hwif->channel && ideic == 0x03) ||
+		    (!hwif->channel && !ideic)) {
+			pci_read_config_byte(dev, 0x44, &inmir);
+			inmir = inmir & 0x0f;
+			hwif->irq = irq_routing_table[inmir];
+		} else
+			if (hwif->channel && !(ideic & 0x01)) {
+				pci_read_config_byte(dev, 0x75, &inmir);
+				inmir = inmir & 0x0f;
+				hwif->irq = irq_routing_table[inmir];
+			}
+	}
+#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
+	bmide_dev = hwif->pci_dev;
+	ali_display_info = &ali_get_info;
+#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+	hwif->tuneproc = &ali15x3_tune_drive;
+	if ((hwif->dma_base) && (iderev >= 0xC1)) {
+		/* M1543C or newer for DMAing */
+		hwif->dmaproc = &ali15x3_dmaproc;
+	} else {
+		hwif->autodma = 0;
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+	return;
+}
+
+#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy)
+{
+	byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1;
+	unsigned int bibma;
+	byte c0, c1;
+	byte rev, tmp;
+	char *p = buffer;
+	char *q;
+
+	/* fetch rev. */
+	pci_read_config_byte(bmide_dev, 0x08, &rev);
+	if (rev >= 0xc1)	/* M1543C or newer */
+		udmaT[7] = " ???";
+	else
+		fifo[3]  = "   ???  ";
+
+	/* first fetch bibma: */
+	pci_read_config_dword(bmide_dev, 0x20, &bibma);
+	bibma = (bibma & 0xfff0) ;
+	/*
+	 * 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);
+
+	p += sprintf(p,
+		"\n                                Ali M15x3 Chipset.\n");
+	p += sprintf(p,
+		"                                ------------------\n");
+	pci_read_config_byte(bmide_dev, 0x78, &reg53h);
+	p += sprintf(p, "PCI Clock: %d.\n", reg53h);
+
+	pci_read_config_byte(bmide_dev, 0x53, &reg53h);
+	p += sprintf(p,
+		"CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
+		(reg53h & 0x02) ? "Yes" : "No ",
+		(reg53h & 0x01) ? "Yes" : "No " );
+	pci_read_config_byte(bmide_dev, 0x74, &reg53h);
+	p += sprintf(p,
+		"FIFO Status: contains %d Words, runs%s%s\n\n",
+		(reg53h & 0x3f),
+		(reg53h & 0x40) ? " OVERWR" : "",
+		(reg53h & 0x80) ? " OVERRD." : "." );
+
+	p += sprintf(p,
+		"-------------------primary channel-------------------secondary channel---------\n\n");
+
+	pci_read_config_byte(bmide_dev, 0x09, &reg53h);
+	p += sprintf(p,
+		"channel status:       %s                               %s\n",
+		(reg53h & 0x20) ? "On " : "Off",
+		(reg53h & 0x10) ? "On " : "Off" );
+
+	p += sprintf(p,
+		"both channels togth:  %s                               %s\n",
+		(c0&0x80) ? "No " : "Yes",
+		(c1&0x80) ? "No " : "Yes" );
+
+	pci_read_config_byte(bmide_dev, 0x76, &reg53h);
+	p += sprintf(p,
+		"Channel state:        %s                    %s\n",
+		channel_status[reg53h & 0x07],
+		channel_status[(reg53h & 0x70) >> 4] );
+
+	pci_read_config_byte(bmide_dev, 0x58, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);
+	p += sprintf(p,
+		"Add. Setup Timing:    %dT                                %dT\n",
+		(reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
+		(reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
+
+	pci_read_config_byte(bmide_dev, 0x59, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);
+	p += sprintf(p,
+		"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");
+	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 " );
+
+	pci_read_config_byte(bmide_dev, 0x54, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x55, &reg5yh);
+	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);
+		} else {
+			p += sprintf(p, q,
+				(reg5xh & 0x03) + 12,
+				((reg5xh & 0x30)>>4) + 12,
+				(reg5yh & 0x03) + 12,
+				((reg5yh & 0x30)>>4) + 12 );
+		}
+	} else {
+		p += sprintf(p, q,
+			(tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4,
+			(tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4,
+			(tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4,
+			(tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4 );
+	}
+
+#if 0
+	p += sprintf(p, 
+		"FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n",
+		(reg5xh & 0x03) + 12,
+		((reg5xh & 0x30)>>4) + 12,
+		(reg5yh & 0x03) + 12,
+		((reg5yh & 0x30)>>4) + 12 );
+#endif
+
+	p += sprintf(p,
+		"FIFO mode:        %s         %s          %s         %s\n",
+		fifo[((reg5xh & 0x0c) >> 2)],
+		fifo[((reg5xh & 0xc0) >> 6)],
+		fifo[((reg5yh & 0x0c) >> 2)],
+		fifo[((reg5yh & 0xc0) >> 6)] );
+
+	pci_read_config_byte(bmide_dev, 0x5a, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);
+	pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);
+	pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);
+
+	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",
+		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+		(reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
+		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
+		(reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
+		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+		(reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
+		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
+		(reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
+
+	p += sprintf(p,
+		"-----------------------------------UDMA Timings--------------------------------\n\n");
+
+	pci_read_config_byte(bmide_dev, 0x56, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x57, &reg5yh);
+	p += sprintf(p,
+		"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",
+		(reg5yh & 0x80) ? "OK" : "No",
+		udmaT[(reg5xh & 0x07)],
+		udmaT[(reg5xh & 0x70) >> 4],
+		udmaT[reg5yh & 0x07],
+		udmaT[(reg5yh & 0x70) >> 4] );
+
+	return p-buffer; /* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
diff -urN linux-2.2.10-pristine/drivers/block/buddha.c linux/drivers/block/buddha.c
--- linux-2.2.10-pristine/drivers/block/buddha.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/buddha.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,161 @@
+/*
+ *  linux/drivers/block/buddha.c -- Amiga Buddha and Catweasel IDE Driver
+ *
+ *	Copyright (C) 1997 by Geert Uytterhoeven
+ *
+ *  This driver was written by based on the specifications in README.buddha.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  TODO:
+ *    - test it :-)
+ *    - tune the timings using the speed-register
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/zorro.h>
+#include <linux/ide.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  The Buddha has 2 IDE interfaces, the Catweasel has 3
+     */
+
+#define BUDDHA_NUM_HWIFS	2
+#define CATWEASEL_NUM_HWIFS	3
+
+
+    /*
+     *  Bases of the IDE interfaces (relative to the board address)
+     */
+
+#define BUDDHA_BASE1	0x800
+#define BUDDHA_BASE2	0xa00
+#define BUDDHA_BASE3	0xc00
+
+static const u_int buddha_bases[CATWEASEL_NUM_HWIFS] = {
+    BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
+};
+
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define BUDDHA_DATA	0x00
+#define BUDDHA_ERROR	0x06		/* see err-bits */
+#define BUDDHA_NSECTOR	0x0a		/* nr of sectors to read/write */
+#define BUDDHA_SECTOR	0x0e		/* starting sector */
+#define BUDDHA_LCYL	0x12		/* starting cylinder */
+#define BUDDHA_HCYL	0x16		/* high byte of starting cyl */
+#define BUDDHA_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+#define BUDDHA_STATUS	0x1e		/* see status-bits */
+#define BUDDHA_CONTROL	0x11a
+
+static int buddha_offsets[IDE_NR_PORTS] = {
+    BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+    BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL
+};
+
+
+    /*
+     *  Other registers
+     */
+
+#define BUDDHA_IRQ1	0xf00		/* MSB = 1, Harddisk is source of */
+#define BUDDHA_IRQ2	0xf40		/* interrupt */
+#define BUDDHA_IRQ3	0xf80
+
+static const int buddha_irqports[CATWEASEL_NUM_HWIFS] = {
+    BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
+};
+
+#define BUDDHA_IRQ_MR	0xfc0		/* master interrupt enable */
+
+
+    /*
+     *  Board information
+     */
+
+static u_long buddha_board = 0;
+static int buddha_num_hwifs = -1;
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int buddha_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    return 1;
+}
+
+
+    /*
+     *  Any Buddha or Catweasel boards present?
+     */
+
+static int find_buddha(void)
+{
+    u_int key;
+    const struct ConfigDev *cd;
+
+    buddha_num_hwifs = 0;
+    if ((key = zorro_find(ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA, 0, 0)))
+	buddha_num_hwifs = BUDDHA_NUM_HWIFS;
+    else if ((key = zorro_find(ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL, 0,
+			       0)))
+	buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
+    if (key) {
+	cd = zorro_get_board(key);
+	buddha_board = (u_long)cd->cd_BoardAddr;
+	if (buddha_board) {
+	    buddha_board = ZTWO_VADDR(buddha_board);
+	    /* write to BUDDHA_IRQ_MR to enable the board IRQ */
+	    *(char *)(buddha_board+BUDDHA_IRQ_MR) = 0;
+	    zorro_config_board(key, 0);
+	}
+    }
+    return buddha_num_hwifs;
+}
+
+
+    /*
+     *  Probe for a Buddha or Catweasel IDE interface
+     *  We support only _one_ of them, no multiple boards!
+     */
+
+void buddha_init(void)
+{
+    hw_regs_t hw;
+    int i, index;
+
+    if (buddha_num_hwifs < 0 && !find_buddha())
+	return;
+
+    for (i = 0; i < buddha_num_hwifs; i++) {
+	ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+buddha_bases[i]),
+			buddha_offsets, 0,
+			(ide_ioreg_t)(buddha_board+buddha_irqports[i]),
+			buddha_ack_intr, IRQ_AMIGA_PORTS);
+	index = ide_register_hw(&hw, NULL);
+	if (index != -1)
+	    printk("ide%d: %s IDE interface\n", index,
+		   buddha_num_hwifs == BUDDHA_NUM_HWIFS ? "Buddha" :
+		   					  "Catweasel");
+    }
+}
diff -urN linux-2.2.10-pristine/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- linux-2.2.10-pristine/drivers/block/cmd640.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/cmd640.c	Thu Jul 22 20:38:43 1999
@@ -110,8 +110,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -urN linux-2.2.10-pristine/drivers/block/cmd646.c linux/drivers/block/cmd646.c
--- linux-2.2.10-pristine/drivers/block/cmd646.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/cmd646.c	Thu Jul 22 20:38:43 1999
@@ -1,4 +1,4 @@
-/* $Id: cmd646.c,v 1.11 1998/12/13 08:36:54 davem Exp $
+/* $Id: cmd646.c,v 1.13 1999/05/27 04:49:38 davem Exp $
  * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Note, this driver is not used at all on other systems because
  *           there the "BIOS" has done all of the following already.
@@ -12,8 +12,10 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
 
 static int cmd646_config_drive_for_dma(ide_drive_t *drive)
 {
@@ -43,14 +45,14 @@
 }
 
 /* This is fun.  -DaveM */
-#define IDE_SETXFER		0x03
-#define IDE_SETFEATURE		0xef
-#define IDE_DMA2_ENABLE		0x22
-#define IDE_DMA1_ENABLE		0x21
-#define IDE_DMA0_ENABLE		0x20
-#define IDE_UDMA2_ENABLE	0x42
-#define IDE_UDMA1_ENABLE	0x41
-#define IDE_UDMA0_ENABLE	0x40
+#define IDE_SETXFER		SETFEATURES_XFER
+#define IDE_SETFEATURE		WIN_SETFEATURES
+#define IDE_DMA2_ENABLE		XFER_MW_DMA_2
+#define IDE_DMA1_ENABLE		XFER_MW_DMA_1
+#define IDE_DMA0_ENABLE		XFER_MW_DMA_0
+#define IDE_UDMA2_ENABLE	XFER_UDMA_2
+#define IDE_UDMA1_ENABLE	XFER_UDMA_1
+#define IDE_UDMA0_ENABLE	XFER_UDMA_0
 
 static __inline__ unsigned char dma2_bits_to_command(unsigned char bits)
 {
@@ -92,6 +94,9 @@
 
 static void cmd646_do_setfeature(ide_drive_t *drive, byte command)
 {
+#if 0
+	(void) ide_config_drive_speed(drive, command);
+#else
 	unsigned long flags;
 	byte old_select;
 
@@ -114,6 +119,7 @@
 out:
 	OUT_BYTE(old_select, IDE_SELECT_REG);
 	restore_flags(flags);
+#endif
 }
 
 static void cmd646_dma2_enable(ide_drive_t *drive, unsigned long dma_base)
@@ -212,10 +218,36 @@
 	return ide_dmaproc(func, drive);
 }
 
+/*
+ * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
+ * event order for DMA transfers.
+ */
+static int cmd646_1_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	byte dma_stat;
+
+	if (func == ide_dma_end) {
+		drive->waiting_for_dma = 0;
+		dma_stat = inb(dma_base+2);		/* get DMA status */
+		outb(inb(dma_base)&~1, dma_base);	/* stop DMA */
+		outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
+		return (dma_stat & 7) != 4;	/* verify good DMA status */
+	}
+
+	/* Other cases are done by generic IDE-DMA code. */
+	return cmd646_dmaproc(func, drive);
+}
+
 __initfunc(void ide_init_cmd646 (ide_hwif_t *hwif))
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned char mrdmode;
+	unsigned int class_rev;
+
+	pci_read_config_dword(hwif->pci_dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
 
 	hwif->chipset = ide_cmd646;
 
@@ -247,5 +279,11 @@
 	(void) pci_write_config_byte(dev, 0x58, 0x3f);
 	(void) pci_write_config_byte(dev, 0x5b, 0x3f);
 
-	hwif->dmaproc = &cmd646_dmaproc;
+	if (hwif->dma_base) {
+		if (class_rev == 0x01) {
+			hwif->dmaproc = &cmd646_1_dmaproc;
+		} else {
+			hwif->dmaproc = &cmd646_dmaproc;
+		}
+	}
 }
diff -urN linux-2.2.10-pristine/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c
--- linux-2.2.10-pristine/drivers/block/cy82c693.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/cy82c693.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,432 @@
+/*
+ * linux/drivers/block/cy82c693.c	Version 0.33	Jan. 23, 1999
+ *
+ *  Copyright (C) 1998, 1999 Andreas S. Krebs (akrebs@altavista.net), Maintainer
+ *  Copyright (C) 1998 Andre Hedrick, Integrater
+ *
+ * CYPRESS CY82C693 chipset IDE controller
+ *
+ * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
+ * Writting the driver was quite simple, since most of the job is
+ * done by the generic pci-ide support. 
+ * The hard part was finding the CY82C693's datasheet on Cypress's
+ * web page :-(. But Altavista solved this problem :-).
+ *
+ *
+ * Notes:
+ * - I recently got a 16.8G IBM DTTA, so I was able to test it with
+ *   a large and fast disk - the results look great, so I'd say the
+ *   driver is working fine :-)
+ *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA 
+ * - this is my first linux driver, so there's probably a lot  of room 
+ *   for optimizations and bug fixing, so feel free to do it.
+ * - use idebus=xx parameter to set PCI bus speed - needed to calc
+ *   timings for PIO modes (default will be 40)
+ * - if using PIO mode it's a good idea to set the PIO mode and 
+ *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
+ * - I had some problems with my IBM DHEA with PIO modes < 2
+ *   (lost interrupts) ?????
+ * - first tests with DMA look okay, they seem to work, but there is a
+ *   problem with sound - the BusMaster IDE TimeOut should fixed this
+ *
+ *
+ * History:
+ * ASK@1999-01-23: v0.33 made a few minor code clean ups
+ *                       removed DMA clock speed setting by default
+ *                       added boot message
+ * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut
+ *                       added support to set DMA Controller Clock Speed
+ * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes on some drive
+ * ASK@1998-10-29: v0.3 added support to set DMA modes
+ * ASK@1998-10-28: v0.2 added support to set PIO modes
+ * ASK@1998-10-27: v0.1 first version - chipset detection
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+/* the current version */
+#define CY82_VERSION	"CY82C693U driver v0.33 99-01-23 Andreas S. Krebs (akrebs@altavista.net)"
+
+/*
+ *	The following are used to debug the driver.
+ */
+#define	CY82C693_DEBUG_LOGS	0
+#define	CY82C693_DEBUG_INFO	0
+
+/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */
+#undef CY82C693_SETDMA_CLOCK
+
+/*
+ * note: the value for busmaster timeout is tricky and i got it by trial and error !
+ *       using a to low value will cause DMA timeouts and drop IDE performance
+ *       using a to high value will cause audio playback to scatter
+ *       if you know a better value or how to calc it, please let me know 
+ */
+#define BUSMASTER_TIMEOUT	0x50	/* twice the value written in cy82c693ub datasheet */
+/*
+ * the value above was tested on my machine and it seems to work okay
+ */
+
+/* here are the offset definitions for the registers */
+#define CY82_IDE_CMDREG		0x04
+#define CY82_IDE_ADDRSETUP	0x48
+#define CY82_IDE_MASTER_IOR	0x4C	
+#define CY82_IDE_MASTER_IOW	0x4D	
+#define CY82_IDE_SLAVE_IOR	0x4E	
+#define CY82_IDE_SLAVE_IOW	0x4F
+#define CY82_IDE_MASTER_8BIT	0x50	
+#define CY82_IDE_SLAVE_8BIT	0x51	
+
+#define CY82_INDEX_PORT		0x22
+#define CY82_DATA_PORT		0x23
+
+#define CY82_INDEX_CTRLREG1	0x01
+#define CY82_INDEX_CHANNEL0	0x30
+#define CY82_INDEX_CHANNEL1	0x31
+#define CY82_INDEX_TIMEOUT	0x32
+
+/* the max PIO mode - from datasheet */
+#define CY82C693_MAX_PIO	4
+
+/* the min and max PCI bus speed in MHz - from datasheet */
+#define CY82C963_MIN_BUS_SPEED	25
+#define CY82C963_MAX_BUS_SPEED	33
+
+/* the struct for the PIO mode timings */
+typedef struct pio_clocks_s {
+        byte	address_time;		/* Address setup (clocks) */
+	byte	time_16r;		/* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
+	byte	time_16w;		/* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
+	byte	time_8;			/* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
+} pio_clocks_t;
+
+/*
+ * calc clocks using bus_speed
+ * returns (rounded up) time in bus clocks for time in ns
+ */
+static int calc_clk (int time, int bus_speed)
+{
+	int clocks;
+
+	clocks = (time*bus_speed+999)/1000 -1;
+
+	if (clocks < 0)
+		clocks = 0;
+
+	if (clocks > 0x0F)
+		clocks = 0x0F;
+
+	return clocks;
+}
+
+/*
+ * compute the values for the clock registers for PIO
+ * mode and pci_clk [MHz] speed
+ *
+ * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
+ *       for mode 3 and 4 drives 8 and 16-bit timings are the same
+ *
+ */ 
+static void compute_clocks (byte pio, pio_clocks_t *p_pclk)
+{
+	int clk1, clk2;
+	int bus_speed;
+
+	bus_speed = ide_system_bus_speed();	/* get speed of PCI bus */
+	/* we don't check against CY82C693's min and max speed,
+	 * so you can play with the idebus=xx parameter
+	 */
+
+	if (pio > CY82C693_MAX_PIO)
+		pio = CY82C693_MAX_PIO;
+
+	/* let's calc the address setup time clocks */
+	p_pclk->address_time = (byte)calc_clk(ide_pio_timings[pio].setup_time, bus_speed);
+
+	/* let's calc the active and recovery time clocks */
+	clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed);
+
+	/* calc recovery timing */
+	clk2 =	ide_pio_timings[pio].cycle_time -
+		ide_pio_timings[pio].active_time -
+		ide_pio_timings[pio].setup_time;
+
+	clk2 = calc_clk(clk2, bus_speed);
+
+	clk1 = (clk1<<4)|clk2;	/* combine active and recovery clocks */
+
+	/* note: we use the same values for 16bit IOR and IOW
+         *	those are all the same, since I don't have other
+	 *	timings than those from ide_modes.h
+	 */
+
+	p_pclk->time_16r = (byte)clk1;
+	p_pclk->time_16w = (byte)clk1;
+
+	/* what are good values for 8bit ?? */
+	p_pclk->time_8 = (byte)clk1;
+}
+
+/*
+ * set DMA mode a specific channel for CY82C693
+ */
+static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
+{
+        byte index;
+	byte data;
+
+        if (mode>2)	/* make sure we set a valid mode */
+		mode = 2;
+			   
+	if (mode > drive->id->tDMA)  /* to be absolutly sure we have a valid mode */
+		mode = drive->id->tDMA;
+	
+        index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
+
+#if CY82C693_DEBUG_LOGS
+       	/* for debug let's show the previous values */
+
+	OUT_BYTE(index, CY82_INDEX_PORT);
+	data = IN_BYTE(CY82_DATA_PORT);
+
+	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, (data&0x3), ((data>>2)&1));
+#endif /* CY82C693_DEBUG_LOGS */
+
+	data = (byte)mode|(byte)(single<<2);
+
+	OUT_BYTE(index, CY82_INDEX_PORT);
+	OUT_BYTE(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, mode, single);
+#endif /* CY82C693_DEBUG_INFO */
+
+	/* 
+	 * note: below we set the value for Bus Master IDE TimeOut Register
+	 * I'm not absolutly sure what this does, but it solved my problem
+	 * with IDE DMA and sound, so I now can play sound and work with
+	 * my IDE driver at the same time :-)
+	 *
+	 * If you know the correct (best) value for this register please
+	 * let me know - ASK
+	 */
+
+	data = BUSMASTER_TIMEOUT;
+	OUT_BYTE(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+	OUT_BYTE(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO	
+	printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", drive->name, data);
+#endif /* CY82C693_DEBUG_INFO */
+}
+
+/* 
+ * used to set DMA mode for CY82C693 (single and multi modes)
+ */
+static int cy82c693_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	/*
+	 * if the function is dma on, set dma mode for drive everything
+	 * else is done by the defaul func
+	 */
+	if (func == ide_dma_on) {
+		struct hd_driveid *id = drive->id;
+
+#if CY82C693_DEBUG_INFO
+		printk (KERN_INFO "dma_on: %s\n", drive->name);
+#endif /* CY82C693_DEBUG_INFO */
+
+		if (id != NULL) {		
+                       /* Enable DMA on any drive that has DMA (multi or single) enabled */
+                       if (id->field_valid & 2) {       /* regular DMA */
+			       int mmode, smode;
+
+			       mmode = id->dma_mword & (id->dma_mword >> 8);
+			       smode = id->dma_1word & (id->dma_1word >> 8);
+			       		      
+		               if (mmode != 0)
+				     cy82c693_dma_enable(drive, (mmode >> 1), 0); /* enable multi */
+			       else if (smode != 0)
+				     cy82c693_dma_enable(drive, (smode >> 1), 1); /* enable single */
+			}
+		}
+	}
+        return ide_dmaproc(func, drive);
+}
+
+/*
+ * tune ide drive - set PIO mode
+ */
+static void cy82c693_tune_drive (ide_drive_t *drive, byte pio)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = hwif->pci_dev;
+	pio_clocks_t pclk;
+	unsigned int addrCtrl;
+
+	/* select primary or secondary channel */
+	if (hwif->index > 0)  /* drive is on the secondary channel */
+		dev = dev->next;
+
+#if CY82C693_DEBUG_LOGS
+	/* for debug let's show the register values */
+	
+       	if (drive->select.b.unit == 0) {
+		/*
+		 * get master drive registers               	
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+	  	pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);                
+		addrCtrl &= 0x0F;
+
+		/* now let's get the remaining registers */
+		pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r);
+		pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w);
+		pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8);
+	} else {
+		/*
+		 * set slave drive registers
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+		addrCtrl &= 0xF0;
+		addrCtrl >>= 4;
+
+		/* now let's get the remaining registers */
+		pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r);
+		pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w);
+		pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
+	}
+
+	printk (KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+#endif /* CY82C693_DEBUG_LOGS */
+
+        /* first let's calc the pio modes */
+	pio = ide_get_best_pio_mode(drive, pio, CY82C693_MAX_PIO, NULL);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "%s: Selected PIO mode %d\n", drive->name, pio);
+#endif /* CY82C693_DEBUG_INFO */
+
+        compute_clocks(pio, &pclk);  /* let's calc the values for this PIO mode */
+
+	/* now let's write  the clocks registers */
+	if (drive->select.b.unit == 0) {
+		/*
+		 * set master drive
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+		
+		addrCtrl &= (~0xF);
+		addrCtrl |= (unsigned int)pclk.address_time;
+		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+
+		/* now let's set the remaining registers */
+		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
+		
+		addrCtrl &= 0xF;
+	} else {
+		/*
+		 * set slave drive
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+		addrCtrl &= (~0xF0);
+		addrCtrl |= ((unsigned int)pclk.address_time<<4);
+		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+
+		/* now let's set the remaining registers */
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
+
+		addrCtrl >>= 4;
+		addrCtrl &= 0xF;
+	}	
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+#endif /* CY82C693_DEBUG_INFO */
+}
+
+/*
+ * this function is called during init and is used to setup the cy82c693 chip
+ */
+static void init_cy82c693_chip (struct pci_dev *dev)
+{
+	static int initDone = 0;
+#ifdef CY82C693_SETDMA_CLOCK
+        byte data;
+#endif /* CY82C693_SETDMA_CLOCK */ 
+
+	if (initDone != 0)	/* only perform setup once */
+		return;
+	initDone = 1;
+
+	/* write info about this verion of the driver */
+	printk (KERN_INFO CY82_VERSION "\n");
+
+#ifdef CY82C693_SETDMA_CLOCK
+       /* okay let's set the DMA clock speed */
+        
+        OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+        data = IN_BYTE(CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "CY82U693: Peripheral Configuration Register: 0x%X\n", data);
+#endif /* CY82C693_DEBUG_INFO */
+
+        /*
+	 * for some reason sometimes the DMA controller
+	 * speed is set to ATCLK/2 ???? - we fix this here
+	 * 
+	 * note: i don't know what causes this strange behaviour,
+	 *       but even changing the dma speed doesn't solve it :-(
+	 *       the ide performance is still only half the normal speed 
+	 * 
+	 *       if anybody knows what goes wrong with my machine, please
+	 *       let me know - ASK
+         */
+
+	data |= 0x03;
+
+        OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+        OUT_BYTE(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "CY82U693: New Peripheral Configuration Register: 0x%X\n", data);
+#endif /* CY82C693_DEBUG_INFO */
+
+#endif /* CY82C693_SETDMA_CLOCK */ 
+}
+
+/*
+ * the init function - called for each ide channel once
+ */
+__initfunc(void ide_init_cy82c693(ide_hwif_t *hwif))
+{
+	hwif->chipset = ide_cy82c693;
+	if (hwif->dma_base)
+		hwif->dmaproc = &cy82c693_dmaproc;
+	hwif->tuneproc = &cy82c693_tune_drive;
+
+	init_cy82c693_chip(hwif->pci_dev);
+}
+
diff -urN linux-2.2.10-pristine/drivers/block/dtc2278.c linux/drivers/block/dtc2278.c
--- linux-2.2.10-pristine/drivers/block/dtc2278.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/dtc2278.c	Thu Jul 22 20:38:43 1999
@@ -14,8 +14,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -urN linux-2.2.10-pristine/drivers/block/falconide.c linux/drivers/block/falconide.c
--- linux-2.2.10-pristine/drivers/block/falconide.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/falconide.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,66 @@
+/*
+ *  linux/drivers/block/falconide.c -- Atari Falcon IDE Driver
+ *
+ *     Created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atari_stdma.h>
+
+
+    /*
+     *  Base of the IDE interface
+     */
+
+#define ATA_HD_BASE	0xfff00000
+
+    /*
+     *  Offsets from the above base
+     */
+
+#define ATA_HD_DATA	0x00
+#define ATA_HD_ERROR	0x05		/* see err-bits */
+#define ATA_HD_NSECTOR	0x09		/* nr of sectors to read/write */
+#define ATA_HD_SECTOR	0x0d		/* starting sector */
+#define ATA_HD_LCYL	0x11		/* starting cylinder */
+#define ATA_HD_HCYL	0x15		/* high byte of starting cyl */
+#define ATA_HD_SELECT	0x19		/* 101dhhhh , d=drive, hhhh=head */
+#define ATA_HD_STATUS	0x1d		/* see status-bits */
+#define ATA_HD_CONTROL	0x39
+
+static int falconide_offsets[IDE_NR_PORTS] = {
+    ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL,
+    ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1
+};
+
+
+    /*
+     *  Probe for a Falcon IDE interface
+     */
+
+void falconide_init(void)
+{
+    if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
+	hw_regs_t hw;
+	int index;
+
+	ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets,
+			0, 0, NULL, IRQ_MFP_IDE);
+	index = ide_register_hw(&hw, NULL);
+
+	if (index != -1)
+	    printk("ide%d: Falcon IDE interface\n", index);
+    }
+}
diff -urN linux-2.2.10-pristine/drivers/block/gayle.c linux/drivers/block/gayle.c
--- linux-2.2.10-pristine/drivers/block/gayle.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/gayle.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,169 @@
+/*
+ *  linux/drivers/block/gayle.c -- Amiga Gayle IDE Driver
+ *
+ *     Created 9 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define GAYLE_BASE_4000	0xdd2020	/* A4000/A4000T */
+#define GAYLE_BASE_1200	0xda0000	/* A1200/A600 */
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define GAYLE_DATA	0x00
+#define GAYLE_ERROR	0x06		/* see err-bits */
+#define GAYLE_NSECTOR	0x0a		/* nr of sectors to read/write */
+#define GAYLE_SECTOR	0x0e		/* starting sector */
+#define GAYLE_LCYL	0x12		/* starting cylinder */
+#define GAYLE_HCYL	0x16		/* high byte of starting cyl */
+#define GAYLE_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+#define GAYLE_STATUS	0x1e		/* see status-bits */
+#define GAYLE_CONTROL	0x101a
+
+static int gayle_offsets[IDE_NR_PORTS] = {
+    GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
+    GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
+};
+
+
+    /*
+     *  These are at different offsets from the base
+     */
+
+#define GAYLE_IRQ_4000	0xdd3020	/* MSB = 1, Harddisk is source of */
+#define GAYLE_IRQ_1200	0xda9000	/* interrupt */
+
+
+    /*
+     *  Offset of the secondary port for IDE doublers
+     *  Note that GAYLE_CONTROL is NOT available then!
+     */
+
+#define GAYLE_NEXT_PORT	0x1000
+
+#ifndef CONFIG_BLK_DEV_IDEDOUBLER
+#define GAYLE_NUM_HWIFS		1
+#define GAYLE_NUM_PROBE_HWIFS	GAYLE_NUM_HWIFS
+#define GAYLE_HAS_CONTROL_REG	1
+#else /* CONFIG_BLK_DEV_IDEDOUBLER */
+#define GAYLE_NUM_HWIFS		2
+#define GAYLE_NUM_PROBE_HWIFS	(ide_doubler ? GAYLE_NUM_HWIFS : \
+					       GAYLE_NUM_HWIFS-1)
+#define GAYLE_HAS_CONTROL_REG	(!ide_doubler)
+int ide_doubler = 0;	/* support IDE doublers? */
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    return 1;
+}
+
+static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+    outb(0x7c | (ch & 0x03), hwif->io_ports[IDE_IRQ_OFFSET]);
+    return 1;
+}
+
+    /*
+     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+     */
+
+void gayle_init(void)
+{
+    int a4000, i;
+
+    if (!MACH_IS_AMIGA)
+	return;
+
+    if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE))
+	return;
+
+    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+	ide_ioreg_t base, ctrlport, irqport;
+	ide_ack_intr_t *ack_intr;
+	hw_regs_t hw;
+	int index;
+
+	if (a4000) {
+	    base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_4000);
+	    irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000);
+	    ack_intr = gayle_ack_intr_a4000;
+	} else {
+	    base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_1200);
+	    irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200);
+	    ack_intr = gayle_ack_intr_a1200;
+	}
+
+	if (GAYLE_HAS_CONTROL_REG)
+	    ctrlport = base + GAYLE_CONTROL;
+	else
+	    ctrlport = 0;
+
+	base += i*GAYLE_NEXT_PORT;
+
+	ide_setup_ports(&hw, base, gayle_offsets,
+			ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS);
+
+	index = ide_register_hw(&hw, NULL);
+	if (index != -1) {
+	    switch (i) {
+		case 0:
+		    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
+			   a4000 ? 4000 : 1200);
+		    break;
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+		case 1:
+		    printk("ide%d: IDE doubler\n", index);
+		    break;
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+	    }
+	}
+#if 1 /* TESTING */
+	if (i == 1) {
+	    volatile u_short *addr = (u_short *)base;
+	    u_short data;
+	    printk("+++ Probing for IDE doubler... ");
+	    *addr = 0xffff;
+	    data = *addr;
+	    printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data);
+	}
+#endif /* TESTING */
+    }
+}
diff -urN linux-2.2.10-pristine/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-2.2.10-pristine/drivers/block/genhd.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/genhd.c	Fri Jul 23 01:08:48 1999
@@ -83,6 +83,10 @@
 	 * This requires special handling here.
 	 */
 	switch (hd->major) {
+		case IDE7_MAJOR:
+			unit += 2;
+		case IDE6_MAJOR:
+			unit += 2;
 		case IDE5_MAJOR:
 			unit += 2;
 		case IDE4_MAJOR:
diff -urN linux-2.2.10-pristine/drivers/block/hpt34x.c linux/drivers/block/hpt34x.c
--- linux-2.2.10-pristine/drivers/block/hpt34x.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/hpt34x.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,413 @@
+/*
+ * linux/drivers/block/hpt34x.c		Version 0.25	July 11, 1999
+ *
+ * Copyright (C) 1998-99	Andre Hedrick
+ *
+ * 00:12.0 Unknown mass storage controller:
+ * Triones Technologies, Inc.
+ * Unknown device 0003 (rev 01)
+ *
+ * hde: UDMA 2 (0x0000 0x0002) (0x0000 0x0010)
+ * hdf: UDMA 2 (0x0002 0x0012) (0x0010 0x0030)
+ * hde: DMA 2  (0x0000 0x0002) (0x0000 0x0010)
+ * hdf: DMA 2  (0x0002 0x0012) (0x0010 0x0030)
+ * hdg: DMA 1  (0x0012 0x0052) (0x0030 0x0070)
+ * hdh: DMA 1  (0x0052 0x0252) (0x0070 0x00f0)
+ *
+ * drive_number
+ *	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#ifndef SPLIT_BYTE
+#define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
+#endif
+
+#define HPT343_DEBUG_DRIVE_INFO		0
+#define HPT343_DISABLE_ALL_DMAING	0
+#define HPT343_DMA_DISK_ONLY		0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static void hpt34x_clear_chipset (ide_drive_t *drive)
+{
+	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	unsigned int reg1	= 0, tmp1 = 0;
+	unsigned int reg2	= 0, tmp2 = 0;
+
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
+	tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
+	tmp2 = ((0x00 << drive_number) | reg2);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+}
+
+static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	int			err;
+	byte			hi_speed, lo_speed;
+	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	unsigned int reg1	= 0, tmp1 = 0;
+	unsigned int reg2	= 0, tmp2 = 0;
+
+	SPLIT_BYTE(speed, hi_speed, lo_speed);
+
+	if (hi_speed & 7) {
+		hi_speed = (hi_speed & 4) ? 0x01 : 0x10;
+	} else {
+		lo_speed <<= 5;
+		lo_speed >>= 5;
+	}
+
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
+	tmp1 = ((lo_speed << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
+	tmp2 = ((hi_speed << drive_number) | reg2);
+	err = ide_config_drive_speed(drive, speed);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+
+#if HPT343_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \
+		" (0x%02x 0x%02x) 0x%04x\n",
+		drive->name, ide_xfer_verbose(speed),
+		drive_number, reg1, tmp1, reg2, tmp2,
+		hi_speed, lo_speed, err);
+#endif /* HPT343_DEBUG_DRIVE_INFO */
+
+	return(err);
+}
+
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS.  Initally for designed for
+ * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc.
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	byte speed		= 0x00;
+
+#if HPT343_DISABLE_ALL_DMAING
+	return ((int) ide_dma_off);
+#elif HPT343_DMA_DISK_ONLY
+	if (drive->media != ide_disk)
+		return ((int) ide_dma_off_quietly);
+#endif /* HPT343_DISABLE_ALL_DMAING */
+
+	if (id->dma_ultra & 0x0010) {
+		goto backspeed;
+	} else if (id->dma_ultra & 0x0008) {
+		goto backspeed;
+	} else if (id->dma_ultra & 0x0004) {
+backspeed:
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_2;
+	} else if (id->dma_ultra & 0x0002) {
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_1;
+	} else if (id->dma_ultra & 0x0001) {
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		if (!((id->dma_mword >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0101;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		if (!((id->dma_1word >> 8) & 2)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		if (!((id->dma_1word >> 8) & 1)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_0;
+        } else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) hpt34x_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 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 : 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) hpt34x_tune_chipset(drive, speed);
+}
+
+static void hpt34x_tune_drive (ide_drive_t *drive, byte pio)
+{
+	byte speed;
+
+	hpt34x_clear_chipset(drive);
+	switch(pio) {
+		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 = XFER_PIO_0;break;
+	}
+	(void) hpt34x_tune_chipset(drive, speed);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_dma_action_t dma_func = ide_dma_on;
+
+	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x0007) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+
+		config_chipset_for_pio(drive);
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ *
+ * This is specific to the HPT343 UDMA bios-less chipset
+ * and HPT345 UDMA bios chipset (stamped HPT363)
+ * by HighPoint|Triones Technologies, Inc.
+ */
+
+int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			hpt34x_clear_chipset(drive);
+			return config_drive_xfer_rate(drive);
+#if 0
+		case ide_dma_off:
+		case ide_dma_off_quietly:
+		case ide_dma_on:
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		case ide_dma_read:
+		case ide_dma_write:
+		case ide_dma_begin:
+		case ide_dma_end:
+		case ide_dma_test_irq:
+#endif
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+/*
+ * If the BIOS does not set the IO base addaress to XX00, 343 will fail.
+ */
+#define	HPT34X_PCI_INIT_REG		0x80
+
+__initfunc(unsigned int pci_init_hpt34x (struct pci_dev *dev, const char *name))
+{
+	int i;
+	unsigned short cmd;
+	unsigned long hpt34xIoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+#if 0
+	unsigned char misc10 = inb(hpt34xIoBase + 0x0010);
+	unsigned char misc11 = inb(hpt34xIoBase + 0x0011);
+#endif
+
+	pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00);
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO);
+
+	dev->base_address[0] = (hpt34xIoBase + 0x20);
+	dev->base_address[1] = (hpt34xIoBase + 0x34);
+	dev->base_address[2] = (hpt34xIoBase + 0x28);
+	dev->base_address[3] = (hpt34xIoBase + 0x3c);
+
+	for(i=0; i<4; i++)
+		dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+
+	/*
+	 * Since 20-23 can be assigned and are R/W, we correct them.
+	 */
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->base_address[0]);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->base_address[1]);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->base_address[2]);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->base_address[3]);
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+#if 0
+	outb(misc10|0x78, (hpt34xIoBase + 0x0010));
+	outb(misc11, (hpt34xIoBase + 0x0011));
+#endif
+
+#ifdef DEBUG
+	printk("%s: 0x%02x 0x%02x\n",
+		(pcicmd & PCI_COMMAND_MEMORY) ? "HPT345" : name,
+		inb(hpt34xIoBase + 0x0010),
+		inb(hpt34xIoBase + 0x0011));
+#endif
+
+	if (cmd & PCI_COMMAND_MEMORY) {
+		if (dev->rom_address) {
+			pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+			printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->rom_address);
+		}
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
+	} else {
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+	}
+	return dev->irq;
+}
+
+__initfunc(void ide_init_hpt34x (ide_hwif_t *hwif))
+{
+	hwif->tuneproc = &hpt34x_tune_drive;
+	if (hwif->dma_base) {
+		unsigned short pcicmd = 0;
+
+		pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
+#ifdef CONFIG_BLK_DEV_HPT34X_DMA
+		hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+#endif /* CONFIG_BLK_DEV_HPT34X_DMA */
+		hwif->dmaproc = &hpt34x_dmaproc;
+	} else {
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+}
diff -urN linux-2.2.10-pristine/drivers/block/hpt366.c linux/drivers/block/hpt366.c
--- linux-2.2.10-pristine/drivers/block/hpt366.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/hpt366.c	Fri Jul 23 01:58:51 1999
@@ -0,0 +1,502 @@
+/*
+ * linux/drivers/block/hpt366.c		Version 0.08	July 23, 1999
+ *
+ * Copyright (C) 1999			Andre Hedrick
+ *
+ * RMA@maxtor.com
+ *
+ * drive_number
+ *	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+/*
+ * "Maxtor ", "Maxtor ", "Maxtor ",
+ * "Maxtor ", "Maxtor ", "Maxtor ",
+ * "Maxtor ", "Maxtor ", "Maxtor ",
+ */
+
+const char *bad_maxtor_udma_drives[] = {
+	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
+	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+	"Maxtor 90510D4",
+	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
+	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+	NULL
+};
+
+struct chipset_bus_clock_list_entry {
+	byte		xfer_speed;
+	unsigned int	chipset_settings;
+};
+
+struct chipset_bus_clock_list_entry forty_base [] = {
+
+	{	XFER_UDMA_4	,	0x900fd943	},
+	{	XFER_UDMA_3	,	0x900ad943	},
+	{	XFER_UDMA_2	,	0x900bd943	},
+	{	XFER_UDMA_1	,	0x9008d943	},
+	{	XFER_UDMA_0	,	0x9008d943	},
+
+	{	XFER_MW_DMA_2	,	0xa008d943	},
+	{	XFER_MW_DMA_1	,	0xa010d955	},
+	{	XFER_MW_DMA_0	,	0xa010d9fc	},
+
+	{	XFER_PIO_4	,	0xc008d963	},
+	{	XFER_PIO_3	,	0xc010d974	},
+	{	XFER_PIO_2	,	0xc010d997	},
+	{	XFER_PIO_1	,	0xc010d9c7	},
+	{	XFER_PIO_0	,	0xc018d9d9	},
+	{	0		,	0x0120d9d9	}
+};
+
+struct chipset_bus_clock_list_entry thirty_three_base [] = {
+
+	{	XFER_UDMA_4	,	0x90c9a731	},
+	{	XFER_UDMA_3	,	0x90cfa731	},
+	{	XFER_UDMA_2	,	0x90caa731	},
+	{	XFER_UDMA_1	,	0x90cba731	},
+	{	XFER_UDMA_0	,	0x90c8a731	},
+
+	{	XFER_MW_DMA_2	,	0xa0c8a731	},
+	{	XFER_MW_DMA_1	,	0xa0c8a732	},	/* 0xa0c8a733 */
+	{	XFER_MW_DMA_0	,	0xa0c8a797	},
+
+	{	XFER_PIO_4	,	0xc0c8a731	},
+	{	XFER_PIO_3	,	0xc0c8a742	},
+	{	XFER_PIO_2	,	0xc0d0a753	},
+	{	XFER_PIO_1	,	0xc0d0a7a3	},	/* 0xc0d0a793 */
+	{	XFER_PIO_0	,	0xc0d0a7aa	},	/* 0xc0d0a7a7 */
+	{	0		,	0x0120a7a7	}
+};
+
+struct chipset_bus_clock_list_entry twenty_five_base [] = {
+
+	{	XFER_UDMA_4	,	0x90c98521	},
+	{	XFER_UDMA_3	,	0x90cf8521	},
+	{	XFER_UDMA_2	,	0x90cf8521	},
+	{	XFER_UDMA_1	,	0x90cb8521	},
+	{	XFER_UDMA_0	,	0x90cb8521	},
+
+	{	XFER_MW_DMA_2	,	0xa0ca8521	},
+	{	XFER_MW_DMA_1	,	0xa0ca8532	},
+	{	XFER_MW_DMA_0	,	0xa0ca8575	},
+
+	{	XFER_PIO_4	,	0xc0ca8521	},
+	{	XFER_PIO_3	,	0xc0ca8532	},
+	{	XFER_PIO_2	,	0xc0ca8542	},
+	{	XFER_PIO_1	,	0xc0d08572	},
+	{	XFER_PIO_0	,	0xc0d08585	},
+	{	0		,	0x01208585	}
+};
+
+#define HPT366_DEBUG_DRIVE_INFO		0
+#define HPT366_ALLOW_MAXTOR_ATA33_0	0
+#define HPT366_ALLOW_MAXTOR_ATA33_1	0
+#define HPT366_ALLOW_MAXTOR_ATA33_2	0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+int check_maxtor_drive_lists (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	const char **list = bad_maxtor_udma_drives;
+
+	while (*list) {
+		if (!strcmp(*list++,id->model)) {
+			printk("%s: Broken ASIC, BackSpeeding (U)DMA for %s\n", drive->name, id->model);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+	for ( ; chipset_table->xfer_speed ; chipset_table++)
+		if (chipset_table->xfer_speed == speed)
+			return chipset_table->chipset_settings;
+	return 0x01208585;
+}
+
+static void hpt366_clear_chipset (ide_drive_t *drive)
+{
+	byte		busclock;
+	unsigned int	raw_reg;
+	byte regtime	= (drive->select.b.unit & 0x01) ? 0x43 : 0x40;
+	
+	pci_read_config_byte(HWIF(drive)->pci_dev, regtime|0x01, &busclock);
+	switch(busclock) {
+		case 0xd9:	raw_reg = 0x0120d9d9;break;
+		case 0x85:	raw_reg = 0x01208585;break;
+		case 0xa7:
+		default:	raw_reg = 0x0120a7a7;break;
+	}
+	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, raw_reg);
+}
+
+static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	int			err;
+	byte			busclock;
+
+	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	byte regtime		= (drive->select.b.unit & 0x01) ? 0x43 : 0x40;
+	unsigned int reg1	= 0;
+	unsigned int reg2	= 0;
+
+	pci_read_config_byte(HWIF(drive)->pci_dev, regtime|0x01, &busclock);
+	pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);
+	
+	switch(busclock) {
+		case 0xd9:
+			reg2 = pci_bus_clock_list(speed, forty_base);
+			break;
+		case 0x85:
+			reg2 = pci_bus_clock_list(speed, twenty_five_base);
+			break;
+		case 0xa7:
+		default:
+			reg2 = pci_bus_clock_list(speed, thirty_three_base);
+			break;
+	}
+
+	if (drive->id->dword_io & 1)
+		reg2 |= 0x80000000;
+	else
+		reg2 &= ~0x80000000;
+
+	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
+	err = ide_config_drive_speed(drive, speed);
+#if HPT366_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d (0x%08x 0x%08x) 0x%04x\n",
+		drive->name, ide_xfer_verbose(speed),
+		drive_number, reg1, reg2, err);
+#endif /* HPT366_DEBUG_DRIVE_INFO */
+	return(err);
+}
+
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS.  Initally for designed for
+ * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	byte speed		= 0x00;
+
+#if 0
+	byte pio		= (id->eide_pio_modes & 2) ? 4 :
+				  (id->eide_pio_modes & 1) ? 3 :
+				  (id->tPIO & 2) ? 2 :
+				  (id->tPIO & 1) ? 1 : 0;
+#endif
+
+	if ((id->dma_ultra & 0x0010) && (HWIF(drive)->udma_four)) {
+		if (!((id->dma_ultra >> 8) & 16)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x1010;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (HWIF(drive)->udma_four)) {
+		if (!((id->dma_ultra >> 8) & 8)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0808;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_3;
+#if HPT366_ALLOW_MAXTOR_ATA33_2
+	} else if (id->dma_ultra & 0x0004) {
+#else
+	} else if ((id->dma_ultra & 0x0004) && (!check_maxtor_drive_lists(drive))) {
+#endif /* HPT366_ALLOW_MAXTOR_ATA33_2 */
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_2;
+#if HPT366_ALLOW_MAXTOR_ATA33_1
+	} else if (id->dma_ultra & 0x0002) {
+#else
+	} else if ((id->dma_ultra & 0x0002) && (!check_maxtor_drive_lists(drive))) {
+#endif /* HPT366_ALLOW_MAXTOR_ATA33_1 */
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_1;
+#if HPT366_ALLOW_MAXTOR_ATA33_0
+	} else if (id->dma_ultra & 0x0001) {
+#else
+	} else if ((id->dma_ultra & 0x0001) && (!check_maxtor_drive_lists(drive))) {
+#endif /* HPT366_ALLOW_MAXTOR_ATA33_0 */
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		drive->id->dma_ultra &= ~0xFF00;
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		drive->id->dma_ultra &= ~0xFF00;
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		drive->id->dma_ultra &= ~0xFF00;
+		if (!((id->dma_mword >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0101;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		drive->id->dma_ultra &= ~0xFF00;
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		drive->id->dma_ultra &= ~0xFF00;
+		if (!((id->dma_1word >> 8) & 2)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		drive->id->dma_ultra &= ~0xFF00;
+		if (!((id->dma_1word >> 8) & 1)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_0;
+        } else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) hpt366_tune_chipset(drive, speed);
+
+	return ((int)	((id->dma_ultra >> 11) & 3) ? 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 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) hpt366_tune_chipset(drive, speed);
+}
+
+static void hpt366_tune_drive (ide_drive_t *drive, byte pio)
+{
+	byte speed;
+
+	hpt366_clear_chipset(drive);
+	switch(pio) {
+		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 = XFER_PIO_0;break;
+	}
+	(void) hpt366_tune_chipset(drive, speed);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_dma_action_t dma_func = ide_dma_on;
+
+	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+
+		config_chipset_for_pio(drive);
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ *
+ * This is specific to the HPT343 UDMA bios-less chipset
+ * and HPT345 UDMA bios chipset (stamped HPT363)
+ * by HighPoint|Triones Technologies, Inc.
+ */
+
+int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+#if 0
+			hpt366_clear_chipset(drive);
+#endif
+			return config_drive_xfer_rate(drive);
+#if 0
+		case ide_dma_off:
+		case ide_dma_off_quietly:
+		case ide_dma_on:
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		case ide_dma_read:
+		case ide_dma_write:
+		case ide_dma_begin:
+		case ide_dma_end:
+		case ide_dma_test_irq:
+#endif
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+__initfunc(unsigned int pci_init_hpt366 (struct pci_dev *dev, const char *name))
+{
+	unsigned short pcicmd	= 0;
+	byte ata66		= 0;
+
+	pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+	pci_read_config_byte(dev, 0x5a, &ata66);
+	if (!(pcicmd & PCI_COMMAND_MEMORY))
+		pci_write_config_byte(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_MEMORY);
+	if (dev->rom_address)
+		pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+
+	printk("%s: reg5ah=0x%02x ATA-%s Cable Port%d\n", name, ata66, (ata66 & 0x02) ? "33" : "66", PCI_FUNC(dev->devfn));
+	return dev->irq;
+}
+
+__initfunc(void ide_init_hpt366 (ide_hwif_t *hwif))
+{
+	hwif->tuneproc = &hpt366_tune_drive;
+	if (hwif->dma_base) {
+		byte ata66		= 0;
+
+		hwif->dmaproc = &hpt366_dmaproc;
+		pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);
+		hwif->udma_four = (ata66 & 0x02) ? 0 : 1;
+	} else {
+		hwif->udma_four = 0;
+		hwif->autodma = 0;
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+}
diff -urN linux-2.2.10-pristine/drivers/block/ht6560b.c linux/drivers/block/ht6560b.c
--- linux-2.2.10-pristine/drivers/block/ht6560b.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ht6560b.c	Thu Jul 22 20:38:43 1999
@@ -57,8 +57,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -urN linux-2.2.10-pristine/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- linux-2.2.10-pristine/drivers/block/ide-cd.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-cd.c	Thu Jul 22 20:38:43 1999
@@ -258,13 +258,14 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
+#include <linux/ide.h>
+
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
-#include "ide.h"
 #include "ide-cd.h"
 
 /****************************************************************************
@@ -670,7 +671,8 @@
 
 	OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
 	OUT_BYTE (xferlen >> 8  , IDE_HCYL_REG);
-	OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
  
 	if (info->dma)
 		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
@@ -2940,7 +2942,19 @@
         else 	
         	printk (" drive");
 
-	printk (", %dkB Cache\n", ntohs(buf.cap.buffer_size));
+	printk (", %dkB Cache", ntohs(buf.cap.buffer_size));
+
+	if (drive->using_dma) {
+		if ((drive->id->field_valid & 4) &&
+		    (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) {
+			printk(", UDMA");	/* UDMA BIOS-enabled! */
+		} else if (drive->id->field_valid & 4) {
+			printk(", (U)DMA");	/* Can be BIOS-enabled! */
+		} else {
+			printk(", DMA");
+		}
+	}
+	printk("\n");
 
 	return nslots;
 }
@@ -2956,6 +2970,54 @@
 	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1,	1, &drive->dsc_overlap, NULL);
 }
 
+#ifdef CONFIG_IDECD_SLOTS
+static void ide_cdrom_slot_check (ide_drive_t *drive, int nslots)
+{
+	tracktype tracks;
+	struct cdrom_info *info = drive->driver_data;
+	struct cdrom_device_info *devinfo = &info->devinfo;
+	int slot_count = 0, drive_stat = 0, tmp;
+
+	for (slot_count=0;slot_count<nslots;slot_count++) {
+		(void) ide_cdrom_select_disc(devinfo, slot_count);
+		printk("     CD Slot %d ", slot_count+1);
+
+		drive_stat = ide_cdrom_drive_status(devinfo, slot_count);
+		if (drive_stat<0) {
+			continue;
+		} else switch(drive_stat) {
+			case CDS_DISC_OK:
+				/* use routine in Uniform CD-ROM driver */
+				cdrom_count_tracks(devinfo, &tracks);
+				tmp = tracks.audio + tracks.data +
+					tracks.cdi + tracks.xa;
+				printk(": Disc has %d track%s: ", tmp,
+					(tmp == 1)? "" : "s");
+				printk("%d=data %d=audio %d=Cd-I %d=XA\n",
+					tracks.data, tracks.audio,
+					tracks.cdi, tracks.xa);
+				break;
+			case CDS_NO_DISC:
+				printk("Empty slot.\n");
+				break;
+			case CDS_TRAY_OPEN:
+				printk("CD-ROM tray open.\n");
+				break;
+			case CDS_DRIVE_NOT_READY:
+				printk("CD-ROM drive not ready.\n");
+				break;
+			case CDS_NO_INFO:
+				printk("No Information available.\n");
+				break;
+			default:
+				printk("This Should not happen!\n");
+				break;
+		}
+	}
+	(void) ide_cdrom_select_disc(devinfo, 0);
+}
+#endif /* CONFIG_IDECD_SLOTS */
+
 static
 int ide_cdrom_setup (ide_drive_t *drive)
 {
@@ -3083,6 +3145,11 @@
 		return 1;
 	}
 	ide_cdrom_add_settings(drive);
+#ifdef CONFIG_IDECD_SLOTS
+	if (CDROM_CONFIG_FLAGS (drive)->is_changer) {
+		ide_cdrom_slot_check(drive, nslots);
+	}
+#endif /* CONFIG_IDECD_SLOTS */
 	return 0;
 }
 
diff -urN linux-2.2.10-pristine/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
--- linux-2.2.10-pristine/drivers/block/ide-disk.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-disk.c	Thu Jul 22 20:38:43 1999
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide-disk.c	Version 1.08  Dec   10, 1998
+ *  linux/drivers/block/ide-disk.c	Version 1.09  April 23, 1999
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -25,12 +25,16 @@
  *			process of adding new ATA4 compliance.
  *			fixed problems in allowing fdisk to see
  *			the entire disk.
+ * Version 1.09		added increment of rq->sector in ide_multwrite
+ *			added UDMA 3/4 reporting
  */
 
-#define IDEDISK_VERSION	"1.08"
+#define IDEDISK_VERSION	"1.09"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
+#define _IDE_DISK_C		/* Tell linux/hdsmart.h it's really us */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -44,13 +48,18 @@
 #include <linux/genhd.h>
 #include <linux/malloc.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "ide.h"
+#ifdef CONFIG_BLK_DEV_PDC4030
+#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
+#else
+#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
+#endif
 
 static void idedisk_bswap_data (void *buffer, int wcount)
 {
@@ -101,6 +110,15 @@
 		id->cyls = lba_sects / (16 * 63); /* correct cyls */
 		return 1;	/* lba_capacity is our only option */
 	}
+	/*
+	 * ... and at least one TLA VBC has POS instead of brain and can't
+	 * tell 16 from 15.
+	 */
+	if ((id->lba_capacity >= 15481935) && (id->cyls == 0x3fff) &&
+	    (id->heads == 15) && (id->sectors == 63)) {
+		id->cyls = lba_sects / (15 * 63); /* correct cyls */
+		return 1;	/* lba_capacity is our only option */
+	}
 	/* perform a rough sanity check on lba_sects:  within 10% is "okay" */
 	if ((lba_sects - chs_sects) < _10_percent) {
 		return 1;	/* lba_capacity is good */
@@ -221,6 +239,9 @@
 			drive->name, rq->sector, (unsigned long) rq->buffer,
 			nsect, rq->nr_sectors - nsect);
 #endif
+#ifdef CONFIG_BLK_DEV_PDC4030
+		rq->sector += nsect;
+#endif
 		if ((rq->nr_sectors -= nsect) <= 0)
 			break;
 		if ((rq->current_nr_sectors -= nsect) == 0) {
@@ -279,7 +300,11 @@
 {
 	byte stat = GET_STAT();
 
+#if 0
+	if (OK_STAT(stat,READY_STAT,BAD_STAT) || drive->mult_req == 0) {
+#else
 	if (OK_STAT(stat,READY_STAT,BAD_STAT)) {
+#endif
 		drive->mult_count = drive->mult_req;
 	} else {
 		drive->mult_req = drive->mult_count = 0;
@@ -317,20 +342,11 @@
  */
 static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
-#ifdef CONFIG_BLK_DEV_PDC4030
-	ide_hwif_t *hwif = HWIF(drive);
-	int use_pdc4030_io = 0;
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
-	OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (IS_PDC4030_DRIVE) {
-		if (hwif->channel != 0 || rq->cmd == READ) {
-			use_pdc4030_io = 1;
-		}
-	}
-	if (drive->select.b.lba || use_pdc4030_io) {
+	if (drive->select.b.lba || IS_PDC4030_DRIVE) {
 #else /* !CONFIG_BLK_DEV_PDC4030 */
 	if (drive->select.b.lba) {
 #endif /* CONFIG_BLK_DEV_PDC4030 */
@@ -360,7 +376,7 @@
 #endif
 	}
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (use_pdc4030_io) {
+	if (IS_PDC4030_DRIVE) {
 		extern void do_pdc4030_io(ide_drive_t *, struct request *);
 		do_pdc4030_io (drive, rq);
 		return;
@@ -760,9 +776,13 @@
 			drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
 	if (drive->using_dma) {
-		if ((id->field_valid & 4) &&
-		    (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
-			printk(", UDMA");	/* UDMA BIOS-enabled! */
+		if ((id->field_valid & 4) && (id->word93 & 0x2000) &&
+		    (HWIF(drive)->udma_four) &&
+		    (id->dma_ultra & (id->dma_ultra >> 11) & 3)) {
+			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */
+		} else if ((id->field_valid & 4) &&
+			   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+			printk(", UDMA(33)");	/* UDMA BIOS-enabled! */
 		} else if (id->field_valid & 4) {
 			printk(", (U)DMA");	/* Can be BIOS-enabled! */
 		} else {
@@ -786,17 +806,17 @@
 
 	drive->mult_count = 0;
 	if (id->max_multsect) {
-#if 1	/* original, pre IDE-NFG, per request of AC */
+#ifdef CONFIG_IDEDISK_MULTI_MODE
+		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
+		id->multsect_valid = id->multsect ? 1 : 0;
+		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
+#else	/* original, pre IDE-NFG, per request of AC */
 		drive->mult_req = INITIAL_MULT_COUNT;
 		if (drive->mult_req > id->max_multsect)
 			drive->mult_req = id->max_multsect;
 		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
 			drive->special.b.set_multmode = 1;
-#else
-		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
-		id->multsect_valid = id->multsect ? 1 : 0;
-		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
-		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
 #endif
 	}
 	drive->no_io_32bit = id->dword_io ? 1 : 0;
@@ -837,11 +857,16 @@
 	ide_drive_t *drive;
 	int failed = 0;
 
-	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL)
+	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {
 		if (idedisk_cleanup (drive)) {
 			printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
 			failed++;
 		}
+		/* We must remove proc entries defined in this module.
+		   Otherwise we oops while accessing these entries */
+		if (drive->proc)
+			ide_remove_proc_entries(drive->proc, idedisk_proc);
+	}
 	ide_unregister_module(&idedisk_module);
 }
 #endif /* MODULE */
diff -urN linux-2.2.10-pristine/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- linux-2.2.10-pristine/drivers/block/ide-dma.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-dma.c	Thu Jul 22 20:38:43 1999
@@ -1,5 +1,12 @@
 /*
- *  linux/drivers/block/ide-dma.c	Version 4.08  December 31, 1997
+ *  linux/drivers/block/ide-dma.c	Version 4.09  April 23, 1999
+ *
+ *  Copyright (c) 1999  Andre Hedrick
+ *  May be copied or modified under the terms of the GNU General Public License
+ */
+
+/*
+ *  Special Thanks to Mark for his Six years of work.
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -24,7 +31,7 @@
  *
  * Use "hdparm -i" to view modes supported by a given drive.
  *
- * The hdparm-2.4 (or later) utility can be used for manually enabling/disabling
+ * The hdparm-3.5 (or later) utility can be used for manually enabling/disabling
  * DMA support, but must be (re-)compiled against this kernel version or later.
  *
  * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
@@ -79,11 +86,51 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "ide.h"
+#ifdef IDEDMA_NEW_DRIVE_LISTINGS
+
+struct drive_list_entry {
+	char * id_model;
+	char * id_firmware;
+};
+
+struct drive_list_entry drive_whitelist [] = {
+
+	{ "Micropolis 2112A"	,       "ALL"		},
+	{ "CONNER CTMA 4000"	,       "ALL"		},
+	{ "CONNER CTT8000-A"	,       "ALL"		},
+	{ "ST34342A"		,	"ALL"		},
+	{ 0			,	0		}
+};
+
+struct drive_list_entry drive_blacklist [] = {
+
+	{ "WDC AC11000H"	,	"ALL"		},
+	{ "WDC AC22100H"	,	"ALL"		},
+	{ "WDC AC32500H"	,	"ALL"		},
+	{ "WDC AC33100H"	,	"ALL"		},
+	{ "WDC AC31600H"	,	"ALL"		},
+	{ "WDC AC32100H"	,	"24.09P07"	},
+	{ "WDC AC23200L"	,	"21.10N21"	},
+	{ 0			,	0		}
+
+};
+
+int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
+{
+	for ( ; drive_table->id_model ; drive_table++)
+		if ((!strcmp(drive_table->id_model, id->model)) &&
+		    ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
+		     (!strcmp(drive_table->id_firmware, "ALL"))))
+			return 1;
+	return 0;
+}
+
+#else /* !IDEDMA_NEW_DRIVE_LISTINGS */
 
 /*
  * good_dma_drives() lists the model names (from "hdparm -i")
@@ -109,11 +156,14 @@
  */
 const char *bad_dma_drives[] = {"WDC AC11000H",
 				"WDC AC22100H",
+				"WDC AC32100H",
 				"WDC AC32500H",
 				"WDC AC33100H",
 				"WDC AC31600H",
  				NULL};
 
+#endif /* IDEDMA_NEW_DRIVE_LISTINGS */
+
 /*
  * Our Physical Region Descriptor (PRD) table should be large enough
  * to handle the biggest I/O request we are likely to see.  Since requests
@@ -164,11 +214,12 @@
  * Returns 0 if all went okay, returns 1 otherwise.
  * May also be invoked from trm290.c
  */
-int ide_build_dmatable (ide_drive_t *drive)
+int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
 {
 	struct request *rq = HWGROUP(drive)->rq;
 	struct buffer_head *bh = rq->bh;
 	unsigned int size, addr, *table = (unsigned int *)HWIF(drive)->dmatable;
+	unsigned char *virt_addr;
 #ifdef CONFIG_BLK_DEV_TRM290
 	unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
 #else
@@ -185,11 +236,13 @@
 		 * than two possibly non-adjacent physical 4kB pages.
 		 */
 		if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
-			addr = virt_to_bus (rq->buffer);
+			virt_addr = rq->buffer;
+			addr = virt_to_bus (virt_addr);
 			size = rq->nr_sectors << 9;
 		} else {
 			/* group sequential buffers into one large buffer */
-			addr = virt_to_bus (bh->b_data);
+			virt_addr = bh->b_data;
+			addr = virt_to_bus (virt_addr);
 			size = bh->b_size;
 			while ((bh = bh->b_reqnext) != NULL) {
 				if ((addr + size) != virt_to_bus (bh->b_data))
@@ -206,6 +259,20 @@
 			printk("%s: misaligned DMA buffer\n", drive->name);
 			return 0;
 		}
+
+		/*
+		 * Some CPUs without cache snooping need to invalidate/write
+		 * back their caches before DMA transfers to guarantee correct
+		 * data.        -- rmk
+		 */
+		if (size) {
+			if (func == ide_dma_read) {
+				dma_cache_inv((unsigned int)virt_addr, size);
+			} else {
+				dma_cache_wback((unsigned int)virt_addr, size);
+			}
+		}
+
 		while (size) {
 			if (++count >= PRD_ENTRIES) {
 				printk("%s: DMA table too small\n", drive->name);
@@ -224,10 +291,17 @@
 			}
 		}
 	} while (bh != NULL);
-	if (!count)
+	if (!count) {
 		printk("%s: empty DMA table?\n", drive->name);
-	else if (!is_trm290_chipset)
-		*--table |= cpu_to_le32(0x80000000);	/* set End-Of-Table (EOT) bit */
+	} else {
+		if (!is_trm290_chipset)
+			*--table |= cpu_to_le32(0x80000000);	/* set End-Of-Table (EOT) bit */
+		/*
+		 * Some CPUs need to flush the DMA table to physical RAM
+		 * before DMA can start.        -- rmk
+		 */
+		dma_cache_wback((unsigned long)HWIF(drive)->dmatable, count * sizeof(unsigned int) * 2);
+	}
 	return count;
 }
 
@@ -238,9 +312,20 @@
  */
 int check_drive_lists (ide_drive_t *drive, int good_bad)
 {
-	const char **list;
 	struct hd_driveid *id = drive->id;
 
+#ifdef IDEDMA_NEW_DRIVE_LISTINGS
+	if (good_bad) {
+		return in_drive_list(id, drive_whitelist);
+	} else {
+		int blacklist = in_drive_list(id, drive_blacklist);
+		if (blacklist)
+			printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);
+		return(blacklist);
+	}
+#else /* !IDEDMA_NEW_DRIVE_LISTINGS */
+	const char **list;
+
 	if (good_bad) {
 		/* Consult the list of known "good" drives */
 		list = good_dma_drives;
@@ -259,6 +344,7 @@
 			}
 		}
 	}
+#endif /* IDEDMA_NEW_DRIVE_LISTINGS */
 	return 0;
 }
 
@@ -269,18 +355,23 @@
 
 	if (id && (id->capability & 1) && hwif->autodma) {
 		/* Consult the list of known "bad" drives */
-		if (check_drive_lists(drive, BAD_DMA_DRIVE))
+		if (ide_dmaproc(ide_dma_bad_drive, drive))
 			return hwif->dmaproc(ide_dma_off, drive);
+
+		/* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */
+		if ((id->field_valid & 4) && (hwif->udma_four) && (id->word93 & 0x2000))
+			if ((id->dma_ultra & (id->dma_ultra >> 11) & 3))
+				return hwif->dmaproc(ide_dma_on, drive);
 		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
 		if (id->field_valid & 4)	/* UltraDMA */
-			if  ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
+			if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
 				return hwif->dmaproc(ide_dma_on, drive);
 		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
 		if (id->field_valid & 2)	/* regular DMA */
 			if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
 				return hwif->dmaproc(ide_dma_on, drive);
 		/* Consult the list of known "good" drives */
-		if (check_drive_lists(drive, GOOD_DMA_DRIVE))
+		if (ide_dmaproc(ide_dma_good_drive, drive))
 			return hwif->dmaproc(ide_dma_on, drive);
 	}
 	return hwif->dmaproc(ide_dma_off_quietly, drive);
@@ -321,7 +412,7 @@
 		case ide_dma_read:
 			reading = 1 << 3;
 		case ide_dma_write:
-			if (!(count = ide_build_dmatable(drive)))
+			if (!(count = ide_build_dmatable(drive, func)))
 				return 1;	/* try PIO instead of DMA */
 			outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */
 			outb(reading, dma_base);			/* specify r/w */
@@ -348,6 +439,9 @@
 		case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
 			dma_stat = inb(dma_base+2);
 			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
+		case ide_dma_bad_drive:
+		case ide_dma_good_drive:
+			return check_drive_lists(drive, (func == ide_dma_good_drive));
 		default:
 			printk("ide_dmaproc: unsupported func: %d\n", func);
 			return 1;
@@ -430,13 +524,35 @@
 		}
 	}
 	if (dma_base) {
-		if (extra) /* PDC20246 & HPT343 */
+		if (extra) /* PDC20246, PDC20262, & HPT343 */
 			request_region(dma_base+16, extra, name);
 		dma_base += hwif->channel ? 8 : 0;
 		hwif->dma_extra = extra;
-		if (inb(dma_base+2) & 0x80) {
-			printk("%s: simplex device:  DMA disabled\n", name);
-			dma_base = 0;
+
+		switch(dev->device) {
+			case PCI_DEVICE_ID_CMD_643:
+				/*
+				 * Lets attempt to use the same Ali tricks
+				 * to fix CMD643.....
+				 */
+#ifdef CONFIG_BLK_DEV_ALI15X3
+			case PCI_DEVICE_ID_AL_M5219:
+			case PCI_DEVICE_ID_AL_M5229:
+				/*
+				 * Ali 15x3 chipsets know as ALI IV and V report
+				 * this as simplex, skip this test for them.
+				 */
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
+				outb(inb(dma_base+2) & 0x60, dma_base+2);
+				if (inb(dma_base+2) & 0x80) {
+					printk("%s: simplex device: DMA forced\n", name);
+				}
+				break;
+			default:
+				if (inb(dma_base+2) & 0x80) {
+					printk("%s: simplex device:  DMA disabled\n", name);
+					dma_base = 0;
+				}
 		}
 	}
 	return dma_base;
diff -urN linux-2.2.10-pristine/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c
--- linux-2.2.10-pristine/drivers/block/ide-floppy.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-floppy.c	Thu Jul 22 20:38:43 1999
@@ -44,6 +44,7 @@
 #include <linux/genhd.h>
 #include <linux/malloc.h>
 #include <linux/cdrom.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -53,11 +54,6 @@
 #include <asm/bitops.h>
 
 /*
- *	Main Linux ide driver include file
- */
-#include "ide.h"
-
-/*
  *	The following are used to debug the driver.
  */
 #define IDEFLOPPY_DEBUG_LOG		0
@@ -1011,7 +1007,8 @@
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
@@ -1633,11 +1630,16 @@
 	ide_drive_t *drive;
 	int failed = 0;
 
-	while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL)
+	while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) {
 		if (idefloppy_cleanup (drive)) {
 			printk ("%s: cleanup_module() called while still busy\n", drive->name);
 			failed++;
 		}
+		/* We must remove proc entries defined in this module.
+		   Otherwise we oops while accessing these entries */
+		if (drive->proc)
+			ide_remove_proc_entries(drive->proc, idefloppy_proc);
+	}
 	ide_unregister_module(&idefloppy_module);
 }
 #endif /* MODULE */
diff -urN linux-2.2.10-pristine/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- linux-2.2.10-pristine/drivers/block/ide-pci.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-pci.c	Thu Jul 22 20:38:43 1999
@@ -1,5 +1,7 @@
 /*
- *  linux/drivers/block/ide-pci.c	Version 1.02  December 29, 1997
+ *  linux/drivers/block/ide-pci.c	Version 1.03  May 1, 1999
+ *
+ *  Copyright (c) 1998-1999  Andre Hedrick
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -18,26 +20,29 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "ide.h"
-
 #define DEVID_PIIXa	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_0})
 #define DEVID_PIIXb	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_1})
 #define DEVID_PIIX3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371SB_1})
 #define DEVID_PIIX4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371AB})
+#define DEVID_VIA_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C561})
 #define DEVID_VP_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_1})
 #define DEVID_PDC20246	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246})
+#define DEVID_PDC20262	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262})
 #define DEVID_RZ1000	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1000})
 #define DEVID_RZ1001	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1001})
+#define DEVID_SAMURAI	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_SAMURAI_IDE})
 #define DEVID_CMD640	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_640})
+#define DEVID_CMD643	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_643})
 #define DEVID_CMD646	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_646})
 #define DEVID_SIS5513	((ide_pci_devid_t){PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5513})
 #define DEVID_OPTI621	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C621})
 #define DEVID_OPTI621V	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C558})
-#define DEVID_OPTI621X	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    0xd568})  /* from datasheets */
+#define DEVID_OPTI621X	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C825})
 #define DEVID_TRM290	((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM,  PCI_DEVICE_ID_TEKRAM_DC290})
 #define DEVID_NS87410	((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87410})
 #define DEVID_NS87415	((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87415})
@@ -46,7 +51,12 @@
 #define DEVID_W82C105	((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
 #define DEVID_UM8886A	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886A})
 #define DEVID_UM8886BF	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886BF})
-#define DEVID_HPT343	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT343})
+#define DEVID_HPT34X	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT343})
+#define	DEVID_HPT366	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT366})
+#define DEVID_ALI15X3	((ide_pci_devid_t){PCI_VENDOR_ID_AL,      PCI_DEVICE_ID_AL_M5229})
+#define DEVID_CY82C693	((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ,  PCI_DEVICE_ID_CONTAQ_82C693})
+#define DEVID_HINT	((ide_pci_devid_t){0x3388,                0x8013})
+#define DEVID_CX5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
 
 #define IDE_IGNORE	((void *)-1)
 
@@ -97,12 +107,92 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_VIA82C586
+extern unsigned int pci_init_via82c568(struct pci_dev *, const char *);
 extern void ide_init_via82c586(ide_hwif_t *);
+extern void ide_dmacapable_via82c586(ide_hwif_t *, unsigned long dmabase);
+#define PCI_VIA82C586	&pci_init_via82c568
 #define	INIT_VIA82C586	&ide_init_via82c586
+#define	DMA_VIA82C586	&ide_dmacapable_via82c586
 #else
+#define PCI_VIA82C586	NULL
 #define	INIT_VIA82C586	NULL
+#define	DMA_VIA82C586	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_ALI15X3
+extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *);
+extern void ide_init_ali15x3(ide_hwif_t *);
+#define PCI_ALI15X3	&pci_init_ali15x3
+#define	INIT_ALI15X3	&ide_init_ali15x3
+#else
+#define PCI_ALI15X3	NULL
+#define	INIT_ALI15X3	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_CY82C693
+extern void ide_init_cy82c693(ide_hwif_t *);
+#define	INIT_CY82C693	&ide_init_cy82c693
+#else
+#define	INIT_CY82C693	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PDC202XX
+extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *);
+extern void ide_init_pdc202xx(ide_hwif_t *);
+#define PCI_PDC202XX	&pci_init_pdc202xx
+#define	INIT_PDC202XX	&ide_init_pdc202xx
+#else
+#define PCI_PDC202XX	NULL
+#define	INIT_PDC202XX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PIIX
+extern void ide_init_piix(ide_hwif_t *);
+#define	INIT_PIIX	&ide_init_piix
+#else
+#define	INIT_PIIX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_AEC6210
+extern unsigned int pci_init_aec6210(struct pci_dev *, const char *);
+#define PCI_AEC6210	&pci_init_aec6210
+#else
+#define PCI_AEC6210	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_HPT34X
+extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *);
+extern void ide_init_hpt34x(ide_hwif_t *);
+#define PCI_HPT34X	&pci_init_hpt34x
+#define	INIT_HPT34X	&ide_init_hpt34x
+#else
+#define PCI_HPT34X	NULL
+#define	INIT_HPT34X	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_HPT366
+extern unsigned int pci_init_hpt366(struct pci_dev *, const char *);
+extern void ide_init_hpt366(ide_hwif_t *);
+#define PCI_HPT366	&pci_init_hpt366
+#define INIT_HPT366	&ide_init_hpt366
+#else
+#define PCI_HPT366	NULL
+#define INIT_HPT366	IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_SIS5513
+extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
+extern void ide_init_sis5513(ide_hwif_t *);
+#define PCI_SIS5513	&pci_init_sis5513
+#define INIT_SIS5513	&ide_init_sis5513
+#else
+#define PCI_SIS5513	NULL
+#define INIT_SIS5513	NULL
 #endif
 
+#define INIT_SAMURAI	NULL
+#define INIT_CX5530	NULL
+
 typedef struct ide_pci_enablebit_s {
 	byte	reg;	/* byte pci reg holding the enable-bit */
 	byte	mask;	/* mask to isolate the enable-bit */
@@ -112,36 +202,47 @@
 typedef struct ide_pci_device_s {
 	ide_pci_devid_t		devid;
 	const char		*name;
+	unsigned int		(*init_chipset)(struct pci_dev *dev, const char *name);
 	void 			(*init_hwif)(ide_hwif_t *hwif);
+	void			(*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
 	ide_pci_enablebit_t	enablebits[2];
 	byte			bootable;
 	unsigned int		extra;
 } ide_pci_device_t;
 
 static ide_pci_device_t ide_pci_chipsets[] __initdata = {
-	{DEVID_PIIXa,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIXb,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIX3,	"PIIX3",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIX4,	"PIIX4",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_VP_IDE,	"VP_IDE",	INIT_VIA82C586,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
-	{DEVID_PDC20246,"PDC20246",	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
-	{DEVID_RZ1000,	"RZ1000",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_RZ1001,	"RZ1001",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_CMD640,	"CMD640",	IDE_IGNORE,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_NS87410,	"NS87410",	NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
-	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
-	{DEVID_CMD646,	"CMD646",	INIT_CMD646,	{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_HT6565,	"HT6565",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_OPTI621,	"OPTI621",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_OPTI621X,"OPTI621X",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_TRM290,	"TRM290",	INIT_TRM290,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_NS87415,	"NS87415",	INIT_NS87415,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_AEC6210,	"AEC6210",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	OFF_BOARD,	0 },
-	{DEVID_W82C105,	"W82C105",	INIT_W82C105,	{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	ON_BOARD,	0 },
-	{DEVID_UM8886A,	"UM8886A",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_UM8886BF,"UM8886BF",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_HPT343,	"HPT343",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
-	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
+	{DEVID_PIIXa,	"PIIX",		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIXb,	"PIIX",		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX3,	"PIIX3",	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX4,	"PIIX4",	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_VIA_IDE,	"VIA_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_VP_IDE,	"VP_IDE",	PCI_VIA82C586,	INIT_VIA82C586,	DMA_VIA82C586,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
+	{DEVID_PDC20246,"PDC20246",	PCI_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
+	{DEVID_PDC20262,"PDC20262",	PCI_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
+	{DEVID_RZ1000,	"RZ1000",	NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_RZ1001,	"RZ1001",	NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_SAMURAI,	"SAMURAI",	NULL,		INIT_SAMURAI,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD640,	"CMD640",	NULL,		IDE_IGNORE,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87410,	"NS87410",	NULL,		NULL,		NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
+	{DEVID_SIS5513,	"SIS5513",	PCI_SIS5513,	INIT_SIS5513,	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
+	{DEVID_CMD643,	"CMD643",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD646,	"CMD646",	NULL,		INIT_CMD646,	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_HT6565,	"HT6565",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621,	"OPTI621",	NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621X,"OPTI621X",	NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_TRM290,	"TRM290",	NULL,		INIT_TRM290,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87415,	"NS87415",	NULL,		INIT_NS87415,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_AEC6210,	"AEC6210",	PCI_AEC6210,	NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	OFF_BOARD,	0 },
+	{DEVID_W82C105,	"W82C105",	NULL,		INIT_W82C105,	NULL,		{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	ON_BOARD,	0 },
+	{DEVID_UM8886A,	"UM8886A",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_UM8886BF,"UM8886BF",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_HPT34X,	"HPT34X",	PCI_HPT34X,	INIT_HPT34X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
+	{DEVID_HPT366,	"HPT366",	PCI_HPT366,	INIT_HPT366,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	16 },
+	{DEVID_ALI15X3,	"ALI15X3",	PCI_ALI15X3,	INIT_ALI15X3,	NULL,		{{0x09,0x20,0x20}, {0x09,0x10,0x10}},	ON_BOARD,	0 },
+	{DEVID_CY82C693,"CY82C693",	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CX5530,	"CX5530",	NULL,		INIT_CX5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
 /*
  * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
@@ -151,27 +252,31 @@
 __initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
 {
 	switch(dev->device) {
-		case PCI_DEVICE_ID_ARTOP_ATP850UF:
-		case PCI_DEVICE_ID_PROMISE_20246:
-			if (dev->rom_address) {
-				pci_write_config_byte(dev, PCI_ROM_ADDRESS,
-					dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
-				printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
-			}
-			
-			if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) {
-				unsigned char irq1 = 0, irq2 = 0;
-
-				pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq1);
-				pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);	/* 0xbc */
-				if (irq1 != irq2) {
-					printk("%s: IRQ1 %d IRQ2 %d\n",
-						name, irq1, irq2);
-					pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq1);	/* 0xbc */
+		case PCI_DEVICE_ID_TTI_HPT343:
+			{
+				int i;
+				unsigned short pcicmd = 0;
+				unsigned long hpt34xIoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+
+				pci_write_config_byte(dev, 0x80, 0x00);
+				dev->base_address[0] = (hpt34xIoBase + 0x20);
+				dev->base_address[1] = (hpt34xIoBase + 0x34);
+				dev->base_address[2] = (hpt34xIoBase + 0x28);
+				dev->base_address[3] = (hpt34xIoBase + 0x3c);
+				for(i=0; i<4; i++)
+					dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+
+				pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+				if (!(pcicmd & PCI_COMMAND_MEMORY)) {
+					pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+				} else {
+					pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
 				}
 			}
-			return dev->irq;
-		case PCI_DEVICE_ID_TTI_HPT343:
+		case PCI_DEVICE_ID_TTI_HPT366:
+		case PCI_DEVICE_ID_PROMISE_20246:
+		case PCI_DEVICE_ID_PROMISE_20262:
+		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 			return dev->irq;
 		default:
 			break;
@@ -269,7 +374,7 @@
 	 */
 	for (reg = 0; reg < 4; reg++)
 		if (!dev->base_address[reg]) {
-			printk("%s: Missing I/O address #%d, please report to <mj@ucw.cz>\n", name, reg);
+			printk("%s: Missing I/O address #%d\n", name, reg);
 			return 1;
 		}
 	return 0;
@@ -325,7 +430,13 @@
 	pciirq = dev->irq;
 	if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
 		printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
-		pciirq = ide_special_settings(dev, d->name);
+		/*
+		 * This allows offboard ide-pci cards the enable a BIOS,
+		 * verify interrupt settings of split-mirror pci-config
+		 * space, place chipset into init-mode, and/or preserve
+		 * an interrupt if the card is not native ide support.
+		 */
+		pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name);
 	} else if (tried_config) {
 		printk("%s: will probe irqs later\n", d->name);
 		pciirq = 0;
@@ -340,14 +451,33 @@
 		printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
 #endif
 	}
+	if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) {
+		/*
+		 * Since there are two cards that report almost identically,
+		 * the only discernable difference is the values
+		 * reported in pcicmd.
+		 * Booting-BIOS card or HPT363 :: pcicmd == 0x07
+		 * Non-bootable card or HPT343 :: pcicmd == 0x05
+		 */
+		if (pcicmd & PCI_COMMAND_MEMORY) {
+			printk("%s: is IDE Express HPT363.\n", d->name);
+			d->bootable = OFF_BOARD;
+		}
+	}
 	/*
 	 * Set up the IDE ports
 	 */
 	for (port = 0; port <= 1; ++port) {
 		unsigned long base = 0, ctl = 0;
+#if 1
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
+#else
+		ide_pci_enablebit_t *e = (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) ? &(d->enablebits[port+PCI_FUNC(dev->devfn)]) : &(d->enablebits[port]);
+#endif
 		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
 			continue;	/* port not enabled */
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port))
+			return;
 		if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
 			ctl  = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
 			base = dev->base_address[2*port] & ~7;
@@ -363,8 +493,8 @@
 		if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
 			continue;	/* no room in ide_hwifs[] */
 		if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
-			ide_init_hwif_ports(hwif->io_ports, base, NULL);
-			hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2;
+			ide_init_hwif_ports(&hwif->hw, base, (ctl + 2), NULL);
+			memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 			hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
 		}
 		hwif->chipset = ide_pci;
@@ -382,17 +512,28 @@
 			}
 		}
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
-		    IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF))
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF)) {
 			hwif->irq = hwif->channel ? 15 : 14;
+			goto bypass_umc_dma;
+		}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513))
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X))
 			autodma = 0;
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262))
+			hwif->udma_four = 1;
+
 		if (autodma)
 			hwif->autodma = 1;
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
-		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343) ||
+#ifdef CONFIG_BLK_DEV_HPT34X
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
+#endif /* CONFIG_BLK_DEV_HPT34X */
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) ||
 		    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
 			unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
 			if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
@@ -406,12 +547,18 @@
 					dma_base = 0;
 				}
 			}
-			if (dma_base)
-				ide_setup_dma(hwif, dma_base, 8);
-			else
+			if (dma_base) {
+				if (d->dma_init) {
+					d->dma_init(hwif, dma_base);
+				} else {
+					ide_setup_dma(hwif, dma_base, 8);
+				}
+			} else {
 				printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name);
+			}
 		}
 #endif	/* CONFIG_BLK_DEV_IDEDMA */
+bypass_umc_dma:
 		if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
 			d->init_hwif(hwif);
 		mate = hwif;
@@ -441,6 +588,10 @@
 			printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
 		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
 			continue;	/* OPTI Viper-M uses same devid for functions 0 and 1 */
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
+			continue;	/* CY82C693 is more than only a IDE controller */
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
+			continue;	/* UM8886A/BF pair */
 		else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
 			if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
 				printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
diff -urN linux-2.2.10-pristine/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- linux-2.2.10-pristine/drivers/block/ide-pmac.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-pmac.c	Thu Jul 22 20:38:43 1999
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
+
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
@@ -31,9 +33,9 @@
 #include <asm/adb.h>
 #include <asm/pmu.h>
 #endif
-#include "ide.h"
 #include "ide_modes.h"
 
+int pmac_ide_ports_known;
 ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
 int pmac_ide_irq[MAX_HWIFS];
 int pmac_ide_count;
@@ -58,28 +60,36 @@
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
-void
-pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void pmac_ide_init_hwif_ports (	hw_regs_t *hw,
+				ide_ioreg_t data_port,
+				ide_ioreg_t ctrl_port,
+				int *irq)
 {
+	ide_ioreg_t reg = data_port;
 	int i, r;
 
-	*p = 0;
-	if (base == 0)
+	if (data_port == 0)
 		return;
 	/* we check only for -EINVAL meaning that we have found a matching
 	   bay but with the wrong device type */ 
 
-	r = check_media_bay_by_base(base, MB_CD);
+	r = check_media_bay_by_base(data_port, MB_CD);
 	if (r == -EINVAL)
 		return;
 		
-	for (i = 0; i < 8; ++i)
-		*p++ = base + i * 0x10;
-	*p = base + 0x160;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg * 0x10;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x160;
+	}
 	if (irq != NULL) {
 		*irq = 0;
 		for (i = 0; i < MAX_HWIFS; ++i) {
-			if (base == pmac_ide_regbase[i]) {
+			if (data_port == pmac_ide_regbase[i]) {
 				*irq = pmac_ide_irq[i];
 				break;
 			}
@@ -104,8 +114,7 @@
 	}
 }
 
-__initfunc(void
-pmac_ide_probe(void))
+__initfunc(void pmac_ide_probe(void))
 {
 	struct device_node *np;
 	int i;
@@ -172,7 +181,8 @@
 			feature_set(np, FEATURE_IDE_enable);
 
 		hwif = &ide_hwifs[i];
-		pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq);
+		pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);
+		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->chipset = ide_generic;
 		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
 		hwif->tuneproc = pmac_ide_tuneproc;
diff -urN linux-2.2.10-pristine/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- linux-2.2.10-pristine/drivers/block/ide-probe.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-probe.c	Fri Jul 23 01:08:48 1999
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide-probe.c	Version 1.04  March 10, 1999
+ *  linux/drivers/block/ide-probe.c	Version 1.05  July 3, 1999
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -18,6 +18,11 @@
  *			 by Andrea Arcangeli
  * Version 1.03		fix for (hwif->chipset == ide_4drives)
  * Version 1.04		fixed buggy treatments of known flash memory cards
+ *
+ * Version 1.05		fix for (hwif->chipset == ide_pdc4030)
+ *			added ide6/7
+ *			allowed for secondary flash card to be detectable
+ *			 with new flag : drive->ata_flash : 1;
  */
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
@@ -35,14 +40,14 @@
 #include <linux/genhd.h>
 #include <linux/malloc.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
+
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "ide.h"
-
 static inline void do_identify (ide_drive_t *drive, byte cmd)
 {
 	int bswap = 1;
@@ -139,8 +144,10 @@
 	 */
 	if (drive_is_flashcard(drive)) {
 		ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
-		mate->present = 0;
-		mate->noprobe = 1;
+		if (!mate->ata_flash) {
+			mate->present = 0;
+			mate->noprobe = 1;
+		}
 	}
 	drive->media = ide_disk;
 	printk("ATA DISK drive\n");
@@ -148,17 +155,6 @@
 }
 
 /*
- * Delay for *at least* 50ms.  As we don't know how much time is left
- * until the next tick occurs, we wait an extra tick to be safe.
- * This is used only during the probing/polling for drives at boot time.
- */
-static void delay_50ms (void)
-{
-	unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
-	while (0 < (signed long)(timeout - jiffies));
-}
-
-/*
  * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
  * and waits for a response.  It also monitors irqs while this is
  * happening, in hope of automatically determining which one is
@@ -176,25 +172,32 @@
 	unsigned long irqs = 0;
 	byte s, a;
 
-	if (!HWIF(drive)->irq) {		/* already got an IRQ? */
-		probe_irq_off(probe_irq_on());	/* clear dangling irqs */
-		irqs = probe_irq_on();		/* start monitoring irqs */
-		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
-	}
+	if (IDE_CONTROL_REG) {
+		if (!HWIF(drive)->irq) {		/* already got an IRQ? */
+			probe_irq_off(probe_irq_on());	/* clear dangling irqs */
+			irqs = probe_irq_on();		/* start monitoring irqs */
+			OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
+		}
 
-	delay_50ms();				/* take a deep breath */
-	a = IN_BYTE(IDE_ALTSTATUS_REG);
-	s = IN_BYTE(IDE_STATUS_REG);
-	if ((a ^ s) & ~INDEX_STAT) {
-		printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);
-		hd_status = IDE_STATUS_REG;	/* ancient Seagate drives, broken interfaces */
-	} else
-		hd_status = IDE_ALTSTATUS_REG;	/* use non-intrusive polling */
+		ide_delay_50ms();				/* take a deep breath */
+		a = IN_BYTE(IDE_ALTSTATUS_REG);
+		s = IN_BYTE(IDE_STATUS_REG);
+		if ((a ^ s) & ~INDEX_STAT) {
+			printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);
+			hd_status = IDE_STATUS_REG;	/* ancient Seagate drives, broken interfaces */
+		} else {
+			hd_status = IDE_ALTSTATUS_REG;	/* use non-intrusive polling */
+		}
+	} else {
+		ide_delay_50ms();
+		hd_status = IDE_STATUS_REG;
+	}
 
 #if CONFIG_BLK_DEV_PDC4030
-	if (IS_PDC4030_DRIVE) {
-		extern int pdc4030_cmd(ide_drive_t *, byte);
-		if (pdc4030_cmd(drive,PROMISE_IDENTIFY)) {
+	if (HWIF(drive)->chipset == ide_pdc4030) {
+		/* DC4030 hosted drives need their own identify... */
+		extern int pdc4030_identify(ide_drive_t *);
+		if (pdc4030_identify(drive)) {
 			if (irqs)
 				(void) probe_irq_off(irqs);
 			return 1;
@@ -210,10 +213,10 @@
 				(void) probe_irq_off(irqs);
 			return 1;	/* drive timed-out */
 		}
-		delay_50ms();		/* give drive a breather */
+		ide_delay_50ms();		/* give drive a breather */
 	} while (IN_BYTE(hd_status) & BUSY_STAT);
 
-	delay_50ms();		/* wait for IRQ and DRQ_STAT */
+	ide_delay_50ms();		/* wait for IRQ and DRQ_STAT */
 	if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
 		unsigned long flags;
 		__save_flags(flags);	/* local CPU only */
@@ -224,7 +227,7 @@
 		__restore_flags(flags);	/* local CPU only */
 	} else
 		rc = 2;			/* drive refused ID */
-	if (!HWIF(drive)->irq) {
+	if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
 		irqs = probe_irq_off(irqs);	/* get our irq number */
 		if (irqs > 0) {
 			HWIF(drive)->irq = irqs; /* save it for later */
@@ -280,11 +283,11 @@
 		(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
 #endif
 	SELECT_DRIVE(hwif,drive);
-	delay_50ms();
+	ide_delay_50ms();
 	if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
 		if (drive->select.b.unit != 0) {
 			SELECT_DRIVE(hwif,&hwif->drives[0]);	/* exit with drive0 selected */
-			delay_50ms();		/* allow BUSY_STAT to assert & clear */
+			ide_delay_50ms();		/* allow BUSY_STAT to assert & clear */
 		}
 		return 3;    /* no i/f present: mmm.. this should be a 4 -ml */
 	}
@@ -297,13 +300,13 @@
 		if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {
 			unsigned long timeout;
 			printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT());
-			delay_50ms();
+			ide_delay_50ms();
 			OUT_BYTE (drive->select.all, IDE_SELECT_REG);
-			delay_50ms();
+			ide_delay_50ms();
 			OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
 			timeout = jiffies;
 			while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))
-				delay_50ms();
+				ide_delay_50ms();
 			rc = try_to_identify(drive, cmd);
 		}
 		if (rc == 1)
@@ -314,7 +317,7 @@
 	}
 	if (drive->select.b.unit != 0) {
 		SELECT_DRIVE(hwif,&hwif->drives[0]);	/* exit with drive0 selected */
-		delay_50ms();
+		ide_delay_50ms();
 		(void) GET_STAT();		/* ensure drive irq is clear */
 	}
 	return rc;
@@ -407,15 +410,40 @@
 	unsigned int unit;
 	unsigned long flags;
 
+	ide_ioreg_t ide_control_reg 	= hwif->io_ports[IDE_CONTROL_OFFSET];
+	ide_ioreg_t region_low 		= hwif->io_ports[IDE_DATA_OFFSET];
+	ide_ioreg_t region_high 	= region_low;
+	ide_ioreg_t region_request	= 8;
+	int i;
+
 	if (hwif->noprobe)
 		return;
 	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
 		probe_cmos_for_drives (hwif);
-	if ((hwif->chipset != ide_4drives || !hwif->mate->present)
+
+	/*
+	 * Calculate the region that this interface occupies,
+	 * handling interfaces where the registers may not be
+	 * ordered sanely.  We deal with the CONTROL register
+	 * separately.
+	 */
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		if (hwif->io_ports[i]) {
+			if (hwif->io_ports[i] < region_low)
+				region_low = hwif->io_ports[i];
+			if (hwif->io_ports[i] > region_high)
+				region_high = hwif->io_ports[i];
+		}
+	}
+	region_request = (region_high - region_low);
+	if (region_request == 0x0007)
+		region_request++;
+	if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&
 #if CONFIG_BLK_DEV_PDC4030
-	 && (hwif->chipset != ide_pdc4030 || hwif->channel == 0)
+	    (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
 #endif /* CONFIG_BLK_DEV_PDC4030 */
-	 && (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET],1)))
+	    (ide_check_region(region_low, region_request) ||
+	    (ide_control_reg && ide_check_region(ide_control_reg,1))))
 	{
 		int msgout = 0;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
@@ -443,21 +471,22 @@
 		if (drive->present && !hwif->present) {
 			hwif->present = 1;
 			if (hwif->chipset != ide_4drives || !hwif->mate->present) {
-				ide_request_region(hwif->io_ports[IDE_DATA_OFFSET],  8, hwif->name);
-				ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
+				ide_request_region(region_low, region_request, hwif->name);
+				if (ide_control_reg)
+					ide_request_region(ide_control_reg, 1, hwif->name);
 			}
 		}
 	}
-	if (hwif->reset) {
+	if (ide_control_reg && hwif->reset) {
 		unsigned long timeout = jiffies + WAIT_WORSTCASE;
 		byte stat;
 
 		printk("%s: reset\n", hwif->name);
-		OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(12, ide_control_reg);
 		udelay(10);
-		OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(8, ide_control_reg);
 		do {
-			delay_50ms();
+			ide_delay_50ms();
 			stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
 		} while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));
 
@@ -660,7 +689,11 @@
 	max_readahead[hwif->major] = max_ra;
 	for (unit = 0; unit < minors; ++unit) {
 		*bs++ = BLOCK_SIZE;
+#ifdef CONFIG_BLK_DEV_PDC4030
+		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : MAX_SECTORS);
+#else
 		*max_sect++ = MAX_SECTORS;
+#endif
 		*max_ra++ = MAX_READAHEAD;
 	}
 
@@ -693,7 +726,8 @@
 	if (!hwif->present)
 		return 0;
 	if (!hwif->irq) {
-		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
+		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
+		{
 			printk("%s: DISABLED, NO IRQ\n", hwif->name);
 			return (hwif->present = 0);
 		}
@@ -723,6 +757,12 @@
 #if MAX_HWIFS > 5
 	case IDE5_MAJOR: rfn = &do_ide5_request; break;
 #endif
+#if MAX_HWIFS > 6
+	case IDE6_MAJOR: rfn = &do_ide6_request; break;
+#endif
+#if MAX_HWIFS > 7
+	case IDE7_MAJOR: rfn = &do_ide7_request; break;
+#endif
 	default:
 		printk("%s: request_fn NOT DEFINED\n", hwif->name);
 		return (hwif->present = 0);
@@ -810,7 +850,9 @@
 	
 	for (index = 0; index < MAX_HWIFS; ++index)
 		ide_unregister(index);
-	return ideprobe_init();
+	ideprobe_init();
+	create_proc_ide_interfaces();
+	return 0;
 }
 
 void cleanup_module (void)
diff -urN linux-2.2.10-pristine/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- linux-2.2.10-pristine/drivers/block/ide-proc.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-proc.c	Thu Jul 22 20:38:43 1999
@@ -65,13 +65,22 @@
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/ctype.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
 
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
 
+#ifdef CONFIG_BLK_DEV_VIA82C586
+int (*via_display_info)(char *, char **, off_t, int, int) = NULL;
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+
+#ifdef CONFIG_BLK_DEV_ALI15X3
+int (*ali_display_info)(char *, char **, off_t, int, int) = NULL;
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
+
 static int ide_getxdigit(char c)
 {
 	int digit;
@@ -103,6 +112,8 @@
 	return -EINVAL;
 }
 
+static struct proc_dir_entry * proc_ide_root = NULL;
+
 static int proc_ide_write_config
 	(struct file *file, const char *buffer, unsigned long count, void *data)
 {
@@ -375,7 +386,7 @@
 	ide_drive_t	*drive = (ide_drive_t *)data;
 	int		len = 0, i = 0;
 
-	if (!proc_ide_get_identify(drive, page)) {
+	if (drive && !proc_ide_get_identify(drive, page)) {
 		unsigned short *val = ((unsigned short *)page) + 2;
 		char *out = ((char *)val) + (SECTOR_WORDS * 4);
 		page = out;
@@ -385,6 +396,8 @@
 		} while (i < (SECTOR_WORDS * 2));
 		len = out - page;
 	}
+	else
+		len = sprintf(page, "\n");
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
@@ -516,8 +529,8 @@
 	char		*out = page;
 	int		len;
 
-	out += sprintf(out,"physical     %hi/%hi/%hi\n", drive->cyl, drive->head, drive->sect);
-	out += sprintf(out,"logical      %hi/%hi/%hi\n", drive->bios_cyl, drive->bios_head, drive->bios_sect);
+	out += sprintf(out,"physical     %d/%d/%d\n", drive->cyl, drive->head, drive->sect);
+	out += sprintf(out,"logical      %d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	len = out - page;
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
@@ -625,21 +638,30 @@
 	return sprintf(page, "ide%d/%s", n, de->name);
 }
 
-static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *parent, struct proc_dir_entry *root)
+static void create_proc_ide_drives(ide_hwif_t *hwif)
 {
 	int	d;
 	struct proc_dir_entry *ent;
+	struct proc_dir_entry *parent = hwif->proc;
 
 	for (d = 0; d < MAX_DRIVES; d++) {
 		ide_drive_t *drive = &hwif->drives[d];
+		ide_driver_t *driver = drive->driver;
 
 		if (!drive->present)
 			continue;
-		drive->proc = create_proc_entry(drive->name, S_IFDIR, parent);
 		if (drive->proc)
-			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
+			continue;
 
-		ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, root);
+		drive->proc = create_proc_entry(drive->name, S_IFDIR, parent);
+		if (drive->proc) {
+			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
+			if (driver) {
+				ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
+				ide_add_proc_entries(drive->proc, driver->proc, drive);
+			}
+		}
+		ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, proc_ide_root);
 		if (!ent) return;
 		ent->data = drive;
 		ent->readlink_proc = proc_ide_readlink;
@@ -647,6 +669,25 @@
 	}
 }
 
+void destroy_proc_ide_drives(ide_hwif_t *hwif)
+{
+	int	d;
+
+	for (d = 0; d < MAX_DRIVES; d++) {
+		ide_drive_t *drive = &hwif->drives[d];
+		ide_driver_t *driver = drive->driver;
+
+		if (!drive->proc)
+			continue;
+		if (driver)
+			ide_remove_proc_entries(drive->proc, driver->proc);
+		ide_remove_proc_entries(drive->proc, generic_drive_entries);
+		remove_proc_entry(drive->name, proc_ide_root);
+		remove_proc_entry(drive->name, hwif->proc);
+		drive->proc = NULL;
+	}
+}
+
 static ide_proc_entry_t hwif_entries[] = {
 	{ "channel",	S_IFREG|S_IRUGO,	proc_ide_read_channel,	NULL },
 	{ "config",	S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config,	proc_ide_write_config },
@@ -655,33 +696,69 @@
 	{ NULL,	0, NULL, NULL }
 };
 
-static void create_proc_ide_interfaces (struct proc_dir_entry *parent)
+void create_proc_ide_interfaces(void)
 {
 	int	h;
-	struct proc_dir_entry *hwif_ent;
 
 	for (h = 0; h < MAX_HWIFS; h++) {
 		ide_hwif_t *hwif = &ide_hwifs[h];
+		int exist = (hwif->proc != NULL);
 
 		if (!hwif->present)
 			continue;
-		hwif_ent = create_proc_entry(hwif->name, S_IFDIR, parent);
-		if (!hwif_ent) return;
-		ide_add_proc_entries(hwif_ent, hwif_entries, hwif);
-		create_proc_ide_drives(hwif, hwif_ent, parent);
+		if (!exist)
+			hwif->proc = create_proc_entry(hwif->name, S_IFDIR, proc_ide_root);
+		if (!hwif->proc)
+			return;
+		if (!exist)
+			ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
+		create_proc_ide_drives(hwif);
+	}
+}
+
+static void destroy_proc_ide_interfaces(void)
+{
+	int	h;
+
+	for (h = 0; h < MAX_HWIFS; h++) {
+		ide_hwif_t *hwif = &ide_hwifs[h];
+		int exist = (hwif->proc != NULL);
+
+/*		if (!hwif->present)
+			continue;*/
+		if (!hwif->proc)
+			continue;
+		else {
+			destroy_proc_ide_drives(hwif);
+			ide_remove_proc_entries(hwif->proc, hwif_entries);
+			remove_proc_entry(hwif->name, proc_ide_root);
+			hwif->proc = NULL;
+		}
 	}
 }
 
 void proc_ide_create(void)
 {
-	struct proc_dir_entry *root, *ent;
-	root = create_proc_entry("ide", S_IFDIR, 0);
-	if (!root) return;
-	create_proc_ide_interfaces(root);
+	struct proc_dir_entry *ent;
+	proc_ide_root = create_proc_entry("ide", S_IFDIR, 0);
+	if (!proc_ide_root) return;
+	create_proc_ide_interfaces();
 
-	ent = create_proc_entry("drivers", 0, root);
+	ent = create_proc_entry("drivers", 0, proc_ide_root);
 	if (!ent) return;
 	ent->read_proc  = proc_ide_read_drivers;
+#ifdef CONFIG_BLK_DEV_VIA82C586
+	if (via_display_info) {
+		ent = create_proc_entry("via", 0, proc_ide_root);
+		ent->get_info = via_display_info;
+	}
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+#ifdef CONFIG_BLK_DEV_ALI15X3
+	if (ali_display_info) {
+		ent = create_proc_entry("ali", 0, proc_ide_root);
+		ent->get_info = ali_display_info;
+	}
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
 }
 
 void proc_ide_destroy(void)
@@ -690,6 +767,15 @@
 	 * Mmmm.. does this free up all resources,
 	 * or do we need to do a more proper cleanup here ??
 	 */
+#ifdef CONFIG_BLK_DEV_VIA82C586
+	if (via_display_info)
+		remove_proc_entry("ide/via",0);
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+#ifdef CONFIG_BLK_DEV_ALI15X3
+	if (ali_display_info)
+		remove_proc_entry("ide/ali",0);
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
 	remove_proc_entry("ide/drivers", 0);
+	destroy_proc_ide_interfaces();
 	remove_proc_entry("ide", 0);
 }
diff -urN linux-2.2.10-pristine/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- linux-2.2.10-pristine/drivers/block/ide-tape.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide-tape.c	Thu Jul 22 20:38:43 1999
@@ -338,6 +338,8 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -347,11 +349,6 @@
 #include <asm/bitops.h>
 
 /*
- *	Main Linux ide driver include file
- */
-#include "ide.h"
-
-/*
  *	For general magnetic tape device compatibility.
  */
 #include <linux/mtio.h>
@@ -401,6 +398,7 @@
 /*
  *	The following are used to debug the driver:
  *
+ *	Setting IDETAPE_INFO_LOG to 1 will log driver vender information.
  *	Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
  *	Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in
  *	some places.
@@ -415,9 +413,15 @@
  *	is verified to be stable enough. This will make it much more
  *	esthetic.
  */
+#define IDETAPE_INFO_LOG		0
 #define IDETAPE_DEBUG_LOG		0
 #define IDETAPE_DEBUG_BUGS		1
 
+#if IDETAPE_DEBUG_LOG
+#undef IDETAPE_INFO_LOG
+#define IDETAPE_INFO_LOG		IDETAPE_DEBUG_LOG
+#endif
+
 /*
  *	After each failed packet command we issue a request sense command
  *	and retry the packet command IDETAPE_MAX_PC_RETRIES times.
@@ -1968,7 +1972,8 @@
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
@@ -3337,16 +3342,16 @@
 static int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id)
 {
 	struct idetape_id_gcw gcw;
-#if IDETAPE_DEBUG_LOG
+#if IDETAPE_INFO_LOG
 	unsigned short mask,i;
-#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_INFO_LOG */
 
 	if (!id)
 		return 0;
 
 	*((unsigned short *) &gcw) = id->config;
 
-#if IDETAPE_DEBUG_LOG
+#if IDETAPE_INFO_LOG
 	printk (KERN_INFO "Dumping ATAPI Identify Device tape parameters\n");
 	printk (KERN_INFO "Protocol Type: ");
 	switch (gcw.protocol) {
@@ -3434,7 +3439,7 @@
 		
 	} else
 		printk (KERN_INFO "According to the device, fields 64-70 are not valid.\n");
-#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_INFO_LOG */
 
 	/* Check that we can support this device */
 
@@ -3491,7 +3496,7 @@
 
 	tape->capabilities = *capabilities;		/* Save us a copy */
 	tape->tape_block_size = capabilities->blk512 ? 512:1024;
-#if IDETAPE_DEBUG_LOG
+#if IDETAPE_INFO_LOG
 	printk (KERN_INFO "Dumping the results of the MODE SENSE packet command\n");
 	printk (KERN_INFO "Mode Parameter Header:\n");
 	printk (KERN_INFO "Mode Data Length - %d\n",header->mode_data_length);
@@ -3519,7 +3524,7 @@
 	printk (KERN_INFO "Continuous transfer limits in blocks - %d\n",capabilities->ctl);
 	printk (KERN_INFO "Current speed in KBps - %d\n",capabilities->speed);	
 	printk (KERN_INFO "Buffer size - %d\n",capabilities->buffer_size*512);
-#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_INFO_LOG */
 }
 
 static void idetape_add_settings(ide_drive_t *drive)
@@ -3561,7 +3566,18 @@
 
 	drive->driver_data = tape;
 	drive->ready_stat = 0;			/* An ATAPI device ignores DRDY */
-	drive->dsc_overlap = 1;
+#ifdef CONFIG_BLK_DEV_IDEPCI
+	/*
+	 *  These two ide-pci host adapters appear to need this disabled.
+	 */
+	if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
+	    (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
+		drive->dsc_overlap = 0;
+	} else
+#endif  /* CONFIG_BLK_DEV_IDEPCI */
+	{
+		drive->dsc_overlap = 1;
+	}
 	memset (tape, 0, sizeof (idetape_tape_t));
 	tape->drive = drive;
 	tape->minor = minor;
@@ -3798,8 +3814,14 @@
 
 	for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) {
 		drive = idetape_chrdevs[minor].drive;
-		if (drive != NULL && idetape_cleanup (drive))
-			printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name);
+		if (drive) {
+			if (idetape_cleanup (drive))
+				printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name);
+			/* We must remove proc entries defined in this module.
+			   Otherwise we oops while accessing these entries */
+			if (drive->proc)
+				ide_remove_proc_entries(drive->proc, idetape_proc);
+		}
 	}
 	ide_unregister_module(&idetape_module);
 }
diff -urN linux-2.2.10-pristine/drivers/block/ide.c linux/drivers/block/ide.c
--- linux-2.2.10-pristine/drivers/block/ide.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide.c	Fri Jul 23 01:08:48 1999
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 6.18  August 16, 1998
+ *  linux/drivers/block/ide.c	Version 6.20  July 10, 1999
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -92,13 +92,24 @@
  * Version 6.16		fixed various bugs; even more SMP friendly
  * Version 6.17		fix for newest EZ-Drive problem
  * Version 6.18		default unpartitioned-disk translation now "BIOS LBA"
+ * Version 6.19		Re-design for a UNIFORM driver for all platforms,
+ *			model based on suggestions from Russell King and
+ *			Geert Uytterhoeven
+ *			Promise DC4030VL now supported.
+ *			delay_50ms() changed to ide_delay_50ms() and exported.
+ * Version 6.20		Added/Fixed Generic ATA-66 support and hwif detection.
+ *			Added hdx=flash to allow for second flash disk
+ *			detection w/o the hang loop.
  *
- *  Some additional driver compile-time options are in ide.h
+ *  Some additional driver compile-time options are in ./include/linux/ide.h
  *
  *  To do, in likely order of completion:
  *	- modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
 */
 
+#define	REVISION	"Revision: 6.20"
+#define	VERSION		"Id: ide.c 6.20 1999/07/10"
+
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
 #define _IDE_C			/* Tell ide.h it's really us */
@@ -117,6 +128,7 @@
 #include <linux/malloc.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -124,24 +136,29 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-#include "ide.h"
 #include "ide_modes.h"
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif /* CONFIG_KMOD */
 
-static const byte	ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR };
+#ifdef CONFIG_BLK_DEV_VIA82C586
+extern byte fifoconfig;           /* defined in via82c586.c used by ide_setup()*/
+#endif
+
+static const byte	ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR };
 
 static int	idebus_parameter; /* holds the "idebus=" parameter */
 static int	system_bus_speed; /* holds what we think is VESA/PCI bus speed */
 static int	initializing;     /* set while initializing built-in drivers */
 
+#if defined(__mc68000__) || defined(CONFIG_APUS)
 /*
  * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
  * which is shared between several drivers.
  */
 static int	ide_lock = 0;
+#endif /* __mc68000__ || CONFIG_APUS */
 
 /*
  * ide_modules keeps track of the available IDE chipset/probe/driver modules.
@@ -187,14 +204,18 @@
 static void init_hwif_data (unsigned int index)
 {
 	unsigned int unit;
+	hw_regs_t hw;
 	ide_hwif_t *hwif = &ide_hwifs[index];
 
 	/* bulk initialize hwif & drive info with zeros */
 	memset(hwif, 0, sizeof(ide_hwif_t));
+	memset(&hw, 0, sizeof(hw_regs_t));
 
 	/* fill in any non-zero initial values */
 	hwif->index     = index;
-	ide_init_hwif_ports(hwif->io_ports, ide_default_io_base(index), &hwif->irq);
+	ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
+	memcpy(&hwif->hw, &hw, sizeof(hw));
+	memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
 	hwif->noprobe	= !hwif->io_ports[IDE_DATA_OFFSET];
 #ifdef CONFIG_BLK_DEV_HD
 	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
@@ -246,9 +267,13 @@
 		return;		/* already initialized */
 	magic_cookie = 0;
 
+	/* Initialise all interface structures */
 	for (index = 0; index < MAX_HWIFS; ++index)
 		init_hwif_data(index);
 
+	/* Add default hw interfaces */
+	ide_init_default_hwifs();
+
 	idebus_parameter = 0;
 	system_bus_speed = 0;
 }
@@ -271,9 +296,10 @@
 
 	if (drive->removable && id != NULL) {
 		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
-		 || !strncmp(id->model, "Hitachi CV", 10)		/* Hitachi */
+		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
 		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* SunDisk */
-		 || !strncmp(id->model, "HAGIWARA HPC", 12))	/* Hagiwara */
+		 || !strncmp(id->model, "HAGIWARA HPC", 12)	/* Hagiwara */
+		 || !strncmp(id->model, "ATA_FLASH", 9))	/* Simple Tech */
 		{
 			return 1;	/* yes, it is a flash memory card */
 		}
@@ -653,6 +679,10 @@
 		pre_reset(&hwif->drives[unit]);
 
 #if OK_TO_RESET_CONTROLLER
+	if (!IDE_CONTROL_REG) {
+		__restore_flags(flags);
+		return;
+	}
 	/*
 	 * Note that we also set nIEN while resetting the device,
 	 * to mask unwanted interrupts from the interface during the reset.
@@ -858,7 +888,8 @@
 void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
 	ide_set_handler (drive, handler, WAIT_CMD);
-	OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
 	OUT_BYTE(nsect,IDE_NSECTOR_REG);
 	OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
@@ -1264,6 +1295,20 @@
 }
 #endif /* MAX_HWIFS > 5 */
 
+#if MAX_HWIFS > 6
+void do_ide6_request (void)
+{
+	unlock_do_hwgroup_request (ide_hwifs[6].hwgroup);
+}
+#endif /* MAX_HWIFS > 6 */
+
+#if MAX_HWIFS > 7
+void do_ide7_request (void)
+{
+	unlock_do_hwgroup_request (ide_hwifs[7].hwgroup);
+}
+#endif /* MAX_HWIFS > 7 */
+
 static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
 {
 	unsigned long	flags;
@@ -1310,7 +1355,7 @@
 			(void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
 			printk("%s: timeout waiting for DMA\n", drive->name);
 	/*
-	 *  need something here for HX PIIX3 UDMA and HPT343.......AMH
+	 *  need something here for HPT34X.......AMH
 	 *  irq timeout: status=0x58 { DriveReady SeekComplete DataRequest }
 	 */
 		}
@@ -1381,6 +1426,12 @@
 	__cli();	/* local CPU only */
 	spin_lock_irqsave(&hwgroup->spinlock, flags);
 	hwif = hwgroup->hwif;
+
+	if (!ide_ack_intr(hwif)) {
+		spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+		return;
+	}
+
 	if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
 		/*
 		 * Not expecting an interrupt from this drive.
@@ -1402,7 +1453,6 @@
 			 * Probably not a shared PCI interrupt,
 			 * so we can safely try to do something about it:
 			 */
-			(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
 			unexpected_intr(irq, hwgroup);
 		}
 		spin_unlock_irqrestore(&hwgroup->spinlock, flags);
@@ -1414,7 +1464,6 @@
 		return;
 	}
 	hwgroup->handler = NULL;
-	(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
 	del_timer(&(hwgroup->timer));
 	spin_unlock_irqrestore(&hwgroup->spinlock, flags);
 	if (drive->unmask)
@@ -1503,8 +1552,10 @@
 	struct request *cur_rq;
 	struct semaphore sem = MUTEX_LOCKED;
 
-	if (IS_PDC4030_DRIVE && rq->buffer != NULL)
+#ifdef CONFIG_BLK_DEV_PDC4030
+	if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
 		return -ENOSYS;  /* special drive cmds not supported */
+#endif
 	rq->errors = 0;
 	rq->rq_status = RQ_ACTIVE;
 	rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
@@ -1636,6 +1687,11 @@
 
 	if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
 		return -ENXIO;
+	if (drive->media == ide_disk) {
+		int minor = (MINOR(inode->i_rdev) & PARTN_MASK);
+		if (drive->part[minor].nr_sects == 0)
+			return -ENXIO;		/* no such partition */
+	}
 	MOD_INC_USE_COUNT;
 	if (drive->driver == NULL)
 		ide_init_module(IDE_DRIVER_MODULE);
@@ -1699,6 +1755,13 @@
 	return 1;
 }
 
+#ifdef CONFIG_PROC_FS
+ide_proc_entry_t generic_subdriver_entries[] = {
+	{ "capacity",	S_IFREG|S_IRUGO,	proc_ide_read_capacity,	NULL },
+	{ NULL, 0, NULL, NULL }
+};
+#endif
+
 void ide_unregister (unsigned int index)
 {
 	struct gendisk *gd, **gdp;
@@ -1708,6 +1771,7 @@
 	int irq_count = 0, unit, i;
 	unsigned long flags;
 	unsigned int p, minor;
+	ide_hwif_t old_hwif;
 
 	if (index >= MAX_HWIFS)
 		return;
@@ -1744,6 +1808,9 @@
 				invalidate_buffers (devp);
 			}
 		}
+#ifdef CONFIG_PROC_FS
+		destroy_proc_ide_drives(hwif);
+#endif
 	}
 	cli();
 	hwgroup = hwif->hwgroup;
@@ -1766,7 +1833,8 @@
 	 * allocated for weird IDE interface chipsets.
 	 */
 	ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-	ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+	if (hwif->io_ports[IDE_CONTROL_OFFSET])
+		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 
 	/*
 	 * Remove us from the hwgroup, and free
@@ -1825,26 +1893,78 @@
 		kfree(gd->part);
 		kfree(gd);
 	}
+	old_hwif = *hwif;
 	init_hwif_data (index);	/* restore hwif data to pristine status */
+	hwif->hwgroup = old_hwif.hwgroup;
+	hwif->tuneproc = old_hwif.tuneproc;
+	hwif->dmaproc = old_hwif.dmaproc;
+	hwif->dma_base = old_hwif.dma_base;
+	hwif->dma_extra = old_hwif.dma_extra;
+	hwif->config_data = old_hwif.config_data;
+	hwif->select_data = old_hwif.select_data;
+	hwif->irq = old_hwif.irq;
+	hwif->major = old_hwif.major;
+	hwif->proc = old_hwif.proc;
+	hwif->chipset = old_hwif.chipset;
+	hwif->udma_four = old_hwif.udma_four;
+	hwif->pci_dev = old_hwif.pci_dev;
+	hwif->pci_devid = old_hwif.pci_devid;
 abort:
 	restore_flags(flags);	/* all CPUs */
 }
 
-int ide_register (int arg1, int arg2, int irq)
+/*
+ * Setup hw_regs_t structure described by parameters.  You
+ * may set up the hw structure yourself OR use this routine to
+ * do it for you.
+ */
+void ide_setup_ports (	hw_regs_t *hw,
+			ide_ioreg_t base, int *offsets,
+			ide_ioreg_t ctrl, ide_ioreg_t intr,
+			ide_ack_intr_t *ack_intr, int irq)
+{
+	int i;
+
+	for (i = 0; i < IDE_NR_PORTS; i++) {
+		if (offsets[i] == -1) {
+			switch(i) {
+				case IDE_CONTROL_OFFSET:
+					hw->io_ports[i] = ctrl;
+					break;
+				case IDE_IRQ_OFFSET:
+					hw->io_ports[i] = intr;
+					break;
+				default:
+					hw->io_ports[i] = 0;
+					break;
+			}
+		} else {
+			hw->io_ports[i] = base + offsets[i];
+		}
+	}
+	hw->irq = irq;
+	hw->ack_intr = ack_intr;
+}
+
+/*
+ * Register an IDE interface, specifing exactly the registers etc
+ * Set init=1 iff calling before probes have taken place.
+ */
+int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
 {
 	int index, retry = 1;
 	ide_hwif_t *hwif;
-	ide_ioreg_t data_port = (ide_ioreg_t) arg1, ctl_port = (ide_ioreg_t) arg2;
 
 	do {
 		for (index = 0; index < MAX_HWIFS; ++index) {
 			hwif = &ide_hwifs[index];
-			if (hwif->io_ports[IDE_DATA_OFFSET] == data_port)
+			if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
 				goto found;
 		}
 		for (index = 0; index < MAX_HWIFS; ++index) {
 			hwif = &ide_hwifs[index];
-			if (!hwif->present)
+			if ((!hwif->present && !hwif->mate && !initializing) ||
+			    (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
 				goto found;
 		}
 		for (index = 0; index < MAX_HWIFS; index++)
@@ -1856,14 +1976,35 @@
 		ide_unregister(index);
 	if (hwif->present)
 		return -1;
-	ide_init_hwif_ports(hwif->io_ports, data_port, &hwif->irq);
-	if (ctl_port)
-		hwif->io_ports[IDE_CONTROL_OFFSET] = ctl_port;
-	hwif->irq = irq;
+	memcpy(&hwif->hw, hw, sizeof(*hw));
+	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
+	hwif->irq = hw->irq;
 	hwif->noprobe = 0;
-	ide_init_module(IDE_PROBE_MODULE);
-	ide_init_module(IDE_DRIVER_MODULE);
-	return hwif->present ? index : -1;
+
+	if (!initializing) {
+		ide_init_module(IDE_PROBE_MODULE);
+#ifdef CONFIG_PROC_FS
+		create_proc_ide_interfaces();
+#endif
+		ide_init_module(IDE_DRIVER_MODULE);
+	}
+
+	if (hwifp)
+		*hwifp = hwif;
+
+	return (initializing || hwif->present) ? index : -1;
+}
+
+/*
+ * Compatability function with existing drivers.  If you want
+ * something different, use the function above.
+ */
+int ide_register (int arg1, int arg2, int irq)
+{
+	hw_regs_t hw;
+	ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);
+	hw.irq = irq;
+	return ide_register_hw(&hw, NULL);
 }
 
 void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
@@ -2088,10 +2229,45 @@
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
+/*
+ * Delay for *at least* 50ms.  As we don't know how much time is left
+ * until the next tick occurs, we wait an extra tick to be safe.
+ * This is used only during the probing/polling for drives at boot time.
+ *
+ * However, its usefullness may be needed in other places, thus we export it now.
+ * The future may change this to a millisecond setable delay.
+ */
+void ide_delay_50ms (void)
+{
+	unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
+	while (0 < (signed long)(timeout - jiffies));
+}
+
+int ide_config_drive_speed (ide_drive_t *drive, byte speed)
+{
+	int err;
+
+	/*
+	 * Don't use ide_wait_cmd here - it will
+	 * attempt to set_geometry and recalibrate,
+	 * but for some reason these don't work at
+	 * this point (lost interrupt).
+	 */
+	SELECT_DRIVE(HWIF(drive), drive);
+	OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+	OUT_BYTE(speed, IDE_NSECTOR_REG);
+	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
+
+	err = ide_wait_stat(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD);
+
+	return(err);
+}
+
 static int ide_ioctl (struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	int err, major, minor;
+	int err = 0, major, minor;
 	ide_drive_t *drive;
 	struct request rq;
 	kdev_t dev;
@@ -2179,7 +2355,73 @@
 					return -ENOMEM;
 				memcpy(argbuf, args, 4);
 			}
+			if ((((byte *)arg)[0] == WIN_SETFEATURES) &&
+			    (((byte *)arg)[1] > 66) &&
+			    (((byte *)arg)[2] == 3)) {
+				if (!HWIF(drive)->udma_four) {
+					printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name);
+					goto abort;
+				}
+				if ((drive->id->word93 & 0x2000) == 0) {
+					printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
+					goto abort;
+				}
+			}
 			err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
+			if (!err &&
+			    (((byte *)arg)[0] == WIN_SETFEATURES) &&
+			    (((byte *)arg)[1] >= 16) &&
+			    (((byte *)arg)[2] == 3) &&
+			    (drive->id->dma_ultra ||
+			     drive->id->dma_mword ||
+			     drive->id->dma_1word)) {
+
+				/* 
+				 * Re-read drive->id for possible DMA mode 
+				 * change (copied from ide-probe.c)
+				 */
+				struct hd_driveid *id;
+				unsigned long timeout, irqs, flags;
+
+				probe_irq_off(probe_irq_on());
+				irqs = probe_irq_on();
+				if (IDE_CONTROL_REG)
+					OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+				ide_delay_50ms();
+				OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG);
+				timeout = jiffies + WAIT_WORSTCASE;
+				do {
+					if (0 < (signed long)(jiffies - timeout)) {
+						if (irqs)
+							(void) probe_irq_off(irqs);
+						goto abort;	/* drive timed-out */
+					}
+					ide_delay_50ms();		/* give drive a breather */
+				} while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
+				ide_delay_50ms();           /* wait for IRQ and DRQ_STAT */
+				if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+					goto abort;
+				__save_flags(flags);	/* local CPU only */
+				__cli();		/* local CPU only; some systems need this */
+				id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+				ide_input_data(drive, id, SECTOR_WORDS);
+				(void) GET_STAT();	/* clear drive IRQ */
+				ide__sti();		/* local CPU only */
+				__restore_flags(flags);	/* local CPU only */
+				ide_fix_driveid(id);
+				if (id && id->cyls) {
+					drive->id->dma_ultra = id->dma_ultra;
+					drive->id->dma_mword = id->dma_mword;
+					drive->id->dma_1word = id->dma_1word;
+					/* anything more ? */
+#ifdef DEBUG
+					printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
+						drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
+#endif
+				kfree(id);
+				}
+			}
+		abort:
 			if (copy_to_user((void *)arg, argbuf, argsize))
 				err = -EFAULT;
 			if (argsize > 4)
@@ -2265,6 +2507,32 @@
 }
 
 /*
+ *
+ */
+char *ide_xfer_verbose (byte xfer_rate) {
+	switch(xfer_rate) {
+		case XFER_UDMA_4:	return("UDMA 4");
+		case XFER_UDMA_3:	return("UDMA 3");
+		case XFER_UDMA_2:	return("UDMA 2");
+		case XFER_UDMA_1:	return("UDMA 1");
+		case XFER_UDMA_0:	return("UDMA 0");
+		case XFER_MW_DMA_2:	return("MW DMA 2");
+		case XFER_MW_DMA_1:	return("MW DMA 1");
+		case XFER_MW_DMA_0:	return("MW DMA 0");
+		case XFER_SW_DMA_2:	return("SW DMA 2");
+		case XFER_SW_DMA_1:	return("SW DMA 1");
+		case XFER_SW_DMA_0:	return("SW DMA 0");
+		case XFER_PIO_4:	return("PIO 4");
+		case XFER_PIO_3:	return("PIO 3");
+		case XFER_PIO_2:	return("PIO 2");
+		case XFER_PIO_1:	return("PIO 1");
+		case XFER_PIO_0:	return("PIO 0");
+		case XFER_PIO_SLOW:	return("PIO SLOW");
+		default:		return("XFER ERROR");
+	}
+}
+
+/*
  * stridx() returns the offset of c within s,
  * or -1 if c is '\0' or not found within s.
  */
@@ -2353,6 +2621,9 @@
  *
  * "hdx=swapdata"	: when the drive is a disk, byte swap all data
  * "hdx=bswap"		: same as above..........
+ * "hdx=flash"		: allows for mor than one ata_flash disk to be
+ *				registered. In most cases, only one device
+ *				will be present.
  *
  * "idebus=xx"		: inform IDE driver of VESA/PCI bus speed in MHz,
  *				where "xx" is between 20 and 66 inclusive,
@@ -2383,7 +2654,22 @@
  * "idex=reset"		: reset interface before first use
  * "idex=dma"		: enable DMA by default on both drives if possible
  *
- * The following are valid ONLY on ide0,
+ * "splitfifo=betweenChan"
+ *			: FIFO Configuration of VIA 82c586(<nothing>,"A"or"B").
+ *                                 --see what follows...
+ * "splitfifo=betweenChan,thresholdprim,thresholdsec"
+ *			: FIFO Configuration of VIA 82c586(<nothing>,"A" or "B").
+ *				betweenChan = 1(all FIFO's to primary channel)
+ *                                          , 2(all FIFO's to secondary channel)
+ *                                          , 3 or 4(evenly shared between them).
+ *				note: without FIFO, a channel is (u)dma disabled!
+ *				thresholdprim = 4, 3, 2 or 1
+ *						(standing for 1, 3/4, 1/2, 1/4).
+ *                                    Sets the threshold of FIFO to begin dma
+ *                                    transfer on the primary channel.
+ *				thresholdsec = cf upper, but for secondary channel.
+ *
+ * The following are valid ONLY on ide0, (except dc4030)
  * and the defaults for the base,ctl ports must not be altered.
  *
  * "ide0=dtc2278"	: probe/support DTC2278 interface
@@ -2393,6 +2679,7 @@
  * "ide0=qd6580"	: probe/support qd6580 interface
  * "ide0=ali14xx"	: probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
  * "ide0=umc8672"	: probe/support umc8672 chipsets
+ * "idex=dc4030"	: probe/support Promise DC4030VL interface
  */
 __initfunc(void ide_setup (char *s))
 {
@@ -2404,6 +2691,17 @@
 	const char max_hwif  = '0' + (MAX_HWIFS - 1);
 
 	printk("ide_setup: %s", s);
+
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+	if (!strcmp(s, "ide=doubler")) {
+		extern int ide_doubler;
+
+		printk("ide: Enabled support for IDE doublers\n");
+		ide_doubler = 1;
+		return;
+	}
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
 	init_ide_data ();
 
 	/*
@@ -2412,7 +2710,7 @@
 	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
 		const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
 				"serialize", "autotune", "noautotune",
-				"slow", "swapdata", "bswap", NULL};
+				"slow", "swapdata", "bswap", "flash", NULL};
 		unit = s[2] - 'a';
 		hw   = unit / MAX_DRIVES;
 		unit = unit % MAX_DRIVES;
@@ -2453,6 +2751,9 @@
 			case -10:
 				drive->bswap = 1;
 				goto done;
+			case -11:
+				drive->ata_flash = 1;
+				goto done;
 			case 3: /* cyl,head,sect */
 				drive->media	= ide_disk;
 				drive->cyl	= drive->bios_cyl  = vals[0];
@@ -2467,6 +2768,58 @@
 		}
 	}
 
+#if defined(CONFIG_BLK_DEV_VIA82C586)
+	/*
+	 *  Look for drive option "splitfifo=..."
+	 */
+
+	if (s[0] == 's' && s[1] == 'p' && s[2] == 'l' &&
+	    s[3] == 'i' && s[4] == 't' && s[5] == 'f' &&
+	    s[6] == 'i' && s[7] == 'f' && s[8] == 'o') {
+		byte tmp = 0x3a;		/* default config byte */
+
+		i = match_parm(&s[9], NULL, vals, 3);
+		switch(i) {
+		case 3:	
+			tmp &= 0xf0;
+			if ((vals[1] > 0) && (vals[1] < 5)) {
+				/* sets threshold for primary Channel: */
+				byte x = 4 - vals[1];
+				tmp |= (x << 2);
+			}
+			else
+				goto bad_option;
+			if ((vals[2] > 0) && (vals[2] < 5)) {
+				/* sets threshold for secondary Channel: */
+				byte x = 4 - vals[2];
+				tmp |= x;
+			}
+			else
+				goto bad_option;
+		case 1:
+			/* set the FIFO config between channels to 0: */
+			tmp &= 0x9f;
+			/* set the needed FIFO config between channels: */
+			if (vals[0] == 1)	/* primary fifo only */
+				tmp |= 0x10;
+			else if (vals[0] == 2)	/* secondary fifo only */
+				tmp |= 0x70;
+			else if (vals[0] == 4)	/* other shared fifo config */
+				tmp |= 0x50;
+			else if (vals[0] == 3)	/* default config */
+				tmp |= 0x30;
+			else
+				goto bad_option;
+			break;
+		default:
+			goto bad_option;
+		}
+		/* set the found option in fifoconfig */
+		fifoconfig = tmp;		
+		goto done;
+	}
+#endif  /* defined(CONFIG_BLK_DEV_VIA82C586) */
+
 	if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
 		goto bad_option;
 	/*
@@ -2500,9 +2853,9 @@
 		if (i > 0 || i <= -7) {			/* is parameter a chipset name? */
 			if (hwif->chipset != ide_unknown)
 				goto bad_option;	/* chipset already specified */
-			if (i <= -7 && hw != 0)
+			if (i <= -7 && i != -14 && hw != 0)
 				goto bad_hwif;		/* chipset drivers are for "ide0=" only */
-			if (i <= -7 && ide_hwifs[hw^1].chipset != ide_unknown)
+			if (i <= -7 && i != -14 && ide_hwifs[hw+1].chipset != ide_unknown)
 				goto bad_option;	/* chipset for 2nd port already specified */
 			printk("\n");
 		}
@@ -2511,8 +2864,8 @@
 #ifdef CONFIG_BLK_DEV_PDC4030
 			case -14: /* "dc4030" */
 			{
-				extern void setup_pdc4030(ide_hwif_t *);
-				setup_pdc4030(hwif);
+				extern void init_pdc4030(void);
+				init_pdc4030();
 				goto done;
 			}
 #endif /* CONFIG_BLK_DEV_PDC4030 */
@@ -2606,8 +2959,9 @@
 			case 2: /* base,ctl */
 				vals[2] = 0;	/* default irq = probe for it */
 			case 3: /* base,ctl,irq */
-				ide_init_hwif_ports(hwif->io_ports, (ide_ioreg_t) vals[0], &hwif->irq);
-				hwif->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) vals[1];
+				hwif->hw.irq = vals[2];
+				ide_init_hwif_ports(&hwif->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &hwif->irq);
+				memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 				hwif->irq      = vals[2];
 				hwif->noprobe  = 0;
 				hwif->chipset  = ide_generic;
@@ -2721,14 +3075,15 @@
 			printk("[remap +63] ");
 		}
 	}
+
 	drive->part[0].nr_sects = current_capacity(drive);
 	printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	/*
 	 * Update the current 3D drive values.
 	 */
-	drive->id->cur_cyls    = drive->bios_cyl;
-	drive->id->cur_heads   = drive->bios_head;
-	drive->id->cur_sectors = drive->bios_sect;
+	drive->id->cur_cyls	= drive->bios_cyl;
+	drive->id->cur_heads	= drive->bios_head;
+	drive->id->cur_sectors	= drive->bios_sect;
 	return 1;
 }
 
@@ -2761,8 +3116,8 @@
 #endif /* CONFIG_BLK_DEV_CMD640 */
 #ifdef CONFIG_BLK_DEV_PDC4030
 	{
-		extern int init_pdc4030(void);
-		(void) init_pdc4030();
+		extern int ide_probe_for_pdc4030(void);
+		(void) ide_probe_for_pdc4030();
 	}
 #endif /* CONFIG_BLK_DEV_PDC4030 */
 #ifdef CONFIG_BLK_DEV_IDE_PMAC
@@ -2771,6 +3126,42 @@
 		pmac_ide_probe();
 	}
 #endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
+	{
+		extern void icside_init(void);
+		icside_init();
+	}
+#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */
+#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
+	{
+		extern void rapide_init(void);
+		rapide_init();
+	}
+#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
+#ifdef CONFIG_BLK_DEV_GAYLE
+	{
+		extern void gayle_init(void);
+		gayle_init();
+	}
+#endif /* CONFIG_BLK_DEV_GAYLE */
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+	{
+		extern void falconide_init(void);
+		falconide_init();
+	}
+#endif /* CONFIG_BLK_DEV_FALCON_IDE */
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+	{
+		extern void macide_init(void);
+		macide_init();
+	}
+#endif /* CONFIG_BLK_DEV_MAC_IDE */
+#ifdef CONFIG_BLK_DEV_BUDDHA
+	{
+		extern void buddha_init(void);
+		buddha_init();
+	}
+#endif /* CONFIG_BLK_DEV_BUDDHA */
 }
 
 __initfunc(void ide_init_builtin_drivers (void))
@@ -2919,13 +3310,6 @@
 	return NULL;
 }
 
-#ifdef CONFIG_PROC_FS
-static ide_proc_entry_t generic_subdriver_entries[] = {
-	{ "capacity",	S_IFREG|S_IRUGO,	proc_ide_read_capacity,	NULL },
-	{ NULL, 0, NULL, NULL }
-};
-#endif
-
 int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version)
 {
 	unsigned long flags;
@@ -3045,6 +3429,12 @@
 #if MAX_HWIFS > 5
 EXPORT_SYMBOL(do_ide5_request);
 #endif /* MAX_HWIFS > 5 */
+#if MAX_HWIFS > 6
+EXPORT_SYMBOL(do_ide6_request);
+#endif /* MAX_HWIFS > 6 */
+#if MAX_HWIFS > 7
+EXPORT_SYMBOL(do_ide7_request);
+#endif /* MAX_HWIFS > 7 */
 
 /*
  * Driver module
@@ -3069,23 +3459,35 @@
 EXPORT_SYMBOL(ide_revalidate_disk);
 EXPORT_SYMBOL(ide_cmd);
 EXPORT_SYMBOL(ide_wait_cmd);
+EXPORT_SYMBOL(ide_delay_50ms);
+EXPORT_SYMBOL(ide_config_drive_speed);
 EXPORT_SYMBOL(ide_stall_queue);
 #ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(ide_add_proc_entries);
 EXPORT_SYMBOL(ide_remove_proc_entries);
 EXPORT_SYMBOL(proc_ide_read_geometry);
+EXPORT_SYMBOL(create_proc_ide_interfaces);
 #endif
 EXPORT_SYMBOL(ide_add_setting);
 EXPORT_SYMBOL(ide_remove_setting);
 
+EXPORT_SYMBOL(ide_register_hw);
 EXPORT_SYMBOL(ide_register);
 EXPORT_SYMBOL(ide_unregister);
+EXPORT_SYMBOL(ide_setup_ports);
 
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
 __initfunc(int ide_init (void))
 {
+	static char banner_printed = 0;
+
+	if (!banner_printed) {
+		printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
+		banner_printed = 1;
+	}
+
 	init_ide_data ();
 
 	initializing = 1;
diff -urN linux-2.2.10-pristine/drivers/block/ide.h linux/drivers/block/ide.h
--- linux-2.2.10-pristine/drivers/block/ide.h	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide.h	Wed Dec 31 18:00:00 1969
@@ -1,769 +0,0 @@
-#ifndef _IDE_H
-#define _IDE_H
-/*
- *  linux/drivers/block/ide.h
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <asm/ide.h>
-
-/*
- * This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
- * There can be up to two drives per interface, as per the ATA-2 spec.
- *
- * Primary i/f:    ide0: major=3;  (hda)         minor=0; (hdb)         minor=64
- * Secondary i/f:  ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
- * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
- * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
- */
-
-/******************************************************************************
- * IDE driver configuration options (play with these as desired):
- *
- * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
- */
-#undef REALLY_FAST_IO			/* define if ide ports are perfect */
-#define INITIAL_MULT_COUNT	0	/* off=0; on=2,4,8,16,32, etc.. */
-
-#ifndef SUPPORT_SLOW_DATA_PORTS		/* 1 to support slow data ports */
-#define SUPPORT_SLOW_DATA_PORTS	1	/* 0 to reduce kernel size */
-#endif
-#ifndef SUPPORT_VLB_SYNC		/* 1 to support weird 32-bit chips */
-#define SUPPORT_VLB_SYNC	1	/* 0 to reduce kernel size */
-#endif
-#ifndef DISK_RECOVERY_TIME		/* off=0; on=access_delay_time */
-#define DISK_RECOVERY_TIME	0	/*  for hardware that needs it */
-#endif
-#ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
-#define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
-#endif
-#ifndef FAKE_FDISK_FOR_EZDRIVE		/* 1 to help linux fdisk with EZDRIVE */
-#define FAKE_FDISK_FOR_EZDRIVE 	1	/* 0 to reduce kernel size */
-#endif
-#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
-#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD640
-#if 0	/* change to 1 when debugging cmd640 problems */
-void cmd640_dump_regs (void);
-#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
-#endif
-#endif  /* CONFIG_BLK_DEV_CMD640 */
-
-/*
- * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
- */
-#define IDE_DRIVE_CMD		99	/* (magic) undef to reduce kernel size*/
-
-/*
- *  "No user-serviceable parts" beyond this point  :)
- *****************************************************************************/
-
-typedef unsigned char	byte;	/* used everywhere */
-
-/*
- * Probably not wise to fiddle with these
- */
-#define ERROR_MAX	8	/* Max read/write errors per sector */
-#define ERROR_RESET	3	/* Reset controller every 4th retry */
-#define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
-
-/*
- * Ensure that various configuration flags have compatible settings
- */
-#ifdef REALLY_SLOW_IO
-#undef REALLY_FAST_IO
-#endif
-
-#define HWIF(drive)		((ide_hwif_t *)((drive)->hwif))
-#define HWGROUP(drive)		((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
-
-/*
- * Definitions for accessing IDE controller registers
- */
-#define IDE_NR_PORTS		(10)
-
-#define IDE_DATA_OFFSET		(0)
-#define IDE_ERROR_OFFSET	(1)
-#define IDE_NSECTOR_OFFSET	(2)
-#define IDE_SECTOR_OFFSET	(3)
-#define IDE_LCYL_OFFSET		(4)
-#define IDE_HCYL_OFFSET		(5)
-#define IDE_SELECT_OFFSET	(6)
-#define IDE_STATUS_OFFSET	(7)
-#define IDE_CONTROL_OFFSET	(8)
-#define IDE_IRQ_OFFSET		(9)
-
-#define IDE_FEATURE_OFFSET	IDE_ERROR_OFFSET
-#define IDE_COMMAND_OFFSET	IDE_STATUS_OFFSET
-
-#define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
-#define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
-#define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
-#define IDE_SECTOR_REG		(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
-#define IDE_LCYL_REG		(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
-#define IDE_HCYL_REG		(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
-#define IDE_SELECT_REG		(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
-#define IDE_STATUS_REG		(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
-#define IDE_CONTROL_REG		(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
-#define IDE_IRQ_REG		(HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
-
-#define IDE_FEATURE_REG		IDE_ERROR_REG
-#define IDE_COMMAND_REG		IDE_STATUS_REG
-#define IDE_ALTSTATUS_REG	IDE_CONTROL_REG
-#define IDE_IREASON_REG		IDE_NSECTOR_REG
-#define IDE_BCOUNTL_REG		IDE_LCYL_REG
-#define IDE_BCOUNTH_REG		IDE_HCYL_REG
-
-#ifdef REALLY_FAST_IO
-#define OUT_BYTE(b,p)		outb((b),(p))
-#define IN_BYTE(p)		(byte)inb(p)
-#else
-#define OUT_BYTE(b,p)		outb_p((b),(p))
-#define IN_BYTE(p)		(byte)inb_p(p)
-#endif /* REALLY_FAST_IO */
-
-#define GET_ERR()		IN_BYTE(IDE_ERROR_REG)
-#define GET_STAT()		IN_BYTE(IDE_STATUS_REG)
-#define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
-#define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
-#define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
-#define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
-#define DRIVE_READY		(READY_STAT  | SEEK_STAT)
-#define DATA_READY		(DRQ_STAT)
-
-/*
- * Some more useful definitions
- */
-#define IDE_MAJOR_NAME	"ide"	/* the same for all i/f; see also genhd.c */
-#define MAJOR_NAME	IDE_MAJOR_NAME
-#define PARTN_BITS	6	/* number of minor dev bits for partitions */
-#define PARTN_MASK	((1<<PARTN_BITS)-1)	/* a useful bit mask */
-#define MAX_DRIVES	2	/* per interface; 2 assumed by lots of code */
-#define SECTOR_WORDS	(512 / 4)	/* number of 32bit words per sector */
-#define IDE_LARGE_SEEK(b1,b2,t)	(((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
-#define IDE_MIN(a,b)	((a)<(b) ? (a):(b))
-#define IDE_MAX(a,b)	((a)>(b) ? (a):(b))
-
-/*
- * Timeouts for various operations:
- */
-#define WAIT_DRQ	(5*HZ/100)	/* 50msec - spec allows up to 20ms */
-#ifdef CONFIG_APM
-#define WAIT_READY	(5*HZ)		/* 5sec - some laptops are very slow */
-#else
-#define WAIT_READY	(3*HZ/100)	/* 30msec - should be instantaneous */
-#endif /* CONFIG_APM */
-#define WAIT_PIDENTIFY	(10*HZ)	/* 10sec  - should be less than 3ms (?)
-				            if all ATAPI CD is closed at boot */
-#define WAIT_WORSTCASE	(30*HZ)	/* 30sec  - worst case when spinning up */
-#define WAIT_CMD	(10*HZ)	/* 10sec  - maximum wait for an IRQ to happen */
-#define WAIT_MIN_SLEEP	(2*HZ/100)	/* 20msec - minimum sleep time */
-
-#define SELECT_DRIVE(hwif,drive)				\
-{								\
-	if (hwif->selectproc)					\
-		hwif->selectproc(drive);			\
-	OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \
-}
-
-/*
- * Now for the data we need to maintain per-drive:  ide_drive_t
- */
-
-#define ide_scsi	0x21
-#define ide_disk	0x20
-#define ide_optical	0x7
-#define ide_cdrom	0x5
-#define ide_tape	0x1
-#define ide_floppy	0x0
-
-typedef union {
-	unsigned all			: 8;	/* all of the bits together */
-	struct {
-		unsigned set_geometry	: 1;	/* respecify drive geometry */
-		unsigned recalibrate	: 1;	/* seek to cyl 0      */
-		unsigned set_multmode	: 1;	/* set multmode count */
-		unsigned set_tune	: 1;	/* tune interface for drive */
-		unsigned reserved	: 4;	/* unused */
-		} b;
-	} special_t;
-
-typedef struct ide_drive_s {
-	struct request		*queue;	/* request queue */
-	struct ide_drive_s 	*next;	/* circular list of hwgroup drives */
-	unsigned long sleep;		/* sleep until this time */
-	unsigned long service_start;	/* time we started last request */
-	unsigned long service_time;	/* service time of last request */
-	special_t	special;	/* special action flags */
-	byte     keep_settings;		/* restore settings after drive reset */
-	byte     using_dma;		/* disk is using dma for read/write */
-	byte     waiting_for_dma;	/* dma currently in progress */
-	byte     unmask;		/* flag: okay to unmask other irqs */
-	byte     slow;			/* flag: slow data port */
-	byte     bswap;			/* flag: byte swap data */
-	byte     dsc_overlap;		/* flag: DSC overlap */
-	byte     nice1;			/* flag: give potential excess bandwidth */
-	unsigned present	: 1;	/* drive is physically present */
-	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
-	unsigned busy		: 1;	/* currently doing revalidate_disk() */
-	unsigned removable	: 1;	/* 1 if need to do check_media_change */
-	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
-	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
-	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
-	unsigned nobios		: 1;	/* flag: do not probe bios for drive */
-	unsigned revalidate	: 1;	/* request revalidation */
-	unsigned atapi_overlap	: 1;	/* flag: ATAPI overlap (not supported) */
-	unsigned nice0		: 1;	/* flag: give obvious excess bandwidth */
-	unsigned nice2		: 1;	/* flag: give a share in our own bandwidth */
-	unsigned doorlocking	: 1;	/* flag: for removable only: door lock/unlock works */
-	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
-#if FAKE_FDISK_FOR_EZDRIVE
-	unsigned remap_0_to_1	: 1;	/* flag: partitioned with ezdrive */
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
-	byte		media;		/* disk, cdrom, tape, floppy, ... */
-	select_t	select;		/* basic drive/head select reg value */
-	byte		ctl;		/* "normal" value for IDE_CONTROL_REG */
-	byte		ready_stat;	/* min status value for drive ready */
-	byte		mult_count;	/* current multiple sector setting */
-	byte 		mult_req;	/* requested multiple sector setting */
-	byte 		tune_req;	/* requested drive tuning setting */
-	byte		io_32bit;	/* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
-	byte		bad_wstat;	/* used for ignoring WRERR_STAT */
-	byte		nowerr;		/* used for ignoring WRERR_STAT */
-	byte		sect0;		/* offset of first sector for DM6:DDO */
-	byte 		usage;		/* current "open()" count for drive */
-	byte 		head;		/* "real" number of heads */
-	byte		sect;		/* "real" sectors per track */
-	byte		bios_head;	/* BIOS/fdisk/LILO number of heads */
-	byte		bios_sect;	/* BIOS/fdisk/LILO sectors per track */
-	unsigned short	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
-	unsigned short	cyl;		/* "real" number of cyls */
-	unsigned int	drive_data;	/* for use by tuneproc/selectproc as needed */
-	void		  *hwif;	/* actually (ide_hwif_t *) */
-	struct wait_queue *wqueue;	/* used to wait for drive in open() */
-	struct hd_driveid *id;		/* drive model identification info */
-	struct hd_struct  *part;	/* drive partition table */
-	char		name[4];	/* drive name, such as "hda" */
-	void 		*driver;	/* (ide_driver_t *) */
-	void		*driver_data;	/* extra driver data */
-	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
-	void		*settings;	/* /proc/ide/ drive settings */
-	char		driver_req[10];	/* requests specific driver */
-	} ide_drive_t;
-
-/*
- * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA.  All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case the caller
- * should either try again later, or revert to PIO for the current request.
- */
-typedef enum {	ide_dma_read,	ide_dma_write,	ide_dma_begin,	ide_dma_end,
-		ide_dma_check,	ide_dma_on,	ide_dma_off,	ide_dma_off_quietly,
-		ide_dma_test_irq
-	} ide_dma_action_t;
-
-typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
-
-
-/*
- * An ide_tuneproc_t() is used to set the speed of an IDE interface
- * to a particular PIO mode.  The "byte" parameter is used
- * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255
- * indicates that the interface driver should "auto-tune" the PIO mode
- * according to the drive capabilities in drive->id;
- *
- * Not all interface types support tuning, and not all of those
- * support all possible PIO settings.  They may silently ignore
- * or round values as they see fit.
- */
-typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
-
-/*
- * This is used to provide support for strange interfaces
- */
-typedef void (ide_selectproc_t) (ide_drive_t *);
-
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum {	ide_unknown,	ide_generic,	ide_pci,
-		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
-		ide_qd6580,	ide_umc8672,	ide_ht6560b,
-		ide_pdc4030,	ide_rz1000,	ide_trm290,
-		ide_cmd646,	ide_4drives
-	} hwif_chipset_t;
-
-typedef struct ide_pci_devid_s {
-	unsigned short	vid;
-	unsigned short	did;
-} ide_pci_devid_t;
-
-#define IDE_PCI_DEVID_NULL	((ide_pci_devid_t){0,0})
-#define IDE_PCI_DEVID_EQ(a,b)	(a.vid == b.vid && a.did == b.did)
-
-typedef struct hwif_s {
-	struct hwif_s	*next;		/* for linked-list in ide_hwgroup_t */
-	void		*hwgroup;	/* actually (ide_hwgroup_t *) */
-	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
-	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
-	struct gendisk	*gd;		/* gendisk structure */
-	ide_tuneproc_t	*tuneproc;	/* routine to tune PIO mode for drives */
-	ide_selectproc_t *selectproc;	/* tweaks hardware to select drive */
-	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
-	unsigned long	*dmatable;	/* dma physical region descriptor table */
-	struct hwif_s	*mate;		/* other hwif from same PCI chip */
-	unsigned long	dma_base;	/* base addr for dma ports */
-	unsigned	dma_extra;	/* extra addr for dma ports */
-	unsigned long	config_data;	/* for use by chipset-specific code */
-	unsigned long	select_data;	/* for use by chipset-specific code */
-	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
-	int		irq;		/* our irq number */
-	byte		major;		/* our major number */
-	char 		name[6];	/* name of interface, eg. "ide0" */
-	byte		index;		/* 0 for ide0; 1 for ide1; ... */
-	hwif_chipset_t	chipset;	/* sub-module for tuning.. */
-	unsigned	noprobe    : 1;	/* don't probe for this interface */
-	unsigned	present    : 1;	/* this interface exists */
-	unsigned	serialized : 1;	/* serialized operation with mate hwif */
-	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
-	unsigned	reset      : 1;	/* reset after probe */
-	unsigned	autodma    : 1;	/* automatically try to enable DMA at boot */
-	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
-	struct pci_dev	*pci_dev;	/* for pci chipsets */
-	ide_pci_devid_t	pci_devid;	/* for pci chipsets: {VID,DID} */
-#if (DISK_RECOVERY_TIME > 0)
-	unsigned long	last_time;	/* time when previous rq was done */
-#endif
-	} ide_hwif_t;
-
-/*
- *  internal ide interrupt handler type
- */
-typedef void (ide_handler_t)(ide_drive_t *);
-
-typedef struct hwgroup_s {
-	spinlock_t		spinlock; /* protects "busy" and "handler" */
-	ide_handler_t		*handler;/* irq handler, if active */
-	int			busy;	/* BOOL: protects all fields below */
-	ide_drive_t		*drive;	/* current drive */
-	ide_hwif_t		*hwif;	/* ptr to current hwif in linked-list */
-	struct request		*rq;	/* current request */
-	struct timer_list	timer;	/* failsafe timer */
-	struct request		wrq;	/* local copy of current write rq */
-	unsigned long		poll_timeout;	/* timeout value during long polls */
-	} ide_hwgroup_t;
-
-/*
- * configurable drive settings
- */
-
-#define TYPE_INT	0
-#define TYPE_INTA	1
-#define TYPE_BYTE	2
-#define TYPE_SHORT	3
-
-#define SETTING_READ	(1 << 0)
-#define SETTING_WRITE	(1 << 1)
-#define SETTING_RW	(SETTING_READ | SETTING_WRITE)
-
-typedef int (ide_procset_t)(ide_drive_t *, int);
-typedef struct ide_settings_s {
-	char			*name;
-	int			rw;
-	int			read_ioctl;
-	int			write_ioctl;
-	int			data_type;
-	int			min;
-	int			max;
-	int			mul_factor;
-	int			div_factor;
-	void			*data;
-	ide_procset_t		*set;
-	int			auto_remove;
-	struct ide_settings_s	*next;
-} ide_settings_t;
-
-void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
-void ide_remove_setting(ide_drive_t *drive, char *name);
-ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
-int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
-int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
-void ide_add_generic_settings(ide_drive_t *drive);
-
-/*
- * /proc/ide interface
- */
-typedef struct {
-	const char	*name;
-	mode_t		mode;
-	read_proc_t	*read_proc;
-	write_proc_t	*write_proc;
-} ide_proc_entry_t;
-
-#ifdef CONFIG_PROC_FS
-void proc_ide_create(void);
-void proc_ide_destroy(void);
-void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
-void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
-read_proc_t proc_ide_read_capacity;
-read_proc_t proc_ide_read_geometry;
-
-/*
- * Standard exit stuff:
- */
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) \
-{					\
-	len -= off;			\
-	if (len < count) {		\
-		*eof = 1;		\
-		if (len <= 0)		\
-			return 0;	\
-	} else				\
-		len = count;		\
-	*start = page + off;		\
-	return len;			\
-}
-#else
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
-#endif
-
-/*
- * Subdrivers support.
- */
-#define IDE_SUBDRIVER_VERSION	1
-
-typedef int	(ide_cleanup_proc)(ide_drive_t *);
-typedef void 	(ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
-typedef void	(ide_end_request_proc)(byte, ide_hwgroup_t *);
-typedef int 	(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
-typedef int	(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef void 	(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef int	(ide_check_media_change_proc)(ide_drive_t *);
-typedef void	(ide_pre_reset_proc)(ide_drive_t *);
-typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
-typedef void	(ide_special_proc)(ide_drive_t *);
-typedef void	(ide_setting_proc)(ide_drive_t *);
-
-typedef struct ide_driver_s {
-	const char			*name;
-	const char			*version;
-	byte				media;
-	unsigned busy			: 1;
-	unsigned supports_dma		: 1;
-	unsigned supports_dsc_overlap	: 1;
-	ide_cleanup_proc		*cleanup;
-	ide_do_request_proc		*do_request;
-	ide_end_request_proc		*end_request;
-	ide_ioctl_proc			*ioctl;
-	ide_open_proc			*open;
-	ide_release_proc		*release;
-	ide_check_media_change_proc	*media_change;
-	ide_pre_reset_proc		*pre_reset;
-	ide_capacity_proc		*capacity;
-	ide_special_proc		*special;
-	ide_proc_entry_t		*proc;
-	} ide_driver_t;
-
-#define DRIVER(drive)		((ide_driver_t *)((drive)->driver))
-
-/*
- * IDE modules.
- */
-#define IDE_CHIPSET_MODULE		0	/* not supported yet */
-#define IDE_PROBE_MODULE		1
-#define IDE_DRIVER_MODULE		2
-
-typedef int	(ide_module_init_proc)(void);
-
-typedef struct ide_module_s {
-	int				type;
-	ide_module_init_proc		*init;
-	void				*info;
-	struct ide_module_s		*next;
-} ide_module_t;
-
-/*
- * ide_hwifs[] is the master data structure used to keep track
- * of just about everything in ide.c.  Whenever possible, routines
- * should be using pointers to a drive (ide_drive_t *) or
- * pointers to a hwif (ide_hwif_t *), rather than indexing this
- * structure directly (the allocation/layout may change!).
- *
- */
-#ifndef _IDE_C
-extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
-extern  ide_module_t	*ide_modules;
-#endif
-
-/*
- * We need blk.h, but we replace its end_request by our own version.
- */
-#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
-#define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
-#include <linux/blk.h>
-
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
-
-/*
- * This is used for (nearly) all data transfers from/to the IDE interface
- */
-void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-
-/*
- * This is used for (nearly) all ATAPI data transfers from/to the IDE interface
- */
-void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
-void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
-
-/*
- * This is used on exit from the driver, to designate the next irq handler
- * and also to start the safety timer.
- */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
-
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * ide_error() takes action based on the error returned by the controller.
- * The calling function must return afterwards, to restart the request.
- */
-void ide_error (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * Issue a simple drive command
- * The drive must be selected beforehand.
- */
-void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
-
-/*
- * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
- * removing leading/trailing blanks and compressing internal blanks.
- * It is primarily used to tidy up the model name/number fields as
- * returned by the WIN_[P]IDENTIFY commands.
- */
-void ide_fixstring (byte *s, const int bytecount, const int byteswap);
-
-/*
- * This routine busy-waits for the drive status to be not "busy".
- * It then checks the status for all of the "good" bits and none
- * of the "bad" bits, and if all is okay it returns 0.  All other
- * cases return 1 after invoking ide_error() -- caller should return.
- *
- */
-int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
-
-/*
- * This routine is called from the partition-table code in genhd.c
- * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
- *
- * The second parameter, "xparm", determines exactly how the translation
- * will be handled:
- *		 0 = convert to CHS with fewer than 1024 cyls
- *			using the same method as Ontrack DiskManager.
- *		 1 = same as "0", plus offset everything by 63 sectors.
- *		-1 = similar to "0", plus redirect sector 0 to sector 1.
- *		>1 = convert to a CHS geometry with "xparm" heads.
- *
- * Returns 0 if the translation was not possible, if the device was not
- * an IDE disk drive, or if a geometry was "forced" on the commandline.
- * Returns 1 if the geometry translation was successful.
- */
-int ide_xlate_1024 (kdev_t, int, const char *);
-
-/*
- * Start a reset operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
-void ide_do_reset (ide_drive_t *);
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_cmd (struct request *rq);
-
-/*
- * "action" parameter type for ide_do_drive_cmd() below.
- */
-typedef enum
-	{ide_wait,	/* insert rq at end of list, and wait for it */
-	 ide_next,	/* insert rq immediately after current request */
-	 ide_preempt,	/* insert rq in front of current request */
-	 ide_end}	/* insert rq at end of list, but don't wait for it */
- ide_action_t;
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed.  This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed.  As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
-
-/*
- * Clean up after success/failure of an explicit drive cmd.
- * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
- */
-void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
-
-/*
- * Issue ATA command and wait for completion.
- */
-int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
-
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz).  This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- */
-int ide_system_bus_speed (void);
-
-/*
- * ide_multwrite() transfers a block of up to mcount sectors of data
- * to a drive as part of a disk multwrite operation.
- */
-void ide_multwrite (ide_drive_t *drive, unsigned int mcount);
-
-/*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
- */
-void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
-
-/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-struct request **ide_get_queue (kdev_t dev);
-
-/*
- * CompactFlash cards and their brethern pretend to be removable hard disks,
- * but they never have a slave unit, and they don't have doorlock mechanisms.
- * This test catches them, and is invoked elsewhere when setting appropriate config bits.
- */
-int drive_is_flashcard (ide_drive_t *drive);
-
-int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
-void ide_timer_expiry (unsigned long data);
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
-void ide_geninit (struct gendisk *gd);
-void do_ide0_request (void);
-#if MAX_HWIFS > 1
-void do_ide1_request (void);
-#endif
-#if MAX_HWIFS > 2
-void do_ide2_request (void);
-#endif
-#if MAX_HWIFS > 3
-void do_ide3_request (void);
-#endif
-#if MAX_HWIFS > 4
-void do_ide4_request (void);
-#endif
-#if MAX_HWIFS > 5
-void do_ide5_request (void);
-#endif
-void ide_init_subdrivers (void);
-
-#ifndef _IDE_C
-extern struct file_operations ide_fops[];
-#endif
-
-#ifdef _IDE_C
-#ifdef CONFIG_BLK_DEV_IDE
-int ideprobe_init (void);
-#endif /* CONFIG_BLK_DEV_IDE */
-#ifdef CONFIG_BLK_DEV_IDEDISK
-int idedisk_init (void);
-#endif /* CONFIG_BLK_DEV_IDEDISK */
-#ifdef CONFIG_BLK_DEV_IDECD
-int ide_cdrom_init (void);
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
-int idetape_init (void);
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-#ifdef CONFIG_BLK_DEV_IDEFLOPPY
-int idefloppy_init (void);
-#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
-#ifdef CONFIG_BLK_DEV_IDESCSI
-int idescsi_init (void);
-#endif /* CONFIG_BLK_DEV_IDESCSI */
-#endif /* _IDE_C */
-
-int ide_register_module (ide_module_t *module);
-void ide_unregister_module (ide_module_t *module);
-ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
-int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
-int ide_unregister_subdriver (ide_drive_t *drive);
-int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-#define ON_BOARD		1
-#define NEVER_BOARD		0
-#ifdef CONFIG_BLK_DEV_OFFBOARD
-#  define OFF_BOARD		ON_BOARD
-#else /* CONFIG_BLK_DEV_OFFBOARD */
-#  define OFF_BOARD		NEVER_BOARD
-#endif /* CONFIG_BLK_DEV_OFFBOARD */
-
-unsigned long ide_find_free_region (unsigned short size) __init;
-void ide_scan_pcibus (void) __init;
-#endif
-#ifdef CONFIG_BLK_DEV_IDEDMA
-#define BAD_DMA_DRIVE		0
-#define GOOD_DMA_DRIVE		1
-int ide_build_dmatable (ide_drive_t *drive);
-void ide_dma_intr  (ide_drive_t *drive);
-int check_drive_lists (ide_drive_t *drive, int good_bad);
-int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
-int ide_release_dma (ide_hwif_t *hwif);
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
-#endif
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-#include "pdc4030.h"
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
-#else
-#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
-#endif /* _IDE_H */
diff -urN linux-2.2.10-pristine/drivers/block/ide_modes.h linux/drivers/block/ide_modes.h
--- linux-2.2.10-pristine/drivers/block/ide_modes.h	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ide_modes.h	Thu Jul 22 20:38:43 1999
@@ -15,7 +15,7 @@
  * breaking the fragile cmd640.c support.
  */
 
-#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) || defined(CONFIG_BLK_DEV_IDE_PMAC)
+#ifdef CONFIG_BLK_DEV_IDE_MODES
 
 /*
  * Standard (generic) timings for PIO modes, from ATA2 specification.
@@ -111,6 +111,8 @@
 	{ "ST3600A",  1 },
 	{ "ST3290A",  0 },
 	{ "ST3144A",  0 },
+	{ "ST3491A",  1 },	/* reports 3, should be 1 or 2 (depending on */	
+				/* drive) according to Seagates FIND-ATA program */
 
 	{ "QUANTUM ELS127A", 0 },
 	{ "QUANTUM ELS170A", 0 },
@@ -222,5 +224,5 @@
 }
 
 #endif /* _IDE_C */
-#endif /* defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) */
+#endif /* CONFIG_BLK_DEV_IDE_MODES */
 #endif /* _IDE_MODES_H */
diff -urN linux-2.2.10-pristine/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.2.10-pristine/drivers/block/ll_rw_blk.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ll_rw_blk.c	Fri Jul 23 01:08:48 1999
@@ -471,6 +471,8 @@
 	     case IDE3_MAJOR:
 	     case IDE4_MAJOR:
 	     case IDE5_MAJOR:
+	     case IDE6_MAJOR:
+	     case IDE7_MAJOR:
 	     case ACSI_MAJOR:
 	     case MFM_ACORN_MAJOR:
 		/*
diff -urN linux-2.2.10-pristine/drivers/block/macide.c linux/drivers/block/macide.c
--- linux-2.2.10-pristine/drivers/block/macide.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/macide.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,167 @@
+/*
+ *  linux/drivers/block/macide.c -- Macintosh IDE Driver
+ *
+ *     Copyright (C) 1998 by Michael Schmitz
+ *
+ *  This driver was written based on information obtained from the MacOS IDE
+ *  driver binary by Mikael Forselius
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/zorro.h>
+#include <linux/ide.h>
+
+#include <asm/machw.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+
+    /*
+     *  Base of the IDE interface (see ATAManager ROM code)
+     */
+
+#define MAC_HD_BASE	0x50f1a000
+
+    /*
+     *  Offsets from the above base (scaling 4)
+     */
+
+#define MAC_HD_DATA	0x00
+#define MAC_HD_ERROR	0x04		/* see err-bits */
+#define MAC_HD_NSECTOR	0x08		/* nr of sectors to read/write */
+#define MAC_HD_SECTOR	0x0c		/* starting sector */
+#define MAC_HD_LCYL	0x10		/* starting cylinder */
+#define MAC_HD_HCYL	0x14		/* high byte of starting cyl */
+#define MAC_HD_SELECT	0x18		/* 101dhhhh , d=drive, hhhh=head */
+#define MAC_HD_STATUS	0x1c		/* see status-bits */
+#define MAC_HD_CONTROL	0x38		/* control/altstatus */
+
+static int macide_offsets[IDE_NR_PORTS] = {
+    MAC_HD_DATA, MAC_HD_ERROR, MAC_HD_NSECTOR, MAC_HD_SECTOR, MAC_HD_LCYL,
+    MAC_HD_HCYL, MAC_HD_SELECT, MAC_HD_STATUS, MAC_HD_CONTROL
+};
+
+	/*
+	 * Other registers
+	 */
+
+	/* 
+	 * IDE interrupt status register for both (?) hwifs on Quadra
+	 * Initial setting: 0xc
+	 * Guessing again:
+	 * Bit 0+1: some interrupt flags
+	 * Bit 2+3: some interrupt enable
+	 * Bit 4:   ??
+	 * Bit 5:   IDE interrupt flag (any hwif)
+	 * Bit 6:   maybe IDE interrupt enable (any hwif) ??
+	 * Bit 7:   Any interrupt condition
+	 *
+	 * Only relevant item: bit 5, to be checked by mac_ack_intr
+	 */
+
+#define MAC_HD_ISR	0x101
+
+	/*
+	 * IDE interrupt glue - seems to be wired to Nubus, Slot C?
+	 * (ROM code disassembly again)
+	 * First try: just use Nubus interrupt for Slot C. Have Nubus code call
+	 * a wrapper to ide_intr that checks the ISR (see above).
+	 * Need to #define IDE_IRQ_NUBUS though.
+	 * Alternative method: set a mac_ide_hook function pointer to the wrapper 
+	 * here and have via_do_nubus call that hook if set. 
+	 *
+	 * Quadra needs the hook, Powerbook can use Nubus slot C. 
+	 * Checking the ISR on Quadra is done by mac_ack_intr (see Amiga code). mac_ide_intr
+	 * mac_ide_intr is obsolete except for providing the hwgroup argument.
+	 */
+
+	/* The Mac hwif data, for passing hwgroup to ide_intr */
+static ide_hwif_t *mac_hwif = NULL;
+
+	/* The function pointer used in the Nubus handler */
+void (*mac_ide_intr_hook)(int, void *, struct pt_regs *) = NULL;
+
+	/*
+	 * Only purpose: feeds the hwgroup to the main IDE handler. 
+	 * Obsolete as soon as Nubus code is fixed WRT pseudo slot C int.
+	 * (should be the case on Powerbooks)
+	 * Alas, second purpose: feed correct irq to IDE handler (I know,
+	 * that's cheating) :-(((
+	 * Fix needed for interrupt code: accept Nubus ints in the regular
+	 * request_irq code, then register Powerbook IDE as Nubus slot C, 
+	 * Quadra as slot F (F for fictious).
+	 */
+void mac_ide_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ide_intr(mac_hwif->irq, mac_hwif->hwgroup, regs);
+}
+
+    /*
+     *  Check the interrupt status
+     *
+     *  Note: In 2.0 kernels, there have been timing problems with the 
+     *  Powerbook IDE interface (BUSY was asserted too long after the
+     *  interrupt triggered). Result: repeated errors, recalibrate etc. 
+     *  Adding a wait loop to read_intr, write_intr and set_geom_intr
+     *  fixed the problem (waits in read/write_intr were present for Amiga
+     *  already). 
+     *  Powerbooks were not tested with 2.1 due to lack of FPU emulation
+     *  (thanks Apple for using LC040). If the BUSY problem resurfaces in 
+     *  2.1, my best bet would be to add the wait loop right here, afterr
+     *  checking the interrupt register.
+     */
+
+static int mac_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x20))
+	return 0;
+    return 1;
+}
+
+    /*
+     *  Probe for a Macintosh IDE interface
+     */
+
+void macide_init(void)
+{
+    hw_regs_t hw;
+    int index = -1;
+
+    if (MACH_IS_MAC) {
+	switch(macintosh_config->ide_type) {
+	case 0:
+	    break;
+
+	case MAC_IDE_QUADRA:
+	    ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
+	    		    0, (ide_ioreg_t)(MAC_HD_BASE+MAC_HD_ISR),
+			    mac_ack_intr, IRQ_MAC_NUBUS);
+	    index = ide_register_hw(&hw, &mac_hwif);
+	    mac_ide_intr_hook = mac_ide_intr;
+	    break;
+
+	default:
+	    ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
+	    		    0, 0, NULL, IRQ_MAC_NUBUS);
+	    index = ide_register_hw(&hw, &mac_hwif);
+	    break;
+	}
+
+        if (index != -1) {
+	    if (macintosh_config->ide_type == MAC_IDE_QUADRA)
+		printk("ide%d: Macintosh Quadra IDE interface\n", index);
+	    else
+		printk("ide%d: Macintosh Powerbook IDE interface\n", index);
+	}
+    }
+}
diff -urN linux-2.2.10-pristine/drivers/block/ns87415.c linux/drivers/block/ns87415.c
--- linux-2.2.10-pristine/drivers/block/ns87415.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/ns87415.c	Thu Jul 22 20:38:43 1999
@@ -17,9 +17,9 @@
 #include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <asm/io.h>
-#include "ide.h"
+#include <linux/ide.h>
 
+#include <asm/io.h>
 
 static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
 
@@ -166,13 +166,15 @@
 #endif
 	}
 
-	outb(0x60, hwif->dma_base + 2);
+	if (hwif->dma_base)
+		outb(0x60, hwif->dma_base + 2);
 
 	if (!using_inta)
 		hwif->irq = hwif->channel ? 15 : 14;	/* legacy mode */
 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
 		hwif->irq = hwif->mate->irq;	/* share IRQ with mate */
 
-	hwif->dmaproc = &ns87415_dmaproc;
+	if (hwif->dma_base)
+		hwif->dmaproc = &ns87415_dmaproc;
 	hwif->selectproc = &ns87415_selectproc;
 }
diff -urN linux-2.2.10-pristine/drivers/block/opti621.c linux/drivers/block/opti621.c
--- linux-2.2.10-pristine/drivers/block/opti621.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/opti621.c	Thu Jul 22 20:38:43 1999
@@ -98,8 +98,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 #define OPTI621_MAX_PIO 3
diff -urN linux-2.2.10-pristine/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c
--- linux-2.2.10-pristine/drivers/block/pdc202xx.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/pdc202xx.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,555 @@
+/*
+ *  linux/drivers/block/pdc202xx.c	Version 0.26	May 12, 1999
+ *
+ *  Copyright (C) 1998-99	Andre Hedrick
+ *					(hedrick@astro.dyer.vanderbilt.edu)
+ *
+ *  Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
+ *  compiled into the kernel if you have more than one card installed.
+ *  Note that BIOS v1.29 is reported to fix the problem.  Since this is
+ *  safe chipset tuning, including this support is harmless
+ *
+ *  The latest chipset code will support the following ::
+ *  Three Ultra33 controllers and 12 drives.
+ *  8 are UDMA supported and 4 are limited to DMA mode 2 multi-word.
+ *  The 8/4 ratio is a BIOS code limit by promise.
+ *
+ *  UNLESS you enable "PDC202XX_FORCE_BURST_BIT"
+ *
+ *  There is only one BIOS in the three contollers.
+ *
+ *  May  8 20:56:17 Orion kernel:
+ *  Uniform Multi-Platform E-IDE driver Revision: 6.19
+ *  PDC20246: IDE controller on PCI bus 00 dev a0
+ *  PDC20246: not 100% native mode: will probe irqs later
+ *  PDC20246: ROM enabled at 0xfebd0000
+ *  PDC20246: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode.
+ *      ide0: BM-DMA at 0xef80-0xef87, BIOS settings: hda:DMA, hdb:DMA
+ *      ide1: BM-DMA at 0xef88-0xef8f, BIOS settings: hdc:pio, hdd:pio
+ *  PDC20246: IDE controller on PCI bus 00 dev 98
+ *  PDC20246: not 100% native mode: will probe irqs later
+ *  PDC20246: ROM enabled at 0xfebc0000
+ *  PDC20246: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode.
+ *      ide2: BM-DMA at 0xef40-0xef47, BIOS settings: hde:DMA, hdf:DMA
+ *      ide3: BM-DMA at 0xef48-0xef4f, BIOS settings: hdg:DMA, hdh:DMA
+ *  PDC20246: IDE controller on PCI bus 00 dev 90
+ *  PDC20246: not 100% native mode: will probe irqs later
+ *  PDC20246: ROM enabled at 0xfebb0000
+ *  PDC20246: (U)DMA Burst Bit DISABLED Primary PCI Mode Secondary PCI Mode.
+ *  PDC20246: FORCING BURST BIT 0x00 -> 0x01 ACTIVE
+ *      ide4: BM-DMA at 0xef00-0xef07, BIOS settings: hdi:DMA, hdj:pio
+ *      ide5: BM-DMA at 0xef08-0xef0f, BIOS settings: hdk:pio, hdl:pio
+ *  PIIX3: IDE controller on PCI bus 00 dev 39
+ *  PIIX3: device not capable of full native PCI mode
+ *
+ *  ide0 at 0xeff0-0xeff7,0xefe6 on irq 19
+ *  ide1 at 0xefa8-0xefaf,0xebe6 on irq 19
+ *  ide2 at 0xefa0-0xefa7,0xef7e on irq 18
+ *  ide3 at 0xef68-0xef6f,0xef66 on irq 18
+ *  ide4 at 0xef38-0xef3f,0xef62 on irq 17
+ *  hda: QUANTUM FIREBALL ST6.4A, 6149MB w/81kB Cache, CHS=13328/15/63, UDMA(33)
+ *  hdb: QUANTUM FIREBALL ST3.2A, 3079MB w/81kB Cache, CHS=6256/16/63, UDMA(33)
+ *  hde: Maxtor 72004 AP, 1916MB w/128kB Cache, CHS=3893/16/63, DMA
+ *  hdf: Maxtor 71626 A, 1554MB w/64kB Cache, CHS=3158/16/63, DMA
+ *  hdi: Maxtor 90680D4, 6485MB w/256kB Cache, CHS=13176/16/63, UDMA(33)
+ *  hdj: Maxtor 90680D4, 6485MB w/256kB Cache, CHS=13176/16/63, UDMA(33)
+ *
+ *  Promise Ultra66 cards with BIOS v1.11 this
+ *  compiled into the kernel if you have more than one card installed.
+ *
+ *  PDC20262: IDE controller on PCI bus 00 dev a0
+ *  PDC20262: not 100% native mode: will probe irqs later
+ *  PDC20262: ROM enabled at 0xfebb0000
+ *  PDC20262: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode.
+ *      ide0: BM-DMA at 0xef00-0xef07, BIOS settings: hda:pio, hdb:pio
+ *      ide1: BM-DMA at 0xef08-0xef0f, BIOS settings: hdc:pio, hdd:pio
+ *
+ *  UDMA 4/2 and UDMA 3/1 only differ by the testing bit 13 in word93.
+ *  Chipset timing speeds must be identical
+ *
+ *  drive_number
+ *      = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *      = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define PDC202XX_DEBUG_DRIVE_INFO		0
+#define PDC202XX_DECODE_REGISTER_INFO		0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/* A Register */
+#define	SYNC_ERRDY_EN	0xC0
+
+#define	SYNC_IN		0x80	/* control bit, different for master vs. slave drives */
+#define	ERRDY_EN	0x40	/* control bit, different for master vs. slave drives */
+#define	IORDY_EN	0x20	/* PIO: IOREADY */
+#define	PREFETCH_EN	0x10	/* PIO: PREFETCH */
+
+#define	PA3		0x08	/* PIO"A" timing */
+#define	PA2		0x04	/* PIO"A" timing */
+#define	PA1		0x02	/* PIO"A" timing */
+#define	PA0		0x01	/* PIO"A" timing */
+
+/* B Register */
+
+#define	MB2		0x80	/* DMA"B" timing */
+#define	MB1		0x40	/* DMA"B" timing */
+#define	MB0		0x20	/* DMA"B" timing */
+
+#define	PB4		0x10	/* PIO_FORCE 1:0 */
+
+#define	PB3		0x08	/* PIO"B" timing */	/* PIO flow Control mode */
+#define	PB2		0x04	/* PIO"B" timing */	/* PIO 4 */
+#define	PB1		0x02	/* PIO"B" timing */	/* PIO 3 half */
+#define	PB0		0x01	/* PIO"B" timing */	/* PIO 3 other half */
+
+/* C Register */
+#define	IORDYp_NO_SPEED	0x4F
+#define	SPEED_DIS	0x0F
+
+#define	DMARQp		0x80
+#define	IORDYp		0x40
+#define	DMAR_EN		0x20
+#define	DMAW_EN		0x10
+
+#define	MC3		0x08	/* DMA"C" timing */
+#define	MC2		0x04	/* DMA"C" timing */
+#define	MC1		0x02	/* DMA"C" timing */
+#define	MC0		0x01	/* DMA"C" timing */
+
+#if PDC202XX_DECODE_REGISTER_INFO
+
+#define REG_A		0x01
+#define REG_B		0x02
+#define REG_C		0x04
+#define REG_D		0x08
+
+static void decode_registers (byte registers, byte value)
+{
+	byte	bit = 0, bit1 = 0, bit2 = 0;
+
+	switch(registers) {
+		case REG_A:
+			bit2 = 0;
+			printk("A Register ");
+			if (value & 0x80) printk("SYNC_IN ");
+			if (value & 0x40) printk("ERRDY_EN ");
+			if (value & 0x20) printk("IORDY_EN ");
+			if (value & 0x10) printk("PREFETCH_EN ");
+			if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; }
+			if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; }
+			if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; }
+			if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; }
+			printk("PIO(A) = %d ", bit2);
+			break;
+		case REG_B:
+			bit1 = 0;bit2 = 0;
+			printk("B Register ");
+			if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; }
+			if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; }
+			if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; }
+			printk("DMA(B) = %d ", bit1 >> 5);
+			if (value & 0x10) printk("PIO_FORCED/PB4 ");
+			if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; }
+			if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; }
+			if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; }
+			if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; }
+			printk("PIO(B) = %d ", bit2);
+			break;
+		case REG_C:
+			bit2 = 0;
+			printk("C Register ");
+			if (value & 0x80) printk("DMARQp ");
+			if (value & 0x40) printk("IORDYp ");
+			if (value & 0x20) printk("DMAR_EN ");
+			if (value & 0x10) printk("DMAW_EN ");
+
+			if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; }
+			if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; }
+			if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; }
+			if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; }
+			printk("DMA(C) = %d ", bit2);
+			break;
+		case REG_D:
+			printk("D Register ");
+			break;
+		default:
+			return;
+	}
+	printk("\n        %s ", (registers & REG_D) ? "DP" :
+				(registers & REG_C) ? "CP" :
+				(registers & REG_B) ? "BP" :
+				(registers & REG_A) ? "AP" : "ERROR");
+	for (bit=128;bit>0;bit/=2)
+		printk("%s", (value & bit) ? "1" : "0");
+	printk("\n");
+}
+
+#endif /* PDC202XX_DECODE_REGISTER_INFO */
+
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+
+	int			err;
+	unsigned int		drive_conf;
+	byte			drive_pci;
+	byte			test1, test2, speed;
+	byte			AP, BP, CP, DP, EP;
+	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	byte udma_66		= ((id->word93 & 0x2000) && (dev->device == PCI_DEVICE_ID_PROMISE_20262)) ? 1 : 0;
+	byte udma_33		= ultra ? (inb((dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0;
+
+	pci_read_config_byte(dev, 0x50, &EP);
+
+	switch(drive_number) {
+		case 0:	drive_pci = 0x60;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			pci_read_config_byte(dev, (drive_pci), &test1);
+			if (!(test1 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN);
+			break;
+		case 1:	drive_pci = 0x64;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			pci_read_config_byte(dev, 0x60, &test1);
+			pci_read_config_byte(dev, (drive_pci), &test2);
+			if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN);
+			break;
+		case 2:	drive_pci = 0x68;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			pci_read_config_byte(dev, (drive_pci), &test1);
+			if (!(test1 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN);
+			break;
+		case 3:	drive_pci = 0x6c;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			pci_read_config_byte(dev, 0x68, &test1);
+			pci_read_config_byte(dev, (drive_pci), &test2);
+			if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN);
+			break;
+		default:
+			return ide_dma_off;
+	}
+
+	if (drive->media != ide_disk)
+		return ide_dma_off_quietly;
+
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
+
+	if (id->capability & 4) {		/* IORDY_EN */
+		pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN);
+		pci_read_config_byte(dev, (drive_pci), &AP);
+	}
+
+	if (drive->media == ide_disk) {		/* PREFETCH_EN */
+		pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
+		pci_read_config_byte(dev, (drive_pci), &AP);
+	}
+
+	if ((BP & 0xF0) && (CP & 0x0F)) {
+		/* clear DMA modes of upper 842 bits of B Register */
+		/* clear PIO forced mode upper 1 bit of B Register */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0);
+		pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+
+		/* clear DMA modes of lower 8421 bits of C Register */
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F);
+		pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+	}
+
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+
+	if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 16)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x1010;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 8 == UDMA mode 4 == speed 6 plus cable */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01);
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 8)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0808;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 7 == UDMA mode 3 == speed 5 plus cable */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02);
+		speed = XFER_UDMA_3;
+	} else if ((id->dma_ultra & 0x0004) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 6 == UDMA mode 2 */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01);
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 5 == UDMA mode 1 */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02);
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 4 == UDMA mode 0 */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03);
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 4 == DMA mode 2 multi-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03);
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 3 == DMA mode 1 multi-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x04);
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		if (!((id->dma_mword >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0101;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 2 == DMA mode 0 multi-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05);
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+		}
+		/* speed 2 == DMA mode 2 single-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05);
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		if (!((id->dma_1word >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0202;
+		}
+		/* speed 1 == DMA mode 1 single-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x80);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x06);
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		if (!((id->dma_1word >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0101;
+		}
+		/* speed 0 == DMA mode 0 single-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0xC0);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x0B);
+		speed = XFER_SW_DMA_0;
+	} else {
+		/* restore original pci-config space */
+		pci_write_config_dword(dev, drive_pci, drive_conf);
+		return ide_dma_off_quietly;
+	}
+
+	err = ide_config_drive_speed(drive, speed);
+
+#if PDC202XX_DECODE_REGISTER_INFO
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+
+	decode_registers(REG_A, AP);
+	decode_registers(REG_B, BP);
+	decode_registers(REG_C, CP);
+	decode_registers(REG_D, DP);
+#endif /* PDC202XX_DECODE_REGISTER_INFO */
+
+#if PDC202XX_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d 0x%08x ",
+		drive->name, ide_xfer_verbose(speed),
+		drive_number, drive_conf);
+	pci_read_config_dword(dev, drive_pci, &drive_conf);
+	printk("0x%08x\n", drive_conf);
+#endif /* PDC202XX_DEBUG_DRIVE_INFO */
+
+	return ((int)	((id->dma_ultra >> 11) & 3) ? 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);
+}
+
+/*   0    1    2    3    4    5    6   7   8
+ * 960, 480, 390, 300, 240, 180, 120, 90, 60
+ *           180, 150, 120,  90,  60
+ * DMA_Speed
+ * 180, 120,  90,  90,  90,  60,  30
+ *  11,   5,   4,   3,   2,   1,   0
+ */
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_hwif_t *hwif = HWIF(drive);
+	ide_dma_action_t dma_func = ide_dma_off_quietly;
+
+	if (id && (id->capability & 1) && hwif->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			return HWIF(drive)->dmaproc(ide_dma_off, drive);
+		}
+
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive, 1);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0004) ||
+			    (id->dma_1word & 0x0004)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive, 0);
+			}
+		} else if ((ide_dmaproc(ide_dma_good_drive, drive)) &&
+			   (id->eide_dma_time > 150)) {
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive, 0);
+		}
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int pdc202xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+__initfunc(unsigned int pci_init_pdc202xx (struct pci_dev *dev, const char *name))
+{
+	unsigned long high_16	= dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+	byte udma_speed_flag	= inb(high_16 + 0x001f);
+	byte primary_mode	= inb(high_16 + 0x001a);
+	byte secondary_mode	= inb(high_16 + 0x001b);
+
+	if (dev->rom_address) {
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+		printk("%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
+	}
+
+	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
+		byte irq = 0, irq2 = 0;
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+		pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);	/* 0xbc */
+		if (irq != irq2) {
+			pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq);	/* 0xbc */
+			printk("%s: pci-config space interrupt mirror fixed.\n", name);
+		}
+	}
+
+	printk("%s: (U)DMA Burst Bit %sABLED " \
+		"Primary %s Mode " \
+		"Secondary %s Mode.\n",
+		name,
+		(udma_speed_flag & 1) ? "EN" : "DIS",
+		(primary_mode & 1) ? "MASTER" : "PCI",
+		(secondary_mode & 1) ? "MASTER" : "PCI" );
+
+#ifdef PDC202XX_FORCE_BURST_BIT
+	if (!(udma_speed_flag & 1)) {
+		printk("%s: FORCING BURST BIT 0x%02x -> 0x%02x ", name, udma_speed_flag, (udma_speed_flag|1));
+		outb(udma_speed_flag|1, high_16 + 0x001f);
+		printk("%sCTIVE\n", (inb(high_16 + 0x001f) & 1) ? "A" : "INA");
+	}
+#endif /* PDC202XX_FORCE_BURST_BIT */
+
+#ifdef PDC202XX_FORCE_MASTER_MODE
+	if (!(primary_mode & 1)) {
+		printk("%s: FORCING PRIMARY MODE BIT 0x%02x -> 0x%02x ",
+			name, primary_mode, (primary_mode|1));
+		outb(primary_mode|1, high_16 + 0x001a);
+		printk("%s\n", (inb(high_16 + 0x001a) & 1) ? "MASTER" : "PCI");
+	}
+
+	if (!(secondary_mode & 1)) {
+		printk("%s: FORCING SECONDARY MODE BIT 0x%02x -> 0x%02x ",
+			name, secondary_mode, (secondary_mode|1));
+		outb(secondary_mode|1, high_16 + 0x001b);
+		printk("%s\n", (inb(high_16 + 0x001b) & 1) ? "MASTER" : "PCI");
+	}
+#endif /* PDC202XX_FORCE_MASTER_MODE */
+	return dev->irq;
+}
+
+__initfunc(void ide_init_pdc202xx (ide_hwif_t *hwif))
+{
+	if (hwif->dma_base) {
+		hwif->dmaproc = &pdc202xx_dmaproc;
+	}
+}
diff -urN linux-2.2.10-pristine/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c
--- linux-2.2.10-pristine/drivers/block/pdc4030.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/pdc4030.c	Thu Jul 22 20:38:43 1999
@@ -1,17 +1,18 @@
 /*  -*- linux-c -*-
- *  linux/drivers/block/pdc4030.c	Version 0.08  Nov 30, 1997
+ *  linux/drivers/block/pdc4030.c	Version 0.90  May 27, 1999
  *
- *  Copyright (C) 1995-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 1995-1999  Linus Torvalds & authors (see below)
  */
 
 /*
  *  Principal Author/Maintainer:  peterd@pnd-pc.demon.co.uk
  *
  *  This file provides support for the second port and cache of Promise
- *  IDE interfaces, e.g. DC4030, DC5030.
+ *  IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2.
  *
  *  Thanks are due to Mark Lord for advice and patiently answering stupid
- *  questions, and all those mugs^H^H^H^Hbrave souls who've tested this.
+ *  questions, and all those mugs^H^H^H^Hbrave souls who've tested this,
+ *  especially Andre Hedrick.
  *
  *  Version 0.01	Initial version, #include'd in ide.c rather than
  *                      compiled separately.
@@ -29,22 +30,48 @@
  *  Version 0.07	Added support for DC4030 variants
  *			Secondary interface autodetection
  *  Version 0.08	Renamed to pdc4030.c
+ *  Version 0.09	Obsolete - never released - did manual write request
+ *			splitting before max_sectors[major][minor] available.
+ *  Version 0.10	Updated for 2.1 series of kernels
+ *  Version 0.11	Updated for 2.3 series of kernels
+ *			Autodetection code added.
+ *
+ *  Version 0.90	Transition to BETA code. No lost/unexpected interrupts
  */
 
 /*
  * Once you've compiled it in, you'll have to also enable the interface
  * setup routine from the kernel command line, as in 
  *
- *	'linux ide0=dc4030'
+ *	'linux ide0=dc4030' or 'linux ide1=dc4030'
+ *
+ * It should now work as a second controller also ('ide1=dc4030') but only
+ * if you DON'T have BIOS V4.44, which has a bug. If you have this version
+ * and EPROM programming facilities, you need to fix 4 bytes:
+ * 	2496:	81	81
+ *	2497:	3E	3E
+ *	2498:	22	98	*
+ *	2499:	06	05	*
+ *	249A:	F0	F0
+ *	249B:	01	01
+ *	...
+ *	24A7:	81	81
+ *	24A8:	3E	3E
+ *	24A9:	22	98	*
+ *	24AA:	06	05	*
+ *	24AB:	70	70
+ *	24AC:	01	01
  *
- * As before, it seems that somewhere around 3Megs when writing, bad things
- * start to happen [timeouts/retries -ml]. If anyone can give me more feedback,
- * I'd really appreciate it.  [email: peterd@pnd-pc.demon.co.uk]
+ * As of January 1999, Promise Technology Inc. have finally supplied me with
+ * some technical information which has shed a glimmer of light on some of the
+ * problems I was having, especially with writes. 
  *
+ * There are still problems with the robustness and efficiency of this driver
+ * because I still don't understand what the card is doing with interrupts.
  */
 
-
-#undef REALLY_SLOW_IO		/* most systems can safely undef this */
+#define DEBUG_READ
+#define DEBUG_WRITE
 
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -54,15 +81,12 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
 #include <asm/irq.h>
-#include "ide.h"
-#include "pdc4030.h"
 
-/* This is needed as the controller may not interrupt if the required data is
-available in the cache. We have to simulate an interrupt. Ugh! */
-
-extern void ide_intr(int, void *dev_id, struct pt_regs*);
+#include "pdc4030.h"
 
 /*
  * promise_selectproc() is invoked by ide.c
@@ -78,7 +102,8 @@
 
 /*
  * pdc4030_cmd handles the set of vendor specific commands that are initiated
- * by command F0. They all have the same success/failure notification.
+ * by command F0. They all have the same success/failure notification -
+ * 'P' (=0x50) on success, 'p' (=0x70) on failure.
  */
 int pdc4030_cmd(ide_drive_t *drive, byte cmd)
 {
@@ -108,56 +133,70 @@
 		return 1; /* device returned failure */
 }
 
-ide_hwif_t *hwif_required = NULL;
+/*
+ * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive
+ */
+int pdc4030_identify(ide_drive_t *drive)
+{
+	return pdc4030_cmd(drive, PROMISE_IDENTIFY);
+}
+
+int enable_promise_support = 0;
 
-void setup_pdc4030 (ide_hwif_t *hwif)
+void __init init_pdc4030 (void)
 {
-    hwif_required = hwif;
+	enable_promise_support = 1;
 }
 
 /*
-init_pdc4030: Test for presence of a Promise caching controller card.
-Returns: 0 if no Promise card present at this io_base
-	 1 if Promise card found
-*/
-int init_pdc4030 (void)
+ * setup_pdc4030()
+ * Completes the setup of a Promise DC4030 controller card, once found.
+ */
+int __init setup_pdc4030 (ide_hwif_t *hwif)
 {
-	ide_hwif_t *hwif = hwif_required;
         ide_drive_t *drive;
-	ide_hwif_t *second_hwif;
+	ide_hwif_t *hwif2;
 	struct dc_ident ident;
 	int i;
 	
 	if (!hwif) return 0;
 
 	drive = &hwif->drives[0];
-	second_hwif = &ide_hwifs[hwif->index+1];
-	if(hwif->chipset == ide_pdc4030) /* we've already been found ! */
-	    return 1;
-
-	if(IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF)
-	{
-	    return 0;
+	hwif2 = &ide_hwifs[hwif->index+1];
+	if (hwif->chipset == ide_pdc4030) /* we've already been found ! */
+		return 1;
+
+	if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) {
+		return 0;
 	}
 	OUT_BYTE(0x08,IDE_CONTROL_REG);
-	if(pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {
-	    return 0;
+	if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {
+		return 0;
 	}
-	if(ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
-	    printk("%s: Failed Promise read config!\n",hwif->name);
-	    return 0;
+	if (ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
+		printk(KERN_INFO
+			"%s: Failed Promise read config!\n",hwif->name);
+		return 0;
 	}
 	ide_input_data(drive,&ident,SECTOR_WORDS);
-	if(ident.id[1] != 'P' || ident.id[0] != 'T') {
-            return 0;
+	if (ident.id[1] != 'P' || ident.id[0] != 'T') {
+		return 0;
 	}
-	printk("%s: Promise caching controller, ",hwif->name);
+	printk(KERN_INFO "%s: Promise caching controller, ",hwif->name);
 	switch(ident.type) {
-            case 0x43:	printk("DC4030VL-2, "); break;
-            case 0x41:	printk("DC4030VL-1, "); break;
-	    case 0x40:	printk("DC4030VL, "); break;
-            default:	printk("unknown - type 0x%02x - please report!\n"
+		case 0x43:	printk("DC4030VL-2, "); break;
+		case 0x41:	printk("DC4030VL-1, "); break;
+		case 0x40:	printk("DC4030VL, "); break;
+		default:
+			printk("unknown - type 0x%02x - please report!\n"
 			       ,ident.type);
+			printk("Please e-mail the following data to "
+			       "promise@pnd-pc.demon.co.uk along with\n"
+			       "a description of your card and drives:\n");
+			for (i=0; i < 0x90; i++) {
+				printk("%02x ", ((unsigned char *)&ident)[i]);
+				if ((i & 0x0f) == 0x0f) printk("\n");
+			}
 			return 0;
 	}
 	printk("%dKB cache, ",(int)ident.cache_mem);
@@ -167,38 +206,104 @@
             default:   hwif->irq = 15; break;
 	}
 	printk("on IRQ %d\n",hwif->irq);
-	hwif->chipset     = second_hwif->chipset    = ide_pdc4030;
-	hwif->mate        = second_hwif;
-	second_hwif->mate = hwif;
-	second_hwif->channel = 1;
-	hwif->selectproc  = second_hwif->selectproc = &promise_selectproc;
+
+	/*
+	 * Once found and identified, we set up the next hwif in the array
+	 * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq
+	 * and other settings as the main hwif. This gives us two "mated"
+	 * hwifs pointing to the Promise card.
+	 *
+	 * We also have to shift the default values for the remaining
+	 * interfaces "up by one" to make room for the second interface on the
+	 * same set of values.
+	 */
+
+	hwif->chipset	= hwif2->chipset = ide_pdc4030;
+	hwif->mate	= hwif2;
+	hwif2->mate	= hwif;
+	hwif2->channel	= 1;
+	hwif->selectproc = hwif2->selectproc = &promise_selectproc;
+	hwif->serialized = hwif2->serialized = 1;
+
 /* Shift the remaining interfaces down by one */
 	for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
 		ide_hwif_t *h = &ide_hwifs[i];
 
-		printk("Shifting i/f %d values to i/f %d\n",i-1,i);
-		ide_init_hwif_ports(h->io_ports, (h-1)->io_ports[IDE_DATA_OFFSET], NULL);
-		h->io_ports[IDE_CONTROL_OFFSET] = (h-1)->io_ports[IDE_CONTROL_OFFSET];
+#ifdef DEBUG
+		printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);
+#endif
+		ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL);
+		memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports));
 		h->noprobe = (h-1)->noprobe;
 	}
-	ide_init_hwif_ports(second_hwif->io_ports, hwif->io_ports[IDE_DATA_OFFSET], NULL);
-	second_hwif->io_ports[IDE_CONTROL_OFFSET] = hwif->io_ports[IDE_CONTROL_OFFSET];
-	second_hwif->irq = hwif->irq;
+	ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL);
+	memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports));
+	hwif2->irq = hwif->irq;
+	hwif2->hw.irq = hwif->hw.irq = hwif->irq;
 	for (i=0; i<2 ; i++) {
-            hwif->drives[i].io_32bit = 3;
-	    second_hwif->drives[i].io_32bit = 3;
-	    if(!ident.current_tm[i+2].cyl) second_hwif->drives[i].noprobe=1;
+		hwif->drives[i].io_32bit = 3;
+		hwif2->drives[i].io_32bit = 3;
+		hwif->drives[i].keep_settings = 1;
+		hwif2->drives[i].keep_settings = 1;
+		if (!ident.current_tm[i].cyl)
+			hwif->drives[i].noprobe = 1;
+		if (!ident.current_tm[i+2].cyl)
+			hwif2->drives[i].noprobe = 1;
 	}
         return 1;
 }
 
 /*
+ * detect_pdc4030()
+ * Tests for the presence of a DC4030 Promise card on this interface
+ * Returns: 1 if found, 0 if not found
+ */
+int __init detect_pdc4030(ide_hwif_t *hwif)
+{
+	ide_drive_t *drive = &hwif->drives[0];
+
+	if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */
+		return 0;
+	}
+	OUT_BYTE(0xF3, IDE_SECTOR_REG);
+	OUT_BYTE(0x14, IDE_SELECT_REG);
+	OUT_BYTE(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG);
+	
+	ide_delay_50ms();
+
+	if (IN_BYTE(IDE_ERROR_REG) == 'P' &&
+	    IN_BYTE(IDE_NSECTOR_REG) == 'T' &&
+	    IN_BYTE(IDE_SECTOR_REG) == 'I') {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+void __init ide_probe_for_pdc4030(void)
+{
+	unsigned int	index;
+	ide_hwif_t	*hwif;
+
+	if (enable_promise_support == 0)
+		return;
+	for (index = 0; index < MAX_HWIFS; index++) {
+		hwif = &ide_hwifs[index];
+		if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) {
+			setup_pdc4030(hwif);
+		}
+	}
+}
+
+
+
+/*
  * promise_read_intr() is the handler for disk read/multread interrupts
  */
 static void promise_read_intr (ide_drive_t *drive)
 {
 	byte stat;
-	int i;
+	int total_remaining;
 	unsigned int sectors_left, sectors_avail, nsect;
 	struct request *rq;
 
@@ -209,99 +314,172 @@
 
 read_again:
 	do {
-	    sectors_left = IN_BYTE(IDE_NSECTOR_REG);
-	    IN_BYTE(IDE_SECTOR_REG);
+		sectors_left = IN_BYTE(IDE_NSECTOR_REG);
+		IN_BYTE(IDE_SECTOR_REG);
 	} while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);
 	rq = HWGROUP(drive)->rq;
 	sectors_avail = rq->nr_sectors - sectors_left;
+	if (!sectors_avail)
+		goto read_again;
 
 read_next:
 	rq = HWGROUP(drive)->rq;
-	if ((nsect = rq->current_nr_sectors) > sectors_avail)
+	nsect = rq->current_nr_sectors;
+	if (nsect > sectors_avail)
 		nsect = sectors_avail;
 	sectors_avail -= nsect;
 	ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
-#ifdef DEBUG
-	printk("%s:  promise_read: sectors(%ld-%ld), buffer=0x%08lx, "
-	       "remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, 
-	       (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
+#ifdef DEBUG_READ
+	printk(KERN_DEBUG "%s:  promise_read: sectors(%ld-%ld), "
+	       "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector,
+	       rq->sector+nsect-1, (unsigned long) rq->buffer,
+	       rq->nr_sectors-nsect);
 #endif
 	rq->sector += nsect;
 	rq->buffer += nsect<<9;
 	rq->errors = 0;
-	i = (rq->nr_sectors -= nsect);
-	if ((rq->current_nr_sectors -= nsect) <= 0)
+	rq->nr_sectors -= nsect;
+	total_remaining = rq->nr_sectors;
+	if ((rq->current_nr_sectors -= nsect) <= 0) {
 		ide_end_request(1, HWGROUP(drive));
-	if (i > 0) {
+	}
+/*
+ * Now the data has been read in, do the following:
+ * 
+ * if there are still sectors left in the request, 
+ *   if we know there are still sectors available from the interface,
+ *     go back and read the next bit of the request.
+ *   else if DRQ is asserted, there are more sectors available, so
+ *     go back and find out how many, then read them in.
+ *   else if BUSY is asserted, we are going to get an interrupt, so
+ *     set the handler for the interrupt and just return
+ */
+	if (total_remaining > 0) {
 		if (sectors_avail)
-		    goto read_next;
+			goto read_next;
 		stat = GET_STAT();
-		if(stat & DRQ_STAT)
-		    goto read_again;
-		if(stat & BUSY_STAT) {
-		    ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
-		    return;
+		if (stat & DRQ_STAT)
+			goto read_again;
+		if (stat & BUSY_STAT) {
+			ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
+#ifdef DEBUG_READ
+			printk(KERN_DEBUG "%s: promise_read: waiting for"
+			       "interrupt\n", drive->name);
+#endif 
+			return;
 		}
-		printk("Ah! promise read intr: sectors left !DRQ !BUSY\n");
+		printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left "
+		       "!DRQ !BUSY\n", drive->name);
 		ide_error(drive, "promise read intr", stat);
 	}
 }
 
 /*
+ * promise_complete_pollfunc()
+ * This is the polling function for waiting (nicely!) until drive stops
+ * being busy. It is invoked at the end of a write, after the previous poll
+ * has finished.
+ *
+ * Once not busy, the end request is called.
+ */
+static void promise_complete_pollfunc(ide_drive_t *drive)
+{
+	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+	struct request *rq = hwgroup->rq;
+	int i;
+
+	if (GET_STAT() & BUSY_STAT) {
+		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			ide_set_handler(drive, &promise_complete_pollfunc, 1);
+			return; /* continue polling... */
+		}
+		hwgroup->poll_timeout = 0;
+		printk(KERN_ERR "%s: completion timeout - still busy!\n",
+		       drive->name);
+		ide_error(drive, "busy timeout", GET_STAT());
+		return;
+	}
+
+	hwgroup->poll_timeout = 0;
+#ifdef DEBUG_WRITE
+	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
+#endif
+	for (i = rq->nr_sectors; i > 0; ) {
+		i -= rq->current_nr_sectors;
+		ide_end_request(1, hwgroup);
+	}
+}
+
+/*
  * promise_write_pollfunc() is the handler for disk write completion polling.
  */
 static void promise_write_pollfunc (ide_drive_t *drive)
 {
-	int i;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	struct request *rq;
 
-        if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
-            if (time_before(jiffies, hwgroup->poll_timeout)) {
-                ide_set_handler (drive, &promise_write_pollfunc, 1);
-                return; /* continue polling... */
-            }
-            printk("%s: write timed-out!\n",drive->name);
-            ide_error (drive, "write timeout", GET_STAT());
-            return;
-        }
-        
+	if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
+		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			ide_set_handler (drive, &promise_write_pollfunc, 1);
+			return; /* continue polling... */
+		}
+		hwgroup->poll_timeout = 0;
+		printk(KERN_ERR "%s: write timed-out!\n",drive->name);
+		ide_error (drive, "write timeout", GET_STAT());
+		return;
+	}
+
+	/*
+	 * Now write out last 4 sectors and poll for not BUSY
+	 */
 	ide_multwrite(drive, 4);
-        rq = hwgroup->rq;
-        for (i = rq->nr_sectors; i > 0;) {
-            i -= rq->current_nr_sectors;
-            ide_end_request(1, hwgroup);
-        }
-        return;
+	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+	ide_set_handler(drive, &promise_complete_pollfunc, 1);
+#ifdef DEBUG_WRITE
+	printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
+		drive->name, GET_STAT());
+#endif
+	return;
 }
 
 /*
  * promise_write() transfers a block of one or more sectors of data to a
  * drive as part of a disk write operation. All but 4 sectors are transfered
  * in the first attempt, then the interface is polled (nicely!) for completion
- * before the final 4 sectors are transfered. Don't ask me why, but this is
- * how it's done in the drivers for other O/Ses. There is no interrupt
- * generated on writes, which is why we have to do it like this.
+ * before the final 4 sectors are transfered. There is no interrupt generated
+ * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY.
  */
 static void promise_write (ide_drive_t *drive)
 {
-    ide_hwgroup_t *hwgroup = HWGROUP(drive);
-    struct request *rq = &hwgroup->wrq;
-    int i;
-
-    if (rq->nr_sectors > 4) {
-        ide_multwrite(drive, rq->nr_sectors - 4);
-        hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-        ide_set_handler (drive, &promise_write_pollfunc, 1);
-        return;
-    } else {
-        ide_multwrite(drive, rq->nr_sectors);
-        rq = hwgroup->rq;
-        for (i = rq->nr_sectors; i > 0;) {
-            i -= rq->current_nr_sectors;
-            ide_end_request(1, hwgroup);
-        }
-    }
+	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+	struct request *rq = &hwgroup->wrq;
+
+#ifdef DEBUG_WRITE
+	printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "
+	       "buffer=0x%08x\n", drive->name, rq->sector,
+	       rq->sector + rq->nr_sectors - 1, (unsigned int)rq->buffer);
+#endif
+
+	/*
+	 * If there are more than 4 sectors to transfer, do n-4 then go into
+	 * the polling strategy as defined above.
+	 */
+	if (rq->nr_sectors > 4) {
+		ide_multwrite(drive, rq->nr_sectors - 4);
+		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		ide_set_handler (drive, &promise_write_pollfunc, 1);
+	} else {
+	/*
+	 * There are 4 or fewer sectors to transfer, do them all in one go
+	 * and wait for NOT BUSY.
+	 */
+		ide_multwrite(drive, rq->nr_sectors);
+		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		ide_set_handler(drive, &promise_complete_pollfunc, 1);
+#ifdef DEBUG_WRITE
+		printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
+			"status = %02x\n", drive->name, GET_STAT());
+#endif
+	}
 }
 
 /*
@@ -315,43 +493,54 @@
 	byte stat;
 
 	if (rq->cmd == READ) {
-	    ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
-	    OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
-/* The card's behaviour is odd at this point. If the data is
-   available, DRQ will be true, and no interrupt will be
-   generated by the card. If this is the case, we need to simulate
-   an interrupt. Ugh! Otherwise, if an interrupt will occur, bit0
-   of the SELECT register will be high, so we can just return and
-   be interrupted.*/
-	    timeout = jiffies + HZ/20; /* 50ms wait */
-	    do {
-		stat=GET_STAT();
-		if(stat & DRQ_STAT) {
-                    disable_irq(HWIF(drive)->irq);
-		    ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
-                    enable_irq(HWIF(drive)->irq);
-		    return;
-		}
-		if(IN_BYTE(IDE_SELECT_REG) & 0x01)
-		    return;
-		udelay(1);
-	    } while (time_before(jiffies, timeout));
-	    printk("%s: reading: No DRQ and not waiting - Odd!\n",
-		   drive->name);
-	    return;
-	}
-	if (rq->cmd == WRITE) {
-	    OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
-	    if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
-		printk("%s: no DRQ after issuing PROMISE_WRITE\n", drive->name);
-		return;
-	    }
-	    if (!drive->unmask)
-		__cli();	/* local CPU only */
-	    HWGROUP(drive)->wrq = *rq; /* scratchpad */
-	    promise_write(drive);
-	    return;
+		OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
+/*
+ * The card's behaviour is odd at this point. If the data is
+ * available, DRQ will be true, and no interrupt will be
+ * generated by the card. If this is the case, we need to call the 
+ * "interrupt" handler (promise_read_intr) directly. Otherwise, if
+ * an interrupt is going to occur, bit0 of the SELECT register will
+ * be high, so we can set the handler the just return and be interrupted.
+ * If neither of these is the case, we wait for up to 50ms (badly I'm
+ * afraid!) until one of them is.
+ */
+		timeout = jiffies + HZ/20; /* 50ms wait */
+		do {
+			stat=GET_STAT();
+			if (stat & DRQ_STAT) {
+				udelay(1);
+				promise_read_intr(drive);
+				return;
+			}
+			if (IN_BYTE(IDE_SELECT_REG) & 0x01) {
+#ifdef DEBUG_READ
+				printk(KERN_DEBUG "%s: read: waiting for "
+				                  "interrupt\n", drive->name);
+#endif
+				ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
+				return;
+			}
+			udelay(1);
+		} while (time_before(jiffies, timeout));
+
+		printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n",
+			drive->name);
+
+	} else if (rq->cmd == WRITE) {
+		OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
+		if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
+			printk(KERN_ERR "%s: no DRQ after issuing "
+			       "PROMISE_WRITE\n", drive->name);
+			return;
+	    	}
+		if (!drive->unmask)
+			__cli();	/* local CPU only */
+		HWGROUP(drive)->wrq = *rq; /* scratchpad */
+		promise_write(drive);
+
+	} else {
+		printk("KERN_WARNING %s: bad command: %d\n",
+		       drive->name, rq->cmd);
+		ide_end_request(0, HWGROUP(drive));
 	}
-	printk("%s: bad command: %d\n", drive->name, rq->cmd);
-	ide_end_request(0, HWGROUP(drive));
 }
diff -urN linux-2.2.10-pristine/drivers/block/piix.c linux/drivers/block/piix.c
--- linux-2.2.10-pristine/drivers/block/piix.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/piix.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,309 @@
+/*
+ * linux/drivers/block/piix.c	Version 0.25	July 11, 1999
+ *
+ *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ *  Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer
+ *
+ *  PIO mode setting function for Intel chipsets.  
+ *  For use instead of BIOS settings.
+ *
+ * 40-41
+ * 42-43
+ * 
+ *                 41
+ *                 43
+ *
+ * | PIO 0       | c0 | 80 | 0 | 	piix_tune_drive(drive, 0);
+ * | PIO 2 | SW2 | d0 | 90 | 4 | 	piix_tune_drive(drive, 2);
+ * | PIO 3 | MW1 | e1 | a1 | 9 | 	piix_tune_drive(drive, 3);
+ * | PIO 4 | MW2 | e3 | a3 | b | 	piix_tune_drive(drive, 4);
+ * 
+ * sitre = word40 & 0x4000; primary
+ * sitre = word42 & 0x4000; secondary
+ *
+ * 44 8421|8421    hdd|hdb
+ * 
+ * 48 8421         hdd|hdc|hdb|hda udma enabled
+ *
+ *    0001         hda
+ *    0010         hdb
+ *    0100         hdc
+ *    1000         hdd
+ *
+ * 4a 84|21        hdb|hda
+ * 4b 84|21        hdd|hdc
+ * 
+ *    00|00 udma 0
+ *    01|01 udma 1
+ *    10|10 udma 2
+ *    11|11 reserved
+ *
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
+ *
+ * #if 0
+ * int err;
+ * err = ide_config_drive_speed(drive, speed);
+ * (void) ide_config_drive_speed(drive, speed);
+ * #else
+ * #endif
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define PIIX_DEBUG_DRIVE_INFO		0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+#ifdef CONFIG_BLK_DEV_PIIX_TUNING
+/*
+ *
+ */
+static byte piix_dma_2_pio (byte xfer_rate) {
+	switch(xfer_rate) {
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+		case XFER_MW_DMA_2:
+		case XFER_PIO_4:
+			return 4;
+		case XFER_MW_DMA_1:
+		case XFER_PIO_3:
+			return 3;
+		case XFER_SW_DMA_2:
+		case XFER_PIO_2:
+			return 2;
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+		case XFER_PIO_SLOW:
+		default:
+			return 0;
+	}
+}
+#endif /* CONFIG_BLK_DEV_PIIX_TUNING */
+
+/*
+ *  Based on settings done by AMI BIOS
+ *  (might be usefull if drive is not registered in CMOS for any reason).
+ */
+static void piix_tune_drive (ide_drive_t *drive, byte pio)
+{
+	unsigned long flags;
+	u16 master_data;
+	byte slave_data;
+	int is_slave		= (&HWIF(drive)->drives[1] == drive);
+	int master_port		= HWIF(drive)->index ? 0x42 : 0x40;
+	int slave_port		= 0x44;
+				 /* ISP  RTC */
+	byte timings[][2]	= { { 0, 0 },
+				    { 0, 0 },
+				    { 1, 0 },
+				    { 2, 1 },
+				    { 2, 3 }, };
+
+	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+	pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
+	if (is_slave) {
+		master_data = master_data | 0x4000;
+		if (pio > 1)
+			/* enable PPE, IE and TIME */
+			master_data = master_data | 0x0070;
+		pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
+		slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
+		slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1]
+					   << (HWIF(drive)->index ? 4 : 0)));
+	} else {
+		master_data = master_data & 0xccf8;
+		if (pio > 1)
+			/* enable PPE, IE and TIME */
+			master_data = master_data | 0x0007;
+		master_data = master_data | (timings[pio][0] << 12) |
+			      (timings[pio][1] << 8);
+	}
+	save_flags(flags);
+	cli();
+	pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
+	if (is_slave)
+		pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
+	restore_flags(flags);
+}
+
+#ifdef CONFIG_BLK_DEV_PIIX_TUNING
+
+static int piix_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;
+
+	int			sitre;
+	short			reg4042, reg44, reg48, reg4a;
+	byte			speed;
+	int			u_speed;
+
+	byte maslave		= hwif->channel ? 0x42 : 0x40;
+	int ultra		= (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0;
+	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	int a_speed		= 2 << (drive_number * 4);
+	int u_flag		= 1 << drive_number;
+
+	pci_read_config_word(dev, maslave, &reg4042);
+	sitre =  (reg4042 & 0x4000) ? 1 : 0;
+	pci_read_config_word(dev, 0x44, &reg44);
+	pci_read_config_word(dev, 0x48, &reg48);
+	pci_read_config_word(dev, 0x4a, &reg4a);
+
+	if (id->dma_ultra && (ultra)) {
+		if (!(reg48 & u_flag)) {
+			pci_write_config_word(dev, 0x48, reg48|u_flag);
+		}
+	} else {
+		if (reg48 & u_flag) {
+			pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+		}
+	}
+
+	if ((id->dma_ultra & 0x0010) && (ultra)) {
+		goto backspeed;
+	} else if ((id->dma_ultra & 0x0008) && (ultra)) {
+		goto backspeed;
+	} else if ((id->dma_ultra & 0x0004) && (ultra)) {
+backspeed:
+		drive->id->dma_mword &= ~0x0F00;
+		drive->id->dma_1word &= ~0x0F00;
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0404;
+		}
+		u_speed = 2 << (drive_number * 4);
+		if (!(reg4a & u_speed)) {
+			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+		}
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (ultra)) {
+		drive->id->dma_mword &= ~0x0F00;
+		drive->id->dma_1word &= ~0x0F00;
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0202;
+		}
+		u_speed = 1 << (drive_number * 4);
+		if (!(reg4a & u_speed)) {
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+		}
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (ultra)) {
+		drive->id->dma_mword &= ~0x0F00;
+		drive->id->dma_1word &= ~0x0F00;
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0101;
+		}
+		u_speed = 0 << (drive_number * 4);
+		if (!(reg4a & u_speed)) {
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+		}
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		if (reg4a & a_speed)
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		drive->id->dma_ultra &= ~0x0F00;
+		drive->id->dma_1word &= ~0x0F00;
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+		}
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		if (reg4a & a_speed)
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		drive->id->dma_ultra &= ~0x0F00;
+		drive->id->dma_1word &= ~0x0F00;
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+		}
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_1word & 0x0004) {
+		if (reg4a & a_speed)
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		drive->id->dma_ultra &= ~0x0F00;
+		drive->id->dma_mword &= ~0x0F00;
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+		}
+		speed = XFER_SW_DMA_2;
+        } else {
+		speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+	}
+
+	piix_tune_drive(drive, piix_dma_2_pio(speed));
+
+	(void) ide_config_drive_speed(drive, speed);
+
+#if PIIX_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d ",
+		drive->name,
+		ide_xfer_verbose(speed),
+		drive_number);
+	printk("\n");
+#endif /* PIIX_DEBUG_DRIVE_INFO */
+
+	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 piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			 return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive), drive);
+		default :
+			break;
+	}
+	/* Other cases are done by generic IDE-DMA code. */
+	return ide_dmaproc(func, drive);
+}
+#endif /* CONFIG_BLK_DEV_PIIX_TUNING */
+
+void ide_init_piix (ide_hwif_t *hwif)
+{
+	hwif->tuneproc = &piix_tune_drive;
+
+	if (hwif->dma_base) {
+#ifdef CONFIG_BLK_DEV_PIIX_TUNING
+		hwif->dmaproc = &piix_dmaproc;
+#endif /* CONFIG_BLK_DEV_PIIX_TUNING */
+		hwif->drives[0].autotune = 0;
+		hwif->drives[1].autotune = 0;
+	} else {
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+
+}
diff -urN linux-2.2.10-pristine/drivers/block/qd6580.c linux/drivers/block/qd6580.c
--- linux-2.2.10-pristine/drivers/block/qd6580.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/qd6580.c	Thu Jul 22 20:38:43 1999
@@ -19,8 +19,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -urN linux-2.2.10-pristine/drivers/block/rz1000.c linux/drivers/block/rz1000.c
--- linux-2.2.10-pristine/drivers/block/rz1000.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/rz1000.c	Thu Jul 22 20:38:43 1999
@@ -26,9 +26,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
-#include <asm/io.h>
 #include <linux/pci.h>
-#include "ide.h"
+#include <linux/ide.h>
+
+#include <asm/io.h>
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 
diff -urN linux-2.2.10-pristine/drivers/block/sis5513.c linux/drivers/block/sis5513.c
--- linux-2.2.10-pristine/drivers/block/sis5513.c	Wed Dec 31 18:00:00 1969
+++ linux/drivers/block/sis5513.c	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,418 @@
+/*
+ * linux/drivers/block/sis5513.c	Version 0.06	July 11, 1999
+ *
+ * Copyright (C) 1999	Andre Hedrick
+ *
+ * drive_number
+ *	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+static struct pci_dev *host_dev;
+
+#define SIS5513_DEBUG_DRIVE_INFO	0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ * ((id->word93 & 0x2000) && (HWIF(drive)->udma_four))
+ */
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+
+	byte			drive_pci, test1, test2, mask;
+	int			err;
+
+	byte speed		= 0x00;
+	byte unmask		= 0xE0;
+	byte four_two		= 0x00;
+	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	byte udma_66		= ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+
+	if (host_dev) {
+		switch(host_dev->device) {
+			case PCI_DEVICE_ID_SI_530:
+			case PCI_DEVICE_ID_SI_620:
+				unmask   = 0xF0;
+				four_two = 0x01;
+			default:
+				break;
+		}
+	}
+
+	switch(drive_number) {
+		case 0:		drive_pci = 0x40;break;
+		case 1:		drive_pci = 0x42;break;
+		case 2:		drive_pci = 0x44;break;
+		case 3:		drive_pci = 0x46;break;
+		default:	return ide_dma_off;
+	}
+
+	pci_read_config_byte(dev, drive_pci, &test1);
+	pci_read_config_byte(dev, drive_pci|0x01, &test2);
+
+	if ((!ultra) && (test2 & 0x80)) {
+		pci_write_config_byte(dev, drive_pci|0x01, test2 & ~0x80);
+		pci_read_config_byte(dev, drive_pci|0x01, &test2);
+	}
+
+	if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) {
+		if (!((id->dma_ultra >> 8) & 16)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x1010;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		if (!(test2 & 0x90)) {
+			pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+			pci_write_config_byte(dev, drive_pci|0x01, test2|0x90);
+		}
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) {
+		if (!((id->dma_ultra >> 8) & 8)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0808;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		if (!(test2 & 0xA0)) {
+			pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+			pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0);
+		}
+		speed = XFER_UDMA_3;
+	} else if ((id->dma_ultra & 0x0004) && (ultra)) {
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		mask = (four_two) ? 0xB0 : 0xA0;
+		if (!(test2 & mask)) {
+			pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+			pci_write_config_byte(dev, drive_pci|0x01, test2|mask);
+		}
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (ultra)) {
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		mask = (four_two) ? 0xD0 : 0xC0;
+		if (!(test2 & mask)) {
+			pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+			pci_write_config_byte(dev, drive_pci|0x01, test2|mask);
+		}
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (ultra)) {
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		if (!(test2 & unmask)) {
+			pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask);
+			pci_write_config_byte(dev, drive_pci|0x01, test2|unmask);
+		}
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		if (!((id->dma_mword >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0101;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		if (!((id->dma_1word >> 8) & 2)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		if (!((id->dma_1word >> 8) & 1)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_0;
+        } else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	err = ide_config_drive_speed(drive, speed);
+
+#if SIS5513_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d\n",
+		drive->name,
+		ide_xfer_verbose(speed),
+		drive_number);
+#endif /* SIS5513_DEBUG_DRIVE_INFO */
+
+	return ((int)	((id->dma_ultra >> 11) & 3) ? 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 void config_drive_art_rwp (ide_drive_t *drive)
+{
+	ide_hwif_t *hwif		= HWIF(drive);
+	struct pci_dev *dev		= hwif->pci_dev;
+
+	byte				timing, pio, drive_pci, test1, test2;
+
+	unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
+	unsigned short xfer_pio		= drive->id->eide_pio_modes;
+	int drive_number		= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+
+	if (drive->media == ide_disk) {
+		struct pci_dev *dev	= hwif->pci_dev;
+		byte reg4bh		= 0;
+                byte rw_prefetch	= (0x11 << drive_number);
+
+		pci_read_config_byte(dev, 0x4b, &reg4bh);
+		if ((reg4bh & rw_prefetch) != rw_prefetch)
+			pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
+	}
+
+	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 : xfer_pio;
+	}
+
+	timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+/*
+ *               Mode 0       Mode 1     Mode 2     Mode 3     Mode 4
+ * Active time    8T (240ns)  6T (180ns) 4T (120ns) 3T  (90ns) 3T  (90ns)
+ * 0x41 2:0 bits  000          110        100        011        011
+ * Recovery time 12T (360ns)  7T (210ns) 4T (120ns) 3T  (90ns) 1T  (30ns)
+ * 0x40 3:0 bits 0000         0111       0100       0011       0001
+ * Cycle time    20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns)
+ */
+
+	switch(drive_number) {
+		case 0:		drive_pci = 0x40;break;
+		case 1:		drive_pci = 0x42;break;
+		case 2:		drive_pci = 0x44;break;
+		case 3:		drive_pci = 0x46;break;
+		default:	return;
+	}
+
+	pci_read_config_byte(dev, drive_pci, &test1);
+	pci_read_config_byte(dev, drive_pci|0x01, &test2);
+
+	/*
+	 * Do a blanket clear of active and recovery timings.
+	 */
+
+	test1 &= ~0x07;
+	test2 &= ~0x0F;
+
+	switch(timing) {
+		case 4:		test1 |= 0x01;test2 |= 0x03;break;
+		case 3:		test1 |= 0x03;test2 |= 0x03;break;
+		case 2:		test1 |= 0x04;test2 |= 0x04;break;
+		case 1:		test1 |= 0x07;test2 |= 0x06;break;
+		default:	break;
+	}
+
+	pci_write_config_byte(dev, drive_pci, test1);
+	pci_write_config_byte(dev, drive_pci|0x01, test2);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id		= drive->id;
+	ide_dma_action_t dma_func	= ide_dma_off_quietly;
+
+	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			return HWIF(drive)->dmaproc(ide_dma_off, drive);
+		}
+
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive, 1);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive, 0);
+			}
+		} else if ((ide_dmaproc(ide_dma_good_drive, drive)) &&
+			   (id->eide_dma_time > 150)) {
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive, 0);
+		}
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * sis5513_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			config_drive_art_rwp(drive);
+			return config_drive_xfer_rate(drive);
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+__initfunc(unsigned int pci_init_sis5513 (struct pci_dev *dev, const char *name))
+{
+	struct pci_dev *host;
+	byte latency = 0, reg48h = 0;
+
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
+	pci_read_config_byte(dev, 0x48, &reg48h);
+
+	for (host = pci_devices; host; host=host->next) {
+		if (host->vendor == PCI_VENDOR_ID_SI &&
+		    host->device == PCI_DEVICE_ID_SI_620) {
+			if (latency != 0x10)
+				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+			host_dev = host;
+			printk("%s: Chipset Core ATA-66, SiS620\n", name);
+			printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n",
+				name,
+				(reg48h & 0x10) ? "33" : "66",
+				(reg48h & 0x20) ? "33" : "66");
+			break;
+		} else if (host->vendor == PCI_VENDOR_ID_SI &&
+			   host->device == PCI_DEVICE_ID_SI_530) {
+			host_dev = host;
+			printk("%s: Chipset Core ATA-66, SiS530\n", name);
+			printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n",
+				name,
+				(reg48h & 0x10) ? "33" : "66",
+				(reg48h & 0x20) ? "33" : "66");
+			break;
+		} else if (host->vendor == PCI_VENDOR_ID_SI &&
+			   host->device == PCI_DEVICE_ID_SI_5600) {
+			host_dev = host;
+			printk("SIS5600:%s Chipset Core ATA-33\n", name);
+			break;
+		} else if (host->vendor == PCI_VENDOR_ID_SI &&
+			   host->device == PCI_DEVICE_ID_SI_5597) {
+			host_dev = host;
+			printk("SIS5597:%s Chipset Core ATA-33\n", name);
+			break;
+		}
+	}
+
+	if (host_dev) {
+		byte reg52h = 0;
+
+		pci_read_config_byte(dev, 0x52, &reg52h);
+		if (!(reg52h & 0x04))
+			pci_write_config_byte(dev, 0x52, reg52h|0x04);
+	}
+
+	return 0;
+}
+
+__initfunc(void ide_init_sis5513 (ide_hwif_t *hwif))
+{
+	byte reg48h = 0;
+	byte mask = hwif->channel ? 0x20 : 0x10;
+
+	pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
+	hwif->irq = hwif->channel ? 15 : 14;
+
+	if (!(hwif->dma_base))
+		return;
+
+	if (host_dev) {
+		switch(host_dev->device) {
+			case PCI_DEVICE_ID_SI_530:
+			case PCI_DEVICE_ID_SI_620:
+				hwif->autodma = 1;
+				hwif->udma_four = (reg48h & mask) ? 0 : 1;
+				hwif->dmaproc = &sis5513_dmaproc;
+				return;
+			case PCI_DEVICE_ID_SI_5600:
+			case PCI_DEVICE_ID_SI_5597:
+				hwif->autodma = 1;
+				hwif->udma_four = 0;
+				hwif->dmaproc = &sis5513_dmaproc;
+				return;
+			default:
+				hwif->autodma = 0;
+				hwif->udma_four = 0;
+				return;
+		}
+	}
+}
diff -urN linux-2.2.10-pristine/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c
--- linux-2.2.10-pristine/drivers/block/sl82c105.c	Tue Jul 20 19:11:52 1999
+++ linux/drivers/block/sl82c105.c	Thu Jul 22 20:38:43 1999
@@ -8,11 +8,11 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#include "ide.h"
 #include "ide_modes.h"
 
 void ide_init_sl82c105(ide_hwif_t *hwif)
diff -urN linux-2.2.10-pristine/drivers/block/trm290.c linux/drivers/block/trm290.c
--- linux-2.2.10-pristine/drivers/block/trm290.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/trm290.c	Thu Jul 22 20:38:43 1999
@@ -134,11 +134,10 @@
 #include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 
-#include "ide.h"
-
 static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -185,7 +184,7 @@
 			break;	/* always use PIO for writes */
 #endif
 		case ide_dma_read:
-			if (!(count = ide_build_dmatable(drive)))
+			if (!(count = ide_build_dmatable(drive, func)))
 				break;		/* try PIO instead of DMA */
 			trm290_prepare_drive(drive, 1);	/* select DMA xfer */
 			outl(virt_to_bus(hwif->dmatable)|reading|writing, hwif->dma_base);
diff -urN linux-2.2.10-pristine/drivers/block/umc8672.c linux/drivers/block/umc8672.c
--- linux-2.2.10-pristine/drivers/block/umc8672.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/umc8672.c	Thu Jul 22 20:38:43 1999
@@ -47,8 +47,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -urN linux-2.2.10-pristine/drivers/block/via82c586.c linux/drivers/block/via82c586.c
--- linux-2.2.10-pristine/drivers/block/via82c586.c	Tue Jul 20 19:11:51 1999
+++ linux/drivers/block/via82c586.c	Thu Jul 22 20:38:43 1999
@@ -1,20 +1,47 @@
 /*
- * linux/drivers/block/via82c586.c	Version 0.01	Aug 16, 1998
+ * linux/drivers/block/via82c586.c	Version 0.04	July 11, 1999
  *
- *  Copyright (C) 1998 Michel Aubry
- *  Copyright (C) 1998 Andre Hedrick
+ *  Copyright (C) 1998 Michel Aubry, Maintainer
+ *  Copyright (C) 1998 Andre Hedrick, Maintainer
  *
  *  The VIA MVP-3 is reported OK with UDMA.
+ *  The TX Pro III is also reported OK with UDMA.
  *
- *  VIA chips also have a single FIFO, with the same 64 bytes deep buffer (16 levels 
- *  of 4 bytes each).
- *  However, VIA chips can have the buffer split either 8:8 levels, 16:0 levels or 
- *  0:16 levels between both channels. One could think of using this feature, as even
- *  if no level of FIFO is given to a given channel, one can always reach ATAPI drives 
- *  through it, or, if one channel is unused, configuration defaults to an even split 
- *  FIFO levels.
+ *  VIA chips also have a single FIFO, with the same 64 bytes deep
+ *  buffer (16 levels of 4 bytes each).
+ *
+ *  However, VIA chips can have the buffer split either 8:8 levels,
+ *  16:0 levels or 0:16 levels between both channels. One could think
+ *  of using this feature, as even if no level of FIFO is given to a
+ *  given channel, one can for instance always reach ATAPI drives through
+ *  it, or, if one channel is unused, configuration defaults to
+ *  an even split FIFO levels.
+ *  
+ *  This feature is available only through a kernel command line :
+ *		"splitfifo=Chan,Thr0,Thr1" or "splitfifo=Chan".
+ *		where:  Chan =1,2,3 or 4 and Thrx = 1,2,3,or 4.
+ *
+ *  If Chan == 1:
+ *	gives all the fifo to channel 0,
+ *	sets its threshold to Thr0/4,
+ *	and disables any dma access to channel 1.
+ *
+ *  If chan == 2:
+ *	gives all the fifo to channel 1,
+ *	sets its threshold to Thr1/4,
+ *	and disables any dma access to channel 0.
+ *
+ *  If chan == 3 or 4:
+ *	shares evenly fifo between channels,
+ *	gives channel 0 a threshold of Thr0/4,
+ *	and channel 1 a threshold of Thr1/4.
+ *
+ *  Note that by default (if no command line is provided) and if a channel
+ *  has been disabled in Bios, all the fifo is given to the active channel,
+ *  and its threshold is set to 3/4.
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
@@ -24,9 +51,258 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
+static struct pci_dev *host_dev;
+static struct pci_dev *isa_dev;
+
+#define DISPLAY_VIA_TIMINGS
+
+#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static char *FIFO_str[] = {
+	" 1 ",
+	"3/4",
+	"1/2",
+	"1/4"
+};
+
+static char *control3_str[] = {
+	"No limitation",
+	"64",
+	"128",
+	"192"
+};
+
+static int via_get_info(char *, char **, off_t, int, int);
+extern int (*via_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
+static struct pci_dev *bmide_dev;
+
+static char * print_apollo_drive_config (char *buf, struct pci_dev *dev)
+{
+	int rc;
+	unsigned int time;
+	byte tm;
+	char *p = buf;  
+ 
+	/* Drive Timing Control */
+	rc = pci_read_config_dword(dev, 0x48, &time);
+	p += sprintf(p, "Act Pls Width:  %02d          %02d           %02d          %02d\n",
+			((time & 0xf0000000)>>28) + 1,
+			((time & 0xf00000)>>20) + 1,
+			((time & 0xf000)>>12) + 1,
+			((time & 0xf0)>>4) + 1 );
+	p += sprintf(p, "Recovery Time:  %02d          %02d           %02d          %02d\n",
+			((time & 0x0f000000)>>24) + 1,
+			((time & 0x0f0000)>>16) + 1,
+			((time & 0x0f00)>>8) + 1,
+			(time & 0x0f) + 1 );
+ 
+	/* Address Setup Time */
+	rc = pci_read_config_byte(dev, 0x4C, &tm);
+	p += sprintf(p, "Add. Setup T.:  %01dT          %01dT           %01dT          %01dT\n",
+			((tm & 0xc0)>>6) + 1,
+			((tm & 0x30)>>4) + 1,
+			((tm & 0x0c)>>2) + 1,
+			(tm & 0x03) + 1 );
+ 
+	/* UltraDMA33 Extended Timing Control */
+ 	rc = pci_read_config_dword(dev, 0x50, &time);
+ 	p += sprintf(p, "------------------UDMA-Timing-Control------------------------\n");
+ 	p += sprintf(p, "Enable Meth.:    %01d           %01d            %01d           %01d\n",
+			(time & 0x80000000)	? 1 : 0,
+			(time & 0x800000)	? 1 : 0,
+			(time & 0x8000)		? 1 : 0,
+			(time & 0x80)		? 1 : 0 );
+ 	p += sprintf(p, "Enable:         %s         %s          %s         %s\n",
+			(time & 0x40000000)	? "yes" : "no ",
+			(time & 0x400000)	? "yes" : "no ",
+			(time & 0x4000)		? "yes" : "no ",
+			(time & 0x40)		? "yes" : "no " );
+ 	p += sprintf(p, "Transfer Mode: %s         %s          %s         %s\n",
+			(time & 0x20000000)	? "PIO" : "DMA",
+			(time & 0x200000)	? "PIO" : "DMA",
+			(time & 0x2000)		? "PIO" : "DMA",
+			(time & 0x20)		? "PIO" : "DMA" );
+ 	p += sprintf(p, "Cycle Time:     %01dT          %01dT           %01dT          %01dT\n",
+			((time & 0x03000000)>>24) + 2,
+			((time & 0x030000)>>16) + 2,
+			((time & 0x0300)>>8) + 2,
+			(time & 0x03) + 2 );
+ 
+ 	return (char *)p;
+}
+
+static char * print_apollo_ide_config (char *buf, struct pci_dev *dev)
+{
+	byte time, tmp; 
+	unsigned short size0, size1;
+	int rc;
+	char *p = buf;  
+ 
+	rc = pci_read_config_byte(dev, 0x41, &time);
+	p += sprintf(p, "Prefetch Buffer :      %s                     %s\n",
+		(time & 128)	? "on " : "off",
+		(time & 32)	? "on " : "off" );
+	p += sprintf(p, "Post Write Buffer:     %s                     %s\n",
+		(time & 64)	? "on " : "off",
+		(time & 16)	? "on " : "off" );
+ 
+	/* FIFO configuration */
+	rc = pci_read_config_byte(dev, 0x43, &time);
+	tmp = ((time & 0x20)>>2) + ((time & 0x40)>>3);
+	p += sprintf(p, "FIFO Conf/Chan. :      %02d                      %02d\n",
+			16 - tmp, tmp);
+	tmp = (time & 0x0F)>>2;
+	p += sprintf(p, "Threshold Prim. :      %s                     %s\n",
+			FIFO_str[tmp],
+			FIFO_str[time & 0x03] );
+ 
+	/* chipset Control3 */
+	rc = pci_read_config_byte(dev, 0x46, &time);
+	p += sprintf(p, "Read DMA FIFO flush:   %s                     %s\n",
+			(time & 0x80)	? "on " : "off",
+			(time & 0x40)	? "on " : "off" );
+	p += sprintf(p, "End Sect. FIFO flush:  %s                     %s\n",
+			(time & 0x20)	? "on " : "off",
+			(time & 0x10)	? "on " : "off" );
+	p += sprintf(p, "Max DRDY Pulse Width:  %s %s\n",
+			control3_str[(time & 0x03)],
+			(time & 0x03) ? "PCI clocks" : "" );
+ 
+	/* Primary and Secondary sector sizes */
+	rc = pci_read_config_word(dev, 0x60, &size0);
+	rc = pci_read_config_word(dev, 0x68, &size1);
+	p += sprintf(p, "Bytes Per Sector:      %03d                     %03d\n",
+			size0 & 0xfff,
+			size1 & 0xfff );
+
+	return (char *)p;
+}
+
+static char * print_apollo_chipset_control1 (char *buf, struct pci_dev *dev)
+{
+	byte t;
+	int rc;
+	char *p = buf;  
+	unsigned short c;
+	byte l, l_max;   
+ 
+	rc = pci_read_config_word(dev, 0x04, &c);
+	rc = pci_read_config_byte(dev, 0x44, &t);
+	rc = pci_read_config_byte(dev, 0x0d, &l);
+	rc = pci_read_config_byte(dev, 0x3f, &l_max);
+
+	p += sprintf(p, "Command register = 0x%x\n", c);
+	p += sprintf(p, "Master Read  Cycle IRDY %d Wait State\n",
+			(t & 64) >>6 );
+	p += sprintf(p, "Master Write Cycle IRDY %d Wait State\n",
+			(t & 32) >> 5 );
+	p += sprintf(p, "FIFO Output Data 1/2 Clock Advance: %s\n",
+			(t & 16) ? "on " : "off" );
+	p += sprintf(p, "Bus Master IDE Status Register Read Retry: %s\n",
+			(t & 8) ? "on " : "off" );
+	p += sprintf(p, "Latency timer = %d (max. = %d)\n",
+			l, l_max);
+
+	return (char *)p;
+}
+ 
+static char * print_apollo_chipset_control2 (char *buf, struct pci_dev *dev)
+{
+	byte t;
+	int rc;
+	char *p = buf;  
+	rc = pci_read_config_byte(dev, 0x45, &t);
+	p += sprintf(p, "Interrupt Steering Swap: %s\n",
+			(t & 64) ? "on ":"off" );
+
+	return (char *)p;
+}
+ 
+static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev,
+						unsigned short n)
+{
+	/*
+	 * at that point we can be sure that register 0x20 of the
+	 * chipset contains the right address...
+	 */
+	unsigned int bibma;
+	int rc;
+	byte c0, c1;    
+	char *p = buf; 
+ 
+	rc = pci_read_config_dword(dev, 0x20, &bibma);
+	bibma = (bibma & 0xfff0) ;
+ 
+	/*
+	 * 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);
+ 
+	if (n == 0) {
+        /*p = sprintf(p,"--------------------Primary IDE------------Secondary IDE-----");*/
+		p += sprintf(p, "both channels togth:   %s                     %s\n",
+				(c0&0x80) ? "no" : "yes",
+				(c1&0x80) ? "no" : "yes" );
+	} else {
+        /*p = sprintf(p,"--------------drive0------drive1-------drive0------drive1----");*/
+		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 " );
+	}
+ 
+	return (char *)p;
+}
+
+static int via_get_info (char *buffer, char **addr, off_t offset, int count, int dummy)
+{
+	/*
+	 * print what /proc/via displays,
+	 * if required from DISPLAY_APOLLO_TIMINGS
+	 */
+	char *p = buffer;
+	/* Parameter of chipset : */
+
+	/* Miscellaneous control 1 */
+	p = print_apollo_chipset_control1(buffer, bmide_dev);
+
+	/* Miscellaneous control 2 */
+	p = print_apollo_chipset_control2(p, bmide_dev);
+	/* Parameters of drives: */
+
+	/* Header */
+	p += sprintf(p, "------------------Primary IDE------------Secondary IDE-----\n");
+	p = print_apollo_chipset_control3(p, bmide_dev, 0);
+	p = print_apollo_ide_config(p, bmide_dev);
+	p += sprintf(p, "--------------drive0------drive1-------drive0------drive1----\n");
+	p = print_apollo_chipset_control3(p, bmide_dev, 1);
+	p = print_apollo_drive_config(p, bmide_dev);
+ 
+	return p-buffer;	/* hoping it is less than 4K... */
+}
+
+#endif  /* defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/*
+ *  Used to set Fifo configuration via kernel command line:
+ */
+
+byte fifoconfig = 0;
+static byte newfifo = 0;
+
+/* Used to just intialize once Fifo configuration */
+static short int done = 0;
 
 /*
  *  Set VIA Chipset Timings for (U)DMA modes enabled.
@@ -37,50 +313,288 @@
 static void set_via_timings (ide_hwif_t *hwif)
 {
 	struct pci_dev  *dev = hwif->pci_dev;
-	byte post  = hwif->channel ? 0xc0 : 0x30;
-	byte flush = hwif->channel ? 0xa0 : 0x50;
+	byte post  = hwif->channel ? 0x30 : 0xc0;
+	byte flush = hwif->channel ? 0x50 : 0xa0;
+	int mask = hwif->channel ? ((newfifo & 0x60) ? 0 : 1) :
+				   (((newfifo & 0x60) == 0x60) ? 1 : 0);
 	byte via_config = 0;
 	int rc = 0, errors = 0;
 
 	printk("%s: VIA Bus-Master ", hwif->name);
 
-	if (!hwif->dma_base) {
-		printk(" ERROR, NO DMA_BASE\n");
-		return;
-	}
-
-	/* setting IDE read prefetch buffer and IDE post write buffer.
+	/*
+	 * setting IDE read prefetch buffer and IDE post write buffer.
 	 * (This feature allows prefetched reads and post writes).
 	 */
-	if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) {
+	if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) 
 		errors++;
-		goto via_error;
-	}
-	if ((rc = pci_write_config_byte(dev, 0x41, via_config | post))) {
-		errors++;
-		goto via_error;
+
+	if (mask) {
+		if ((rc = pci_write_config_byte(dev, 0x41, via_config & ~post)))
+			errors++;
+	} else {
+		if ((rc = pci_write_config_byte(dev, 0x41, via_config | post)))
+			errors++;
 	}
 
-	/* setting Channel read and End-of-sector FIFO flush.
+	/*
+	 * setting Channel read and End-of-sector FIFO flush.
 	 * (This feature ensures that FIFO flush is enabled:
          *  - for read DMA when interrupt asserts the given channel.
          *  - at the end of each sector for the given channel.)
 	 */
-	if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) {
+	if ((rc = pci_read_config_byte(dev, 0x46, &via_config)))
 		errors++;
-		goto via_error;
+
+	if (mask) {
+		if ((rc = pci_write_config_byte(dev, 0x46, via_config & ~flush)))
+			errors++;
+	} else {
+		if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush)))
+			errors++;
 	}
-        if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush))) {
-		errors++;
-		goto via_error;
+
+	if (!hwif->dma_base)
+		printk("Config %s. No DMA Enabled\n",
+			errors ? "ERROR":"Success");
+	else
+		printk("(U)DMA Timing Config %s\n",
+			errors ? "ERROR" : "Success");
+}
+
+/*
+ *  Sets VIA 82c586 FIFO configuration:
+ *  This chipsets gets a splitable fifo. This can be driven either by command
+ *  line option (eg "splitfifo=2,2,3" which asks this driver to switch all the 
+ *  16 fifo levels to the second drive, and give it a threshold of 3 for (u)dma 
+ *  triggering.
+ */
+
+static int via_set_fifoconfig(ide_hwif_t *hwif)
+{
+	byte fifo;
+	unsigned int timings;
+	struct pci_dev  *dev = hwif->pci_dev;
+
+	/* read port configuration */
+	if (pci_read_config_dword(dev, 0x40, &timings))
+		return 1;
+   
+	/* first read actual fifo config: */
+	if (pci_read_config_byte(dev, 0x43, &fifo))
+		return 1;
+
+	/* keep 4 and 7 bit as they seem to differ between chipsets flavors... */
+	newfifo = fifo & 0x90;
+
+	if (fifoconfig) {
+		/* we received a config request from kernel command line: */
+		newfifo |= fifoconfig & 0x6f;
+	} else {
+		/* If ever just one channel is unused, allocate all fifo levels to it
+		 * and give it a 3/4 threshold for (u)dma transfers.
+		 * Otherwise, share it evenly between channels:
+		 */
+		if ((timings & 3) == 2) {
+			/* only primary channel is  enabled
+			 * 16 buf. to prim. chan. thresh=3/4
+			 */
+			newfifo |= 0x06;
+		} else if ((timings & 3) == 1) {
+			/* only secondary channel is enabled!
+			 * 16 buffers to sec. ch. thresh=3/4
+			 */
+			newfifo |= 0x69;
+		} else {
+			/* fifo evenly distributed: */
+			newfifo |= 0x2a;
+		}
 	}
 
-via_error:
-	printk("(U)DMA Timing Config %s\n", errors ? "ERROR" : "Success");
+	/* write resulting configuration to chipset: */
+	if (pci_write_config_byte(dev, 0x43, newfifo))
+		return 1;
+
+	/* and then reread it to get the actual one */
+	if (pci_read_config_byte(dev, 0x43, &newfifo))
+		return 1;
+
+	/* print a kernel report: */
+	printk("Split FIFO Configuration: %s Primary buffers, threshold = %s\n",
+		((newfifo & 0x60) == 0x60)	? " 0" :
+		((newfifo & 0x60)		? " 8" : "16"),
+		!(newfifo & 0x0c)		? "1" :
+		(!(newfifo & 0x08)		? "3/4" :
+		(newfifo & 0x04)		? "1/4" : "1/2"));
+
+	printk("                          %s Second. buffers, threshold = %s\n",
+		((newfifo & 0x60) == 0x60)	? "16" :
+		((newfifo & 0x60)		? " 8" : " 0"),
+		!(newfifo & 0x03)		? "1" :
+		(!(newfifo & 0x02)		? "3/4" :
+		(newfifo & 0x01)		? "1/4" : "1/2"));
+
+#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
+	bmide_dev = hwif->pci_dev;
+	via_display_info = &via_get_info;
+#endif /* DISPLAY_VIA_TIMINGS &&  CONFIG_PROC_FS*/
+	return 0;
+}
+
+__initfunc(unsigned int pci_init_via82c568 (struct pci_dev *dev, const char *name))
+{
+	struct pci_dev *host;
+	struct pci_dev *isa;
+
+	byte revision = 0;
+
+	for (host = pci_devices; host; host=host->next) {
+		if (host->vendor == PCI_VENDOR_ID_VIA &&
+		    host->device == PCI_DEVICE_ID_VIA_82C585) {
+			host_dev = host;
+			printk("VT 82C585 Apollo VP1/VPX");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+					isa_dev = isa;
+					pci_read_config_byte(isa_dev, 0x0d, &revision);
+					if (revision >= 0x20)
+						printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+		} else if (host->vendor == PCI_VENDOR_ID_VIA &&
+			   host->device == PCI_DEVICE_ID_VIA_82C595) {
+			host_dev = host;
+			printk("VT 82C595 Apollo VP2");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+					isa_dev = isa;
+					pci_read_config_byte(isa_dev, 0x0d, &revision);
+					if (revision >= 0x20)
+						printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+		} else if (host->vendor == PCI_VENDOR_ID_VIA &&
+			   host->device == PCI_DEVICE_ID_VIA_82C597_0) {
+			host_dev = host;
+			printk("VT 82C597 Apollo VP3");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+					isa_dev = isa;
+					pci_read_config_byte(isa_dev, 0x0d, &revision);
+					if (revision >= 0x20)
+						printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+	} else if (host->vendor == PCI_VENDOR_ID_VIA &&
+		   host->device == PCI_DEVICE_ID_VIA_82C598_0) {
+			host_dev = host;
+			printk("VT 82C598 Apollo MVP3");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+					isa_dev = isa;
+					pci_read_config_byte(isa_dev, 0x0d, &revision);
+					if (revision >= 0x20)
+						printk(" Chipset Core ATA-33");
+					break;
+				} else if (isa->vendor == PCI_VENDOR_ID_VIA &&
+					   isa->device == PCI_DEVICE_ID_VIA_82C596) {
+					isa_dev = isa;
+					printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+	} else if (host->vendor == PCI_VENDOR_ID_VIA &&
+		   host->device == PCI_DEVICE_ID_VIA_82C680) {
+			host_dev = host;
+			printk("VT 82C680 Apollo P6");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C586_1) {
+					isa_dev = isa;
+					pci_read_config_byte(isa_dev, 0x0d, &revision);
+					if (revision >= 0x20)
+						printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+	} else if (host->vendor == PCI_VENDOR_ID_VIA &&
+		   host->device == PCI_DEVICE_ID_VIA_82C691) {
+			host_dev = host;
+			printk("VT 82C691 Apollo Pro");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C596) {
+					isa_dev = isa;
+					printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+	} else if (host->vendor == PCI_VENDOR_ID_VIA &&
+		   host->device == PCI_DEVICE_ID_VIA_82C693) {
+			host_dev = host;
+			printk("VT 82C693 Apollo Pro Plus");
+			for (isa = pci_devices; isa; isa=isa->next) {
+				if (isa->vendor == PCI_VENDOR_ID_VIA &&
+				    isa->device == PCI_DEVICE_ID_VIA_82C596) {
+					isa_dev = isa;
+					printk(" Chipset Core ATA-33");
+					break;
+				}
+			}
+			printk("\n");
+			break;
+		}
+	}
+	return 0;
 }
 
-void ide_init_via82c586 (ide_hwif_t *hwif)
+__initfunc(void ide_init_via82c586 (ide_hwif_t *hwif))
 {
 	set_via_timings(hwif);
 }
 
+/*
+ *  ide_dmacapable_via82c568(ide_hwif_t *, unsigned long)
+ *  checks if channel "channel" of if hwif is dma
+ *  capable or not, according to kernel command line,
+ *  and the new fifo settings.
+ *  It calls "ide_setup_dma" on capable mainboards, and
+ *  bypasses the setup if not capable.
+ */
+
+void ide_dmacapable_via82c586 (ide_hwif_t *hwif, unsigned long dmabase)
+{
+	if (!done) {
+		via_set_fifoconfig(hwif);
+		done = 1;
+	}
+
+	/*
+	 * check if any fifo is available for requested port:
+	 */
+	if (((hwif->channel == 0) && ((newfifo & 0x60) == 0x60)) ||
+	    ((hwif->channel == 1) && ((newfifo & 0x60) == 0x00))) {
+		printk("    %s: VP_IDE Bus-Master DMA disabled (FIFO setting)\n", hwif->name);
+	} else {
+		ide_setup_dma(hwif, dmabase, 8);
+	}
+}
diff -urN linux-2.2.10-pristine/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- linux-2.2.10-pristine/drivers/pci/oldproc.c	Tue Jul 20 19:11:57 1999
+++ linux/drivers/pci/oldproc.c	Thu Jul 22 20:38:43 1999
@@ -163,13 +163,16 @@
 	DEVICE( SI,		SI_6205,	"6205"),
 	DEVICE( SI,		SI_501,		"85C501"),
 	DEVICE( SI,		SI_496,		"85C496"),
+	DEVICE(	SI,		SI_530,		"530 Host"),
 	DEVICE( SI,		SI_601,		"85C601"),
+	DEVICE(	SI,		SI_620,		"620 Host"),
 	DEVICE( SI,		SI_5107,	"5107"),
 	DEVICE( SI,		SI_5511,       	"85C5511"),
 	DEVICE( SI,		SI_5513,	"85C5513"),
 	DEVICE( SI,		SI_5571,	"5571"),
 	DEVICE( SI,		SI_5591,	"5591/5592 Host"),
 	DEVICE( SI,		SI_5597,	"5597/5598 Host"),
+	DEVICE(	SI,		SI_6306,	"3D-AGP VGA"),
 	DEVICE( SI,		SI_7001,	"7001 USB"),
 	DEVICE( HP,		HP_J2585A,	"J2585A"),
 	DEVICE( HP,		HP_J2585B,	"J2585B (Lassen)"),
@@ -206,6 +209,7 @@
 	DEVICE( MOTOROLA,	MOTOROLA_FALCON,"Falcon"),
 	DEVICE( MOTOROLA,	MOTOROLA_CPX8216,"CPX8216"),
 	DEVICE( PROMISE,        PROMISE_20246,	"IDE UltraDMA/33"),
+	DEVICE(	PROMISE,	PROMISE_20262,	"IDE UltraDMA/66"),
 	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
 	DEVICE( N9,		N9_I128,	"Imagine 128"),
 	DEVICE( N9,		N9_I128_2,	"Imagine 128v2"),
@@ -293,11 +297,15 @@
 	DEVICE( AL,		AL_M1523,	"M1523"),
 	DEVICE( AL,		AL_M1531,	"M1531 Aladdin IV"),
 	DEVICE( AL,		AL_M1533,	"M1533 Aladdin IV"),
+	DEVICE(	AL,		AL_M1541,	"M1541 Aladdin V"),
+	DEVICE(	AL,		AL_M1543,	"M1543 Aladdin V"),
 	DEVICE( AL,		AL_M3307,	"M3307 MPEG-1 decoder"),
 	DEVICE( AL,		AL_M4803,	"M4803"),
 	DEVICE( AL,		AL_M5219,	"M5219"),
 	DEVICE( AL,		AL_M5229,	"M5229 TXpro"),
 	DEVICE( AL,		AL_M5237,	"M5237 USB"),
+	DEVICE(	AL,		AL_M5243,	"M5243 AGP"),
+	DEVICE(	AL,		AL_M7101,	"M7101 PMU"),
 	DEVICE( SURECOM,	SURECOM_NE34,	"NE-34PCI LAN"),
 	DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
 	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
@@ -327,7 +335,8 @@
 	DEVICE( TRUEVISION,	TRUEVISION_T1000,"TARGA 1000"),
 	DEVICE( INIT,		INIT_320P,	"320 P"),
 	DEVICE( INIT,		INIT_360P,	"360 P"),
-	DEVICE(	TTI,		TTI_HPT343,	"HPT343"),
+	DEVICE(	TTI,		TTI_HPT343,	"HPT343 IDE UltraDMA/33"),
+	DEVICE(	TTI,		TTI_HPT366,	"HPT366 IDE UltraDMA/66"),
 	DEVICE( VIA,		VIA_82C505,	"VT 82C505"),
 	DEVICE( VIA,		VIA_82C561,	"VT 82C561"),
 	DEVICE( VIA,		VIA_82C586_1,	"VT 82C586 Apollo IDE"),
@@ -335,13 +344,21 @@
 	DEVICE( VIA,		VIA_82C585,	"VT 82C585 Apollo VP1/VPX"),
 	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo ISA"),
 	DEVICE( VIA,		VIA_82C595,	"VT 82C595 Apollo VP2"),
+	DEVICE(	VIA,		VIA_82C596,	"VT 82C596 Apollo Mobile"),
 	DEVICE( VIA,		VIA_82C597_0,	"VT 82C597 Apollo VP3"),
 	DEVICE( VIA,		VIA_82C598_0,	"VT 82C598 Apollo MVP3"),
+	DEVICE(	VIA,		VIA_82C680,	"VT 82C680 Apollo P6"),
+	DEVICE(	VIA,		VIA_82C686,	"VT 82C686 Apollo Super"),
+	DEVICE(	VIA,		VIA_82C691,	"VT 82C691 Apollo Pro"),
+	DEVICE(	VIA,		VIA_82C693,	"VT 82C693 Apollo Pro Plus"),
 	DEVICE( VIA,		VIA_82C926,	"VT 82C926 Amazon"),
 	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV"),
 	DEVICE( VIA,		VIA_82C595_97,	"VT 82C595 Apollo VP2/97"),
 	DEVICE( VIA,		VIA_82C586_2,	"VT 82C586 Apollo USB"),
 	DEVICE( VIA,		VIA_82C586_3,	"VT 82C586B Apollo ACPI"),
+	DEVICE(	VIA,		VIA_82C686_4,	"VT 82C686 Apollo Super ACPI"),
+	DEVICE(	VIA,		VIA_82C686_5,	"VT 82C686 Apollo Super AC97/Audio"),
+	DEVICE(	VIA,		VIA_82C686_6,	"VT 82C686 Apollo Super AC97/Modem"),
 	DEVICE( VIA,		VIA_86C100A,	"VT 86C100A"),
 	DEVICE( VIA,		VIA_82C597_1,	"VT 82C597 Apollo VP3 AGP"),
 	DEVICE( VIA,		VIA_82C598_1,	"VT 82C598 Apollo MVP3 AGP"),
@@ -457,6 +474,7 @@
 	DEVICE( OPTIBASE,	OPTIBASE_VPLEX,	"VideoPlex"),
 	DEVICE( OPTIBASE,	OPTIBASE_VPLEXCC,"VideoPlex CC"),
 	DEVICE( OPTIBASE,	OPTIBASE_VQUEST,"VideoQuest"),
+	DEVICE(	ESS,		ESS_AUDIOPCI,	"3D Audio 1969"),
 	DEVICE( SATSAGEM,	SATSAGEM_PCR2101,"PCR2101 DVB receiver"),
 	DEVICE( SATSAGEM,	SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"),
 	DEVICE( HUGHES,		HUGHES_DIRECPC,	"DirecPC"),
@@ -812,6 +830,7 @@
 	      case PCI_VENDOR_ID_DIPIX:		return "Dipix";
 	      case PCI_VENDOR_ID_STALLION:	return "Stallion Technologies";
 	      case PCI_VENDOR_ID_OPTIBASE:	return "Optibase";
+	      case PCI_VENDOR_ID_ESS:		return "ESS Technologies";
 	      case PCI_VENDOR_ID_SATSAGEM:	return "SatSagem";
 	      case PCI_VENDOR_ID_HUGHES:	return "Hughes";
 	      case PCI_VENDOR_ID_ENSONIQ:	return "Ensoniq";
diff -urN linux-2.2.10-pristine/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- linux-2.2.10-pristine/drivers/scsi/ide-scsi.c	Tue Jul 20 19:11:53 1999
+++ linux/drivers/scsi/ide-scsi.c	Thu Jul 22 20:38:43 1999
@@ -45,7 +45,7 @@
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
-#include "../block/ide.h"
+#include <linux/ide.h>
 
 #include "scsi.h"
 #include "hosts.h"
diff -urN linux-2.2.10-pristine/include/asm-alpha/hdreg.h linux/include/asm-alpha/hdreg.h
--- linux-2.2.10-pristine/include/asm-alpha/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-alpha/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,12 @@
+/*
+ *  linux/include/asm-alpha/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMalpha_HDREG_H
+#define __ASMalpha_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASMalpha_HDREG_H */
diff -urN linux-2.2.10-pristine/include/asm-alpha/ide.h linux/include/asm-alpha/ide.h
--- linux-2.2.10-pristine/include/asm-alpha/ide.h	Tue Jul 20 19:11:31 1999
+++ linux/include/asm-alpha/ide.h	Thu Jul 22 20:38:43 1999
@@ -13,7 +13,7 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned short ide_ioreg_t;
+#include <asm/hdreg.h>
 
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	4
@@ -45,18 +45,42 @@
 	}
 }
 
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
 
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for (index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
@@ -68,51 +92,19 @@
 	} b;
 	} select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.2.10-pristine/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- linux-2.2.10-pristine/include/asm-alpha/io.h	Tue Jul 20 19:11:31 1999
+++ linux/include/asm-alpha/io.h	Thu Jul 22 20:38:43 1999
@@ -357,6 +357,12 @@
 #endif
 #define RTC_ALWAYS_BCD	0
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif /* __ALPHA_IO_H */
diff -urN linux-2.2.10-pristine/include/asm-arm/arch-arc/ide.h linux/include/asm-arm/arch-arc/ide.h
--- linux-2.2.10-pristine/include/asm-arm/arch-arc/ide.h	Tue Jul 20 19:11:38 1999
+++ linux/include/asm-arm/arch-arc/ide.h	Thu Jul 22 20:38:43 1999
@@ -14,38 +14,38 @@
 
 #include <linux/config.h>
 #include <asm/irq.h>
+#include <asm/hdreg.h>
 
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = (ide_ioreg_t) data_port;
 	int i;
 
-	memset(hw, 0, sizeof(*hw));
-
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
 		reg += 1;
 	}
 	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-	hw->irq = irq;
+	hw->irq = *irq;
 }
 
 /*
  * This registers the standard ports for this architecture with the IDE
  * driver.
  */
-static __inline__ void
-ide_init_default_hwifs(void)
+static __inline__ void ide_init_default_hwifs(void)
 {
 #ifdef CONFIG_ARCH_A5K
 	hw_regs_t hw;
 
-	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+        memset(hw, 0, sizeof(*hw));
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+	hw.irq = IRQ_HARDDISK;
 	ide_register_hw(&hw, NULL);
 #endif
 }
diff -urN linux-2.2.10-pristine/include/asm-arm/arch-ebsa285/ide.h linux/include/asm-arm/arch-ebsa285/ide.h
--- linux-2.2.10-pristine/include/asm-arm/arch-ebsa285/ide.h	Tue Jul 20 19:11:38 1999
+++ linux/include/asm-arm/arch-ebsa285/ide.h	Thu Jul 22 20:38:43 1999
@@ -7,32 +7,38 @@
  *  29-07-1998	RMK	Major re-work of IDE architecture specific code
  */
 #include <asm/irq.h>
+#include <asm/hdreg.h>
 
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = (ide_ioreg_t) data_port;
 	int i;
 
-	memset(hw, 0, sizeof(*hw));
-
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
 		reg += 1;
 	}
 	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-	hw->irq = irq;
+	hw->irq = *irq;
 }
 
 /*
  * This registers the standard ports for this architecture with the IDE
  * driver.
  */
-static __inline__ void
-ide_init_default_hwifs(void)
+static __inline__ void ide_init_default_hwifs(void)
 {
+#if 0
+	hw_regs_t hw;
+
+	memset(hw, 0, sizeof(*hw));
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+	hw.irq = IRQ_HARDDISK;
+	ide_register_hw(&hw, NULL);
+#endif
 }
diff -urN linux-2.2.10-pristine/include/asm-arm/arch-rpc/ide.h linux/include/asm-arm/arch-rpc/ide.h
--- linux-2.2.10-pristine/include/asm-arm/arch-rpc/ide.h	Tue Jul 20 19:11:38 1999
+++ linux/include/asm-arm/arch-rpc/ide.h	Thu Jul 22 20:38:43 1999
@@ -7,36 +7,36 @@
  *  29-07-1998	RMK	Major re-work of IDE architecture specific code
  */
 #include <asm/irq.h>
+#include <asm/hdreg.h>
 
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = (ide_ioreg_t) data_port;
 	int i;
 
-	memset(hw, 0, sizeof(*hw));
-
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
 		reg += 1;
 	}
 	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-	hw->irq = irq;
+	hw->irq = *irq;
 }
 
 /*
  * This registers the standard ports for this architecture with the IDE
  * driver.
  */
-static __inline__ void
-ide_init_default_hwifs(void)
+static __inline__ void ide_init_default_hwifs(void)
 {
 	hw_regs_t hw;
 
-	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+        memset(hw, 0, sizeof(*hw));
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+	hw.irq = IRQ_HARDDISK;
 	ide_register_hw(&hw, NULL);
 }
diff -urN linux-2.2.10-pristine/include/asm-arm/hdreg.h linux/include/asm-arm/hdreg.h
--- linux-2.2.10-pristine/include/asm-arm/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-arm/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-arm/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMARM_HDREG_H
+#define __ASMARM_HDREG_H
+
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __ASMARM_HDREG_H */
+
diff -urN linux-2.2.10-pristine/include/asm-arm/ide.h linux/include/asm-arm/ide.h
--- linux-2.2.10-pristine/include/asm-arm/ide.h	Tue Jul 20 19:11:38 1999
+++ linux/include/asm-arm/ide.h	Thu Jul 22 20:38:43 1999
@@ -13,14 +13,14 @@
 
 #ifdef __KERNEL__
 
+#include <asm/hdreg.h>
+
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	4
 #endif
 
 #define ide__sti()	__sti()
 
-#include <asm/arch/ide.h>
-
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
@@ -48,4 +48,4 @@
 
 #endif /* __KERNEL__ */
 
-#endif /* __ASMi386_IDE_H */
+#endif /* __ASMARM_IDE_H */
diff -urN linux-2.2.10-pristine/include/asm-arm/io.h linux/include/asm-arm/io.h
--- linux-2.2.10-pristine/include/asm-arm/io.h	Tue Jul 20 19:11:38 1999
+++ linux/include/asm-arm/io.h	Thu Jul 22 20:38:43 1999
@@ -189,10 +189,21 @@
 #define inl_p(port) __inl_p((port))
 #endif
 
-#endif
+/* Nothing to do */
 
+#ifndef dma_cache_inv
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#endif
+#ifndef dma_cache_wback
+#define dma_cache_wback(_start,_size)		do { } while (0)
 #ifndef ARCH_READWRITE
+#ifndef dma_cache_wback_inv
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+#endif
+
+#endif /* __KERNEL__ */
 
+#endif /* __ASM_ARM_IO_H */
 /* for panic */
 #include <linux/kernel.h>
 
diff -urN linux-2.2.10-pristine/include/asm-i386/hdreg.h linux/include/asm-i386/hdreg.h
--- linux-2.2.10-pristine/include/asm-i386/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-i386/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,12 @@
+/*
+ *  linux/include/asm-i386/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMi386_HDREG_H
+#define __ASMi386_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASMi386_HDREG_H */
diff -urN linux-2.2.10-pristine/include/asm-i386/ide.h linux/include/asm-i386/ide.h
--- linux-2.2.10-pristine/include/asm-i386/ide.h	Tue Jul 20 19:11:31 1999
+++ linux/include/asm-i386/ide.h	Thu Jul 22 20:38:43 1999
@@ -13,10 +13,10 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned short ide_ioreg_t;
+#include <asm/hdreg.h>
 
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	6
+#define MAX_HWIFS	8
 #endif
 
 #define ide__sti()	__sti()
@@ -49,18 +49,38 @@
 	}
 }
 
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
 
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
@@ -72,51 +92,19 @@
 	} b;
 	} select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.2.10-pristine/include/asm-i386/io.h linux/include/asm-i386/io.h
--- linux-2.2.10-pristine/include/asm-i386/io.h	Tue Jul 20 19:11:30 1999
+++ linux/include/asm-i386/io.h	Thu Jul 22 20:38:43 1999
@@ -183,6 +183,12 @@
 	return retval;
 }
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif
diff -urN linux-2.2.10-pristine/include/asm-m68k/hdreg.h linux/include/asm-m68k/hdreg.h
--- linux-2.2.10-pristine/include/asm-m68k/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-m68k/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-m68k/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef _M68K_HDREG_H
+#define _M68K_HDREG_H
+
+typedef unsigned int   q40ide_ioreg_t;
+typedef unsigned char * ide_ioreg_t;
+
+#endif /* _M68K_HDREG_H */
diff -urN linux-2.2.10-pristine/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
--- linux-2.2.10-pristine/include/asm-m68k/ide.h	Tue Jul 20 19:11:32 1999
+++ linux/include/asm-m68k/ide.h	Thu Jul 22 20:38:43 1999
@@ -45,12 +45,7 @@
 #include <asm/macints.h>
 #endif
 
-
-typedef unsigned int   q40ide_ioreg_t;
-
-
-typedef unsigned char * ide_ioreg_t;
-
+#include <asm/hdreg.h>
 
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	4	/* same as the other archs */
@@ -65,19 +60,39 @@
 	else return 0;
 }
 
+int q40ide_default_io_base(int);
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+	if (MACH_IS_Q40)
+		return q40ide_default_io_base(index);
+	else return 0;
+}
 
 /*
  *  Can we do this in a generic manner??
  */
-void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq);
+void q40_ide_init_hwif_ports (hw_regs_t *hw, q40ide_ioreg_t data_port, q40ide_ioreg_t ctrl_port, int *irq);
 
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 #ifdef CONFIG_Q40
-    if (MACH_IS_Q40)
-      return q40_ide_init_hwif_ports((q40ide_ioreg_t *)p,(q40ide_ioreg_t)base,irq);
+	if (MACH_IS_Q40)
+		return q40_ide_init_hwif_ports(hw, (q40ide_ioreg_t) data_port, (q40ide_ioreg_t) ctrl_port, irq);
 #endif
-    printk("ide_init_hwif_ports: must not be called\n");
+	printk("ide_init_hwif_ports: must not be called\n");
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
 }
 
 typedef union {
@@ -487,7 +502,7 @@
 #endif /* CONFIG_ATARI */
 }
 
-#define ide_ack_intr(hwif)	((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
+#define ide_ack_intr(hwif)	((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
 
 /*
  * On the Atari, we sometimes can't enable interrupts:
diff -urN linux-2.2.10-pristine/include/asm-m68k/io.h linux/include/asm-m68k/io.h
--- linux-2.2.10-pristine/include/asm-m68k/io.h	Tue Jul 20 19:11:31 1999
+++ linux/include/asm-m68k/io.h	Thu Jul 22 20:38:43 1999
@@ -72,6 +72,12 @@
 
 extern void iounmap(void *addr);
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_IO_H */
diff -urN linux-2.2.10-pristine/include/asm-mips/hdreg.h linux/include/asm-mips/hdreg.h
--- linux-2.2.10-pristine/include/asm-mips/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-mips/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,18 @@
+/* $Id: hdreg.h,v 1.4 1998/05/08 21:05:26 davem Exp $
+ *
+ *  linux/include/asm-mips/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the MIPS architecture specific IDE code.
+ */
+
+#ifndef __ASM_MIPS_HDREG_H
+#define __ASM_MIPS_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASM_MIPS_HDREG_H */
+
diff -urN linux-2.2.10-pristine/include/asm-mips/ide.h linux/include/asm-mips/ide.h
--- linux-2.2.10-pristine/include/asm-mips/ide.h	Tue Jul 20 19:11:31 1999
+++ linux/include/asm-mips/ide.h	Thu Jul 22 20:38:43 1999
@@ -14,7 +14,7 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned short ide_ioreg_t;
+#include <asm/hdreg.h>
 
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	6
@@ -25,7 +25,7 @@
 struct ide_ops {
 	int (*ide_default_irq)(ide_ioreg_t base);
 	ide_ioreg_t (*ide_default_io_base)(int index);
-	void (*ide_init_hwif_ports)(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+	void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
 	int (*ide_request_irq)(unsigned int irq, void (*handler)(int, void *,
 	                       struct pt_regs *), unsigned long flags,
 	                       const char *device, void *dev_id);
@@ -48,10 +48,29 @@
 	return ide_ops->ide_default_io_base(index);
 }
 
-static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
-                                           int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ops->ide_init_hwif_ports(p, base, irq);
+	ide_ops->ide_init_hwif_ports(hw->io_ports, data_port, ctrl_port, &hw->irq);
+
+	hw->irq = ide_ops->ide_default_irq(data_port);
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for (index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
 }
 
 typedef union {
@@ -96,26 +115,10 @@
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port,
-                                    ide_ioreg_t irq_port)
-{
-	return 1;
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock,
-                                     void (*handler)(int, void *,
-                                                    struct pt_regs *),
-                                     void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.2.10-pristine/include/asm-mips/io.h linux/include/asm-mips/io.h
--- linux-2.2.10-pristine/include/asm-mips/io.h	Tue Jul 20 19:11:31 1999
+++ linux/include/asm-mips/io.h	Thu Jul 22 20:38:43 1999
@@ -389,4 +389,8 @@
 extern void (*dma_cache_wback_inv)(unsigned long start, unsigned long size);
 extern void (*dma_cache_inv)(unsigned long start, unsigned long size);
 
+/* Nothing to do */
+
+#define dma_cache_wback(_start,_size)		do { } while (0)
+
 #endif /* __ASM_MIPS_IO_H */
diff -urN linux-2.2.10-pristine/include/asm-ppc/hdreg.h linux/include/asm-ppc/hdreg.h
--- linux-2.2.10-pristine/include/asm-ppc/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-ppc/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,17 @@
+/*
+ *  linux/include/asm-ppc/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the ppc architecture specific IDE code.
+ */
+
+#ifndef __ASMPPC_HDREG_H
+#define __ASMPPC_HDREG_H
+
+typedef unsigned int ide_ioreg_t;
+
+#endif /* __ASMPPC_HDREG_H */
+
diff -urN linux-2.2.10-pristine/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- linux-2.2.10-pristine/include/asm-ppc/ide.h	Tue Jul 20 19:11:37 1999
+++ linux/include/asm-ppc/ide.h	Thu Jul 22 20:38:43 1999
@@ -18,7 +18,7 @@
 #define MAX_HWIFS	4
 #endif
 
-typedef unsigned int ide_ioreg_t;
+#include <asm/hdreg.h>
 
 #ifdef __KERNEL__
 
@@ -49,16 +49,20 @@
         void        (*release_region)(ide_ioreg_t from,
                                       unsigned int extent);
         void        (*fix_driveid)(struct hd_driveid *id);
-        void        (*ide_init_hwif)(ide_ioreg_t *p,
-                                     ide_ioreg_t base,
-                                     int *irq); 
+        void        (*ide_init_hwif)(hw_regs_t *hw,
+                                     ide_ioreg_t data_port,
+                                     ide_ioreg_t ctrl_port,
+                                     int *irq);
 
         int io_base;
 };
 
 extern struct ide_machdep_calls ppc_ide_md;
 
-void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+#if 0
+void ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
+#endif
+
 void ide_insw(ide_ioreg_t port, void *buf, int ns);
 void ide_outsw(ide_ioreg_t port, void *buf, int ns);
 void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
@@ -90,6 +94,20 @@
 	return ppc_ide_md.default_io_base(index);
 }
 
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
 {
 	return ppc_ide_md.check_region(from, extent);
@@ -105,7 +123,8 @@
 	ppc_ide_md.release_region(from, extent);
 }
 
-static __inline__ void ide_fix_driveid (struct hd_driveid *id) {
+static __inline__ void ide_fix_driveid (struct hd_driveid *id)
+{
         ppc_ide_md.fix_driveid(id);
 }
 
@@ -131,21 +150,13 @@
 	} b;
 } select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-#define ide_ack_intr(base, irq)		(1)
+#define ide_ack_intr(hwif)		(1)
 #define ide_release_lock(lock)		do {} while (0)
 #define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
diff -urN linux-2.2.10-pristine/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- linux-2.2.10-pristine/include/asm-ppc/io.h	Tue Jul 20 19:11:37 1999
+++ linux/include/asm-ppc/io.h	Thu Jul 22 20:38:43 1999
@@ -277,6 +277,13 @@
 out:
 	return retval;
 }
+
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif
diff -urN linux-2.2.10-pristine/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- linux-2.2.10-pristine/include/asm-sparc/io.h	Tue Jul 20 19:11:34 1999
+++ linux/include/asm-sparc/io.h	Thu Jul 22 20:38:43 1999
@@ -162,4 +162,10 @@
 #define virt_to_phys(x) __pa((unsigned long)(x))
 #define phys_to_virt(x) __va((unsigned long)(x))
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* !(__SPARC_IO_H) */
diff -urN linux-2.2.10-pristine/include/asm-sparc64/hdreg.h linux/include/asm-sparc64/hdreg.h
--- linux-2.2.10-pristine/include/asm-sparc64/hdreg.h	Wed Dec 31 18:00:00 1969
+++ linux/include/asm-sparc64/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,13 @@
+/* $Id: hdreg.h,v 1.9 1998/05/08 21:05:28 davem Exp $
+ * hdreg.h: Ultra/PCI specific IDE glue.
+ *
+ * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998  Eddie C. Dost   (ecd@skynet.be)
+ */
+
+#ifndef __SPARC64_HDREG_H
+#define __SPARC64_HDREG_H
+
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __SPARC64_HDREG_H */
diff -urN linux-2.2.10-pristine/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- linux-2.2.10-pristine/include/asm-sparc64/ide.h	Tue Jul 20 19:11:37 1999
+++ linux/include/asm-sparc64/ide.h	Thu Jul 22 20:38:43 1999
@@ -11,8 +11,7 @@
 #ifdef __KERNEL__
 
 #include <asm/pgtable.h>
-
-typedef unsigned long ide_ioreg_t;
+#include <asm/hdreg.h>
 
 #undef  MAX_HWIFS
 #define MAX_HWIFS	2
@@ -29,21 +28,42 @@
 	return 0;
 }
 
-static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
+	ide_ioreg_t reg =  data_port;
 	int i;
 
-	/* These are simply offsets from base. */
-	for (i = 0; i < 8; i++)
-		*p++ = base++;
-	/* PCI code needs to figure out these. */
-	for ( ; i < 10; i++)
-		*p++ = 0;
-	/* PCI code needs to figure out this. */
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
 
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for (index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 typedef union {
 	unsigned int		all	: 8;	/* all of the bits together */
 	struct {
@@ -92,11 +112,6 @@
 #undef  HD_DATA
 #define HD_DATA ((ide_ioreg_t)0)
 
-static __inline__ int ide_ack_intr(ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return 1;
-}
-
 /* From m68k code... */
 
 #ifdef insl
@@ -255,13 +270,12 @@
 	}
 }
 
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif)		(1)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.2.10-pristine/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- linux-2.2.10-pristine/include/asm-sparc64/io.h	Tue Jul 20 19:11:37 1999
+++ linux/include/asm-sparc64/io.h	Thu Jul 22 20:38:43 1999
@@ -226,4 +226,10 @@
 extern void sparc_free_io (void *va, int sz);
 extern void *sparc_dvma_malloc (int sz, char *name, __u32 *dvma_addr);
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* !(__SPARC64_IO_H) */
diff -urN linux-2.2.10-pristine/include/linux/hdreg.h linux/include/linux/hdreg.h
--- linux-2.2.10-pristine/include/linux/hdreg.h	Tue Jul 20 19:11:29 1999
+++ linux/include/linux/hdreg.h	Thu Jul 22 20:38:43 1999
@@ -93,7 +93,43 @@
 #define SMART_STATUS		0xda
 #define SMART_AUTO_OFFLINE	0xdb
 
+/* WIN_SETFEATURES sub-commands */
+
+#define SETFEATURES_EN_WCACHE	0x02	/* Enable write cache */
+#define SETFEATURES_XFER	0x03	/* Set transfer mode */
+#	define XFER_UDMA_4	0x44	/* 0100|0100 */
+#	define XFER_UDMA_3	0x43	/* 0100|0011 */
+#	define XFER_UDMA_2	0x42	/* 0100|0010 */
+#	define XFER_UDMA_1	0x41	/* 0100|0001 */
+#	define XFER_UDMA_0	0x40	/* 0100|0000 */
+#	define XFER_MW_DMA_2	0x22	/* 0010|0010 */
+#	define XFER_MW_DMA_1	0x21	/* 0010|0001 */
+#	define XFER_MW_DMA_0	0x20	/* 0010|0000 */
+#	define XFER_SW_DMA_2	0x12	/* 0001|0010 */
+#	define XFER_SW_DMA_1	0x11	/* 0001|0001 */
+#	define XFER_SW_DMA_0	0x10	/* 0001|0000 */
+#	define XFER_PIO_4	0x0C	/* 0000|1100 */
+#	define XFER_PIO_3	0x0B	/* 0000|1011 */
+#	define XFER_PIO_2	0x0A	/* 0000|1010 */
+#	define XFER_PIO_1	0x09	/* 0000|1001 */
+#	define XFER_PIO_0	0x08	/* 0000|1000 */
+#	define XFER_PIO_SLOW	0x00	/* 0000|0000 */
+#define SETFEATURES_EN_APM	0x05	/* Enable advanced power management */
+#define SETFEATURES_DIS_MSN	0x31	/* Disable Media Status Notification */
+#define SETFEATURES_DIS_RLA	0x55	/* Disable read look-ahead feature */
+#define SETFEATURES_EN_RI	0x5D	/* Enable release interrupt */
+#define SETFEATURES_EN_SI	0x5E	/* Enable SERVICE interrupt */
+#define SETFEATURES_DIS_RPOD	0x66	/* Disable reverting to power on defaults */
+#define SETFEATURES_DIS_WCACHE	0x82	/* Disable write cache */
+#define SETFEATURES_DIS_APM	0x85	/* Disable advanced power management */
+#define SETFEATURES_EN_MSN	0x95	/* Enable Media Status Notification */
+#define SETFEATURES_EN_RLA	0xAA	/* Enable read look-ahead feature */
+#define SETFEATURES_EN_RPOD	0xCC	/* Enable reverting to power on defaults */
+#define SETFEATURES_DIS_RI	0xDD	/* Disable release interrupt */
+#define SETFEATURES_DIS_SI	0xDE	/* Disable SERVICE interrupt */
+
 /* WIN_SECURITY sub-commands */
+
 #define SECURITY_SET_PASSWORD		0xBA	/* 0xF1 */
 #define SECURITY_UNLOCK			0xBB	/* 0xF2 */
 #define SECURITY_ERASE_PREPARE		0xBC	/* 0xF3 */
diff -urN linux-2.2.10-pristine/include/linux/hdsmart.h linux/include/linux/hdsmart.h
--- linux-2.2.10-pristine/include/linux/hdsmart.h	Wed Dec 31 18:00:00 1969
+++ linux/include/linux/hdsmart.h	Thu Jul 22 20:38:43 1999
@@ -0,0 +1,61 @@
+#ifndef _LINUX_HDSMART_H
+#define _LINUX_HDSMART_H
+
+/*
+ * This file contains some defines for the AT-hd-controller.
+ * Various sources.  
+ */
+
+#define NR_ATTRIBUTES	30
+
+typedef struct threshold_s {
+	unsigned char	id;
+	unsigned char	threshold;
+	unsigned char	reserved[10];
+} __attribute__ ((packed)) threshold_t;
+
+typedef struct thresholds_s {
+	unsigned short	revision;
+	threshold_t	thresholds[NR_ATTRIBUTES];
+	unsigned char	reserved[18];
+	unsigned char	vendor[131];
+	unsigned char	checksum;
+} __attribute__ ((packed)) thresholds_t;
+
+typedef struct value_s {
+	unsigned char	id;
+	unsigned short	status;
+	unsigned char	value;
+	unsigned char	vendor[8];
+} __attribute__ ((packed)) value_t;
+
+typedef struct values_s {
+	unsigned short	revision;
+	value_t		values[NR_ATTRIBUTES];
+	unsigned char	offline_status;
+	unsigned char	vendor1;
+	unsigned short	offline_timeout;
+	unsigned char	vendor2;
+	unsigned char	offline_capability;
+	unsigned short	smart_capability;
+	unsigned char	reserved[16];
+	unsigned char	vendor[125];
+	unsigned char	checksum;
+} __attribute__ ((packed)) values_t;
+
+#if !defined(__KERNEL__) || defined(_IDE_DISK_C)
+ 
+#define NR_OFFLINE_TEXTS	5
+struct {
+	unsigned char	value;
+	char		*text;
+} offline_status_text[NR_OFFLINE_TEXTS] = {
+	{ 0x00, "NeverStarted" },
+	{ 0x02, "Completed" },
+	{ 0x04, "Suspended" },
+	{ 0x05, "Aborted" },
+	{ 0x06, "Failed" }
+};
+#endif /* !defined(__KERNEL__) || defined(_IDE_DISK_C) */
+
+#endif	/* _LINUX_HDSMART_H */
diff -urN linux-2.2.10-pristine/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.2.10-pristine/include/linux/ide.h	Wed Dec 31 18:00:00 1969
+++ linux/include/linux/ide.h	Fri Jul 23 01:08:48 1999
@@ -0,0 +1,819 @@
+#ifndef _IDE_H
+#define _IDE_H
+/*
+ *  linux/drivers/block/ide.h
+ *
+ *  Copyright (C) 1994-1998  Linus Torvalds & authors
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/hdsmart.h>
+#include <linux/blkdev.h>
+#include <linux/proc_fs.h>
+#include <asm/hdreg.h>
+
+/*
+ * This is the multiple IDE interface driver, as evolved from hd.c.
+ * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
+ * There can be up to two drives per interface, as per the ATA-2 spec.
+ *
+ * Primary i/f:    ide0: major=3;  (hda)         minor=0; (hdb)         minor=64
+ * Secondary i/f:  ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
+ * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
+ * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
+ */
+
+/******************************************************************************
+ * IDE driver configuration options (play with these as desired):
+ *
+ * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
+ */
+#undef REALLY_FAST_IO			/* define if ide ports are perfect */
+#define INITIAL_MULT_COUNT	0	/* off=0; on=2,4,8,16,32, etc.. */
+
+#ifndef SUPPORT_SLOW_DATA_PORTS		/* 1 to support slow data ports */
+#define SUPPORT_SLOW_DATA_PORTS	1	/* 0 to reduce kernel size */
+#endif
+#ifndef SUPPORT_VLB_SYNC		/* 1 to support weird 32-bit chips */
+#define SUPPORT_VLB_SYNC	1	/* 0 to reduce kernel size */
+#endif
+#ifndef DISK_RECOVERY_TIME		/* off=0; on=access_delay_time */
+#define DISK_RECOVERY_TIME	0	/*  for hardware that needs it */
+#endif
+#ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
+#define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
+#endif
+#ifndef FAKE_FDISK_FOR_EZDRIVE		/* 1 to help linux fdisk with EZDRIVE */
+#define FAKE_FDISK_FOR_EZDRIVE 	1	/* 0 to reduce kernel size */
+#endif
+#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
+#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
+#endif
+
+#ifdef CONFIG_BLK_DEV_CMD640
+#if 0	/* change to 1 when debugging cmd640 problems */
+void cmd640_dump_regs (void);
+#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
+#endif
+#endif  /* CONFIG_BLK_DEV_CMD640 */
+
+/*
+ * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
+ */
+#define IDE_DRIVE_CMD		99	/* (magic) undef to reduce kernel size*/
+
+/*
+ *  "No user-serviceable parts" beyond this point  :)
+ *****************************************************************************/
+
+typedef unsigned char	byte;	/* used everywhere */
+
+/*
+ * Probably not wise to fiddle with these
+ */
+#define ERROR_MAX	8	/* Max read/write errors per sector */
+#define ERROR_RESET	3	/* Reset controller every 4th retry */
+#define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
+
+/*
+ * Ensure that various configuration flags have compatible settings
+ */
+#ifdef REALLY_SLOW_IO
+#undef REALLY_FAST_IO
+#endif
+
+#define HWIF(drive)		((ide_hwif_t *)((drive)->hwif))
+#define HWGROUP(drive)		((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
+
+/*
+ * Definitions for accessing IDE controller registers
+ */
+#define IDE_NR_PORTS		(10)
+
+#define IDE_DATA_OFFSET		(0)
+#define IDE_ERROR_OFFSET	(1)
+#define IDE_NSECTOR_OFFSET	(2)
+#define IDE_SECTOR_OFFSET	(3)
+#define IDE_LCYL_OFFSET		(4)
+#define IDE_HCYL_OFFSET		(5)
+#define IDE_SELECT_OFFSET	(6)
+#define IDE_STATUS_OFFSET	(7)
+#define IDE_CONTROL_OFFSET	(8)
+#define IDE_IRQ_OFFSET		(9)
+
+#define IDE_FEATURE_OFFSET	IDE_ERROR_OFFSET
+#define IDE_COMMAND_OFFSET	IDE_STATUS_OFFSET
+
+#define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
+#define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
+#define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
+#define IDE_SECTOR_REG		(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
+#define IDE_LCYL_REG		(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
+#define IDE_HCYL_REG		(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
+#define IDE_SELECT_REG		(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
+#define IDE_STATUS_REG		(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
+#define IDE_CONTROL_REG		(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
+#define IDE_IRQ_REG		(HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
+
+#define IDE_FEATURE_REG		IDE_ERROR_REG
+#define IDE_COMMAND_REG		IDE_STATUS_REG
+#define IDE_ALTSTATUS_REG	IDE_CONTROL_REG
+#define IDE_IREASON_REG		IDE_NSECTOR_REG
+#define IDE_BCOUNTL_REG		IDE_LCYL_REG
+#define IDE_BCOUNTH_REG		IDE_HCYL_REG
+
+#ifdef REALLY_FAST_IO
+#define OUT_BYTE(b,p)		outb((b),(p))
+#define IN_BYTE(p)		(byte)inb(p)
+#else
+#define OUT_BYTE(b,p)		outb_p((b),(p))
+#define IN_BYTE(p)		(byte)inb_p(p)
+#endif /* REALLY_FAST_IO */
+
+#define GET_ERR()		IN_BYTE(IDE_ERROR_REG)
+#define GET_STAT()		IN_BYTE(IDE_STATUS_REG)
+#define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
+#define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
+#define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
+#define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
+#define DRIVE_READY		(READY_STAT  | SEEK_STAT)
+#define DATA_READY		(DRQ_STAT)
+
+/*
+ * Some more useful definitions
+ */
+#define IDE_MAJOR_NAME	"ide"	/* the same for all i/f; see also genhd.c */
+#define MAJOR_NAME	IDE_MAJOR_NAME
+#define PARTN_BITS	6	/* number of minor dev bits for partitions */
+#define PARTN_MASK	((1<<PARTN_BITS)-1)	/* a useful bit mask */
+#define MAX_DRIVES	2	/* per interface; 2 assumed by lots of code */
+#define SECTOR_WORDS	(512 / 4)	/* number of 32bit words per sector */
+#define IDE_LARGE_SEEK(b1,b2,t)	(((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
+#define IDE_MIN(a,b)	((a)<(b) ? (a):(b))
+#define IDE_MAX(a,b)	((a)>(b) ? (a):(b))
+
+/*
+ * Timeouts for various operations:
+ */
+#define WAIT_DRQ	(5*HZ/100)	/* 50msec - spec allows up to 20ms */
+#ifdef CONFIG_APM
+#define WAIT_READY	(5*HZ)		/* 5sec - some laptops are very slow */
+#else
+#define WAIT_READY	(3*HZ/100)	/* 30msec - should be instantaneous */
+#endif /* CONFIG_APM */
+#define WAIT_PIDENTIFY	(10*HZ)	/* 10sec  - should be less than 3ms (?)
+				            if all ATAPI CD is closed at boot */
+#define WAIT_WORSTCASE	(30*HZ)	/* 30sec  - worst case when spinning up */
+#define WAIT_CMD	(10*HZ)	/* 10sec  - maximum wait for an IRQ to happen */
+#define WAIT_MIN_SLEEP	(2*HZ/100)	/* 20msec - minimum sleep time */
+
+#define SELECT_DRIVE(hwif,drive)				\
+{								\
+	if (hwif->selectproc)					\
+		hwif->selectproc(drive);			\
+	OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \
+}
+
+/*
+ * Check for an interrupt and acknowledge the interrupt status
+ */
+struct hwif_s;
+typedef int (ide_ack_intr_t)(struct hwif_s *);
+
+/*
+ * Structure to hold all information about the location of this port
+ */
+typedef struct hw_regs_s {
+	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
+	int		irq;			/* our irq number */
+	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
+	void		*priv;			/* interface specific data */
+} hw_regs_t;
+
+/*
+ * Register new hardware with ide
+ */
+int ide_register_hw(hw_regs_t *hw, struct hwif_s **hwifp);
+
+/*
+ * Set up hw_regs_t structure before calling ide_register_hw (optional)
+ */
+void ide_setup_ports(	hw_regs_t *hw,
+			ide_ioreg_t base,
+			int *offsets,
+			ide_ioreg_t ctrl,
+			ide_ioreg_t intr,
+			ide_ack_intr_t *ack_intr,
+			int irq);
+
+#include <asm/ide.h>
+
+/*
+ * Now for the data we need to maintain per-drive:  ide_drive_t
+ */
+
+#define ide_scsi	0x21
+#define ide_disk	0x20
+#define ide_optical	0x7
+#define ide_cdrom	0x5
+#define ide_tape	0x1
+#define ide_floppy	0x0
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned set_geometry	: 1;	/* respecify drive geometry */
+		unsigned recalibrate	: 1;	/* seek to cyl 0      */
+		unsigned set_multmode	: 1;	/* set multmode count */
+		unsigned set_tune	: 1;	/* tune interface for drive */
+		unsigned reserved	: 4;	/* unused */
+		} b;
+	} special_t;
+
+typedef struct ide_drive_s {
+	struct request		*queue;	/* request queue */
+	struct ide_drive_s 	*next;	/* circular list of hwgroup drives */
+	unsigned long sleep;		/* sleep until this time */
+	unsigned long service_start;	/* time we started last request */
+	unsigned long service_time;	/* service time of last request */
+	special_t	special;	/* special action flags */
+	byte     keep_settings;		/* restore settings after drive reset */
+	byte     using_dma;		/* disk is using dma for read/write */
+	byte     waiting_for_dma;	/* dma currently in progress */
+	byte     unmask;		/* flag: okay to unmask other irqs */
+	byte     slow;			/* flag: slow data port */
+	byte     bswap;			/* flag: byte swap data */
+	byte     dsc_overlap;		/* flag: DSC overlap */
+	byte     nice1;			/* flag: give potential excess bandwidth */
+	unsigned present	: 1;	/* drive is physically present */
+	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
+	unsigned busy		: 1;	/* currently doing revalidate_disk() */
+	unsigned removable	: 1;	/* 1 if need to do check_media_change */
+	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
+	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
+	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
+	unsigned nobios		: 1;	/* flag: do not probe bios for drive */
+	unsigned revalidate	: 1;	/* request revalidation */
+	unsigned atapi_overlap	: 1;	/* flag: ATAPI overlap (not supported) */
+	unsigned nice0		: 1;	/* flag: give obvious excess bandwidth */
+	unsigned nice2		: 1;	/* flag: give a share in our own bandwidth */
+	unsigned doorlocking	: 1;	/* flag: for removable only: door lock/unlock works */
+	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
+#if FAKE_FDISK_FOR_EZDRIVE
+	unsigned remap_0_to_1	: 1;	/* flag: partitioned with ezdrive */
+#endif /* FAKE_FDISK_FOR_EZDRIVE */
+	unsigned ata_flash	: 1;	/* 1=present, 0=default */
+	byte		media;		/* disk, cdrom, tape, floppy, ... */
+	select_t	select;		/* basic drive/head select reg value */
+	byte		ctl;		/* "normal" value for IDE_CONTROL_REG */
+	byte		ready_stat;	/* min status value for drive ready */
+	byte		mult_count;	/* current multiple sector setting */
+	byte 		mult_req;	/* requested multiple sector setting */
+	byte 		tune_req;	/* requested drive tuning setting */
+	byte		io_32bit;	/* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
+	byte		bad_wstat;	/* used for ignoring WRERR_STAT */
+	byte		nowerr;		/* used for ignoring WRERR_STAT */
+	byte		sect0;		/* offset of first sector for DM6:DDO */
+	byte 		usage;		/* current "open()" count for drive */
+	byte 		head;		/* "real" number of heads */
+	byte		sect;		/* "real" sectors per track */
+	byte		bios_head;	/* BIOS/fdisk/LILO number of heads */
+	byte		bios_sect;	/* BIOS/fdisk/LILO sectors per track */
+	unsigned short	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
+	unsigned short	cyl;		/* "real" number of cyls */
+	unsigned int	drive_data;	/* for use by tuneproc/selectproc as needed */
+	void		  *hwif;	/* actually (ide_hwif_t *) */
+	struct wait_queue *wqueue;	/* used to wait for drive in open() */
+	struct hd_driveid *id;		/* drive model identification info */
+	struct hd_struct  *part;	/* drive partition table */
+	char		name[4];	/* drive name, such as "hda" */
+	void 		*driver;	/* (ide_driver_t *) */
+	void		*driver_data;	/* extra driver data */
+	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
+	void		*settings;	/* /proc/ide/ drive settings */
+	char		driver_req[10];	/* requests specific driver */
+#if 1
+	struct thresholds_s	*smart_thresholds;
+	struct values_s		*smart_values;
+#else
+	thresholds_t		smart_thresholds;
+	values_t		smart_values;
+#endif
+	} ide_drive_t;
+
+/*
+ * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive.
+ *
+ * The caller is assumed to have selected the drive and programmed the drive's
+ * sector address using CHS or LBA.  All that remains is to prepare for DMA
+ * and then issue the actual read/write DMA/PIO command to the drive.
+ *
+ * Returns 0 if all went well.
+ * Returns 1 if DMA read/write could not be started, in which case the caller
+ * should either try again later, or revert to PIO for the current request.
+ */
+typedef enum {	ide_dma_read,	ide_dma_write,		ide_dma_begin,
+		ide_dma_end,	ide_dma_check,		ide_dma_on,
+		ide_dma_off,	ide_dma_off_quietly,	ide_dma_test_irq,
+		ide_dma_bad_drive,			ide_dma_good_drive
+	} ide_dma_action_t;
+
+typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
+
+
+/*
+ * An ide_tuneproc_t() is used to set the speed of an IDE interface
+ * to a particular PIO mode.  The "byte" parameter is used
+ * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255
+ * indicates that the interface driver should "auto-tune" the PIO mode
+ * according to the drive capabilities in drive->id;
+ *
+ * Not all interface types support tuning, and not all of those
+ * support all possible PIO settings.  They may silently ignore
+ * or round values as they see fit.
+ */
+typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
+
+/*
+ * This is used to provide support for strange interfaces
+ */
+typedef void (ide_selectproc_t) (ide_drive_t *);
+
+/*
+ * hwif_chipset_t is used to keep track of the specific hardware
+ * chipset used by each IDE interface, if known.
+ */
+typedef enum {	ide_unknown,	ide_generic,	ide_pci,
+		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
+		ide_qd6580,	ide_umc8672,	ide_ht6560b,
+		ide_pdc4030,	ide_rz1000,	ide_trm290,
+		ide_cmd646,	ide_cy82c693,	ide_4drives
+	} hwif_chipset_t;
+
+typedef struct ide_pci_devid_s {
+	unsigned short	vid;
+	unsigned short	did;
+} ide_pci_devid_t;
+
+#define IDE_PCI_DEVID_NULL	((ide_pci_devid_t){0,0})
+#define IDE_PCI_DEVID_EQ(a,b)	(a.vid == b.vid && a.did == b.did)
+
+typedef struct hwif_s {
+	struct hwif_s	*next;		/* for linked-list in ide_hwgroup_t */
+	void		*hwgroup;	/* actually (ide_hwgroup_t *) */
+	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
+	hw_regs_t	hw;		/* Hardware info */
+	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
+	struct gendisk	*gd;		/* gendisk structure */
+	ide_tuneproc_t	*tuneproc;	/* routine to tune PIO mode for drives */
+	ide_selectproc_t *selectproc;	/* tweaks hardware to select drive */
+	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
+	unsigned long	*dmatable;	/* dma physical region descriptor table */
+	struct hwif_s	*mate;		/* other hwif from same PCI chip */
+	unsigned long	dma_base;	/* base addr for dma ports */
+	unsigned	dma_extra;	/* extra addr for dma ports */
+	unsigned long	config_data;	/* for use by chipset-specific code */
+	unsigned long	select_data;	/* for use by chipset-specific code */
+	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
+	int		irq;		/* our irq number */
+	byte		major;		/* our major number */
+	char 		name[6];	/* name of interface, eg. "ide0" */
+	byte		index;		/* 0 for ide0; 1 for ide1; ... */
+	hwif_chipset_t	chipset;	/* sub-module for tuning.. */
+	unsigned	noprobe    : 1;	/* don't probe for this interface */
+	unsigned	present    : 1;	/* this interface exists */
+	unsigned	serialized : 1;	/* serialized operation with mate hwif */
+	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
+	unsigned	reset      : 1;	/* reset after probe */
+	unsigned	autodma    : 1;	/* automatically try to enable DMA at boot */
+	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
+	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
+	struct pci_dev	*pci_dev;	/* for pci chipsets */
+	ide_pci_devid_t	pci_devid;	/* for pci chipsets: {VID,DID} */
+#if (DISK_RECOVERY_TIME > 0)
+	unsigned long	last_time;	/* time when previous rq was done */
+#endif
+	} ide_hwif_t;
+
+/*
+ *  internal ide interrupt handler type
+ */
+typedef void (ide_handler_t)(ide_drive_t *);
+
+typedef struct hwgroup_s {
+	spinlock_t		spinlock; /* protects "busy" and "handler" */
+	ide_handler_t		*handler;/* irq handler, if active */
+	int			busy;	/* BOOL: protects all fields below */
+	ide_drive_t		*drive;	/* current drive */
+	ide_hwif_t		*hwif;	/* ptr to current hwif in linked-list */
+	struct request		*rq;	/* current request */
+	struct timer_list	timer;	/* failsafe timer */
+	struct request		wrq;	/* local copy of current write rq */
+	unsigned long		poll_timeout;	/* timeout value during long polls */
+	} ide_hwgroup_t;
+
+/*
+ * configurable drive settings
+ */
+
+#define TYPE_INT	0
+#define TYPE_INTA	1
+#define TYPE_BYTE	2
+#define TYPE_SHORT	3
+
+#define SETTING_READ	(1 << 0)
+#define SETTING_WRITE	(1 << 1)
+#define SETTING_RW	(SETTING_READ | SETTING_WRITE)
+
+typedef int (ide_procset_t)(ide_drive_t *, int);
+typedef struct ide_settings_s {
+	char			*name;
+	int			rw;
+	int			read_ioctl;
+	int			write_ioctl;
+	int			data_type;
+	int			min;
+	int			max;
+	int			mul_factor;
+	int			div_factor;
+	void			*data;
+	ide_procset_t		*set;
+	int			auto_remove;
+	struct ide_settings_s	*next;
+} ide_settings_t;
+
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
+void ide_remove_setting(ide_drive_t *drive, char *name);
+ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
+int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
+int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
+void ide_add_generic_settings(ide_drive_t *drive);
+
+/*
+ * /proc/ide interface
+ */
+typedef struct {
+	const char	*name;
+	mode_t		mode;
+	read_proc_t	*read_proc;
+	write_proc_t	*write_proc;
+} ide_proc_entry_t;
+
+#ifdef CONFIG_PROC_FS
+void proc_ide_create(void);
+void proc_ide_destroy(void);
+void destroy_proc_ide_drives(ide_hwif_t *);
+void create_proc_ide_interfaces(void);
+void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
+void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
+read_proc_t proc_ide_read_capacity;
+read_proc_t proc_ide_read_geometry;
+
+/*
+ * Standard exit stuff:
+ */
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) \
+{					\
+	len -= off;			\
+	if (len < count) {		\
+		*eof = 1;		\
+		if (len <= 0)		\
+			return 0;	\
+	} else				\
+		len = count;		\
+	*start = page + off;		\
+	return len;			\
+}
+#else
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
+#endif
+
+/*
+ * Subdrivers support.
+ */
+#define IDE_SUBDRIVER_VERSION	1
+
+typedef int	(ide_cleanup_proc)(ide_drive_t *);
+typedef void 	(ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
+typedef void	(ide_end_request_proc)(byte, ide_hwgroup_t *);
+typedef int 	(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
+typedef int	(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef void 	(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef int	(ide_check_media_change_proc)(ide_drive_t *);
+typedef void	(ide_pre_reset_proc)(ide_drive_t *);
+typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
+typedef void	(ide_special_proc)(ide_drive_t *);
+typedef void	(ide_setting_proc)(ide_drive_t *);
+
+typedef struct ide_driver_s {
+	const char			*name;
+	const char			*version;
+	byte				media;
+	unsigned busy			: 1;
+	unsigned supports_dma		: 1;
+	unsigned supports_dsc_overlap	: 1;
+	ide_cleanup_proc		*cleanup;
+	ide_do_request_proc		*do_request;
+	ide_end_request_proc		*end_request;
+	ide_ioctl_proc			*ioctl;
+	ide_open_proc			*open;
+	ide_release_proc		*release;
+	ide_check_media_change_proc	*media_change;
+	ide_pre_reset_proc		*pre_reset;
+	ide_capacity_proc		*capacity;
+	ide_special_proc		*special;
+	ide_proc_entry_t		*proc;
+	} ide_driver_t;
+
+#define DRIVER(drive)		((ide_driver_t *)((drive)->driver))
+
+/*
+ * IDE modules.
+ */
+#define IDE_CHIPSET_MODULE		0	/* not supported yet */
+#define IDE_PROBE_MODULE		1
+#define IDE_DRIVER_MODULE		2
+
+typedef int	(ide_module_init_proc)(void);
+
+typedef struct ide_module_s {
+	int				type;
+	ide_module_init_proc		*init;
+	void				*info;
+	struct ide_module_s		*next;
+} ide_module_t;
+
+/*
+ * ide_hwifs[] is the master data structure used to keep track
+ * of just about everything in ide.c.  Whenever possible, routines
+ * should be using pointers to a drive (ide_drive_t *) or
+ * pointers to a hwif (ide_hwif_t *), rather than indexing this
+ * structure directly (the allocation/layout may change!).
+ *
+ */
+#ifndef _IDE_C
+extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
+extern  ide_module_t	*ide_modules;
+#endif
+
+/*
+ * We need blk.h, but we replace its end_request by our own version.
+ */
+#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
+#define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
+#include <linux/blk.h>
+
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
+
+/*
+ * This is used for (nearly) all data transfers from/to the IDE interface
+ */
+void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+
+/*
+ * This is used for (nearly) all ATAPI data transfers from/to the IDE interface
+ */
+void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
+void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
+
+/*
+ * This is used on exit from the driver, to designate the next irq handler
+ * and also to start the safety timer.
+ */
+void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
+
+/*
+ * Error reporting, in human readable form (luxurious, but a memory hog).
+ */
+byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
+
+/*
+ * ide_error() takes action based on the error returned by the controller.
+ * The calling function must return afterwards, to restart the request.
+ */
+void ide_error (ide_drive_t *drive, const char *msg, byte stat);
+
+/*
+ * Issue a simple drive command
+ * The drive must be selected beforehand.
+ */
+void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
+
+/*
+ * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
+ * removing leading/trailing blanks and compressing internal blanks.
+ * It is primarily used to tidy up the model name/number fields as
+ * returned by the WIN_[P]IDENTIFY commands.
+ */
+void ide_fixstring (byte *s, const int bytecount, const int byteswap);
+
+/*
+ * This routine busy-waits for the drive status to be not "busy".
+ * It then checks the status for all of the "good" bits and none
+ * of the "bad" bits, and if all is okay it returns 0.  All other
+ * cases return 1 after invoking ide_error() -- caller should return.
+ *
+ */
+int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
+
+/*
+ * This routine is called from the partition-table code in genhd.c
+ * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
+ *
+ * The second parameter, "xparm", determines exactly how the translation
+ * will be handled:
+ *		 0 = convert to CHS with fewer than 1024 cyls
+ *			using the same method as Ontrack DiskManager.
+ *		 1 = same as "0", plus offset everything by 63 sectors.
+ *		-1 = similar to "0", plus redirect sector 0 to sector 1.
+ *		>1 = convert to a CHS geometry with "xparm" heads.
+ *
+ * Returns 0 if the translation was not possible, if the device was not
+ * an IDE disk drive, or if a geometry was "forced" on the commandline.
+ * Returns 1 if the geometry translation was successful.
+ */
+int ide_xlate_1024 (kdev_t, int, const char *);
+
+/*
+ * Start a reset operation for an IDE interface.
+ * The caller should return immediately after invoking this.
+ */
+void ide_do_reset (ide_drive_t *);
+
+/*
+ * This function is intended to be used prior to invoking ide_do_drive_cmd().
+ */
+void ide_init_drive_cmd (struct request *rq);
+
+/*
+ * "action" parameter type for ide_do_drive_cmd() below.
+ */
+typedef enum
+	{ide_wait,	/* insert rq at end of list, and wait for it */
+	 ide_next,	/* insert rq immediately after current request */
+	 ide_preempt,	/* insert rq in front of current request */
+	 ide_end}	/* insert rq at end of list, but don't wait for it */
+ ide_action_t;
+
+/*
+ * This function issues a special IDE device request
+ * onto the request queue.
+ *
+ * If action is ide_wait, then the rq is queued at the end of the
+ * request queue, and the function sleeps until it has been processed.
+ * This is for use when invoked from an ioctl handler.
+ *
+ * If action is ide_preempt, then the rq is queued at the head of
+ * the request queue, displacing the currently-being-processed
+ * request and this function returns immediately without waiting
+ * for the new rq to be completed.  This is VERY DANGEROUS, and is
+ * intended for careful use by the ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_next, then the rq is queued immediately after
+ * the currently-being-processed-request (if any), and the function
+ * returns without waiting for the new rq to be completed.  As above,
+ * This is VERY DANGEROUS, and is intended for careful use by the
+ * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code.
+ */
+int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
+
+/*
+ * Clean up after success/failure of an explicit drive cmd.
+ * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
+ */
+void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
+
+/*
+ * Issue ATA command and wait for completion.
+ */
+int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
+
+void ide_delay_50ms (void);
+int ide_config_drive_speed (ide_drive_t *drive, byte speed);
+
+/*
+ * ide_system_bus_speed() returns what we think is the system VESA/PCI
+ * bus speed (in MHz).  This is used for calculating interface PIO timings.
+ * The default is 40 for known PCI systems, 50 otherwise.
+ * The "idebus=xx" parameter can be used to override this value.
+ */
+int ide_system_bus_speed (void);
+
+/*
+ * ide_multwrite() transfers a block of up to mcount sectors of data
+ * to a drive as part of a disk multwrite operation.
+ */
+void ide_multwrite (ide_drive_t *drive, unsigned int mcount);
+
+/*
+ * ide_stall_queue() can be used by a drive to give excess bandwidth back
+ * to the hwgroup by sleeping for timeout jiffies.
+ */
+void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
+
+/*
+ * ide_get_queue() returns the queue which corresponds to a given device.
+ */
+struct request **ide_get_queue (kdev_t dev);
+
+/*
+ * CompactFlash cards and their brethern pretend to be removable hard disks,
+ * but they never have a slave unit, and they don't have doorlock mechanisms.
+ * This test catches them, and is invoked elsewhere when setting appropriate config bits.
+ */
+int drive_is_flashcard (ide_drive_t *drive);
+
+int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
+void ide_timer_expiry (unsigned long data);
+void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
+void ide_geninit (struct gendisk *gd);
+void do_ide0_request (void);
+#if MAX_HWIFS > 1
+void do_ide1_request (void);
+#endif
+#if MAX_HWIFS > 2
+void do_ide2_request (void);
+#endif
+#if MAX_HWIFS > 3
+void do_ide3_request (void);
+#endif
+#if MAX_HWIFS > 4
+void do_ide4_request (void);
+#endif
+#if MAX_HWIFS > 5
+void do_ide5_request (void);
+#endif
+#if MAX_HWIFS > 6
+void do_ide6_request (void);
+#endif
+#if MAX_HWIFS > 7
+void do_ide7_request (void);
+#endif
+void ide_init_subdrivers (void);
+
+#ifndef _IDE_C
+extern struct file_operations ide_fops[];
+extern ide_proc_entry_t generic_subdriver_entries[];
+#endif
+
+#ifdef _IDE_C
+#ifdef CONFIG_BLK_DEV_IDE
+int ideprobe_init (void);
+#endif /* CONFIG_BLK_DEV_IDE */
+#ifdef CONFIG_BLK_DEV_IDEDISK
+int idedisk_init (void);
+#endif /* CONFIG_BLK_DEV_IDEDISK */
+#ifdef CONFIG_BLK_DEV_IDECD
+int ide_cdrom_init (void);
+#endif /* CONFIG_BLK_DEV_IDECD */
+#ifdef CONFIG_BLK_DEV_IDETAPE
+int idetape_init (void);
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+int idefloppy_init (void);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+int idescsi_init (void);
+#endif /* CONFIG_BLK_DEV_IDESCSI */
+#endif /* _IDE_C */
+
+int ide_register_module (ide_module_t *module);
+void ide_unregister_module (ide_module_t *module);
+ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
+int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
+int ide_unregister_subdriver (ide_drive_t *drive);
+int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
+
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define ON_BOARD		1
+#define NEVER_BOARD		0
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+#  define OFF_BOARD		ON_BOARD
+#else /* CONFIG_BLK_DEV_OFFBOARD */
+#  define OFF_BOARD		NEVER_BOARD
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+unsigned long ide_find_free_region (unsigned short size) __init;
+void ide_scan_pcibus (void) __init;
+#endif
+#ifdef CONFIG_BLK_DEV_IDEDMA
+#define BAD_DMA_DRIVE		0
+#define GOOD_DMA_DRIVE		1
+int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func);
+void ide_dma_intr  (ide_drive_t *drive);
+int check_drive_lists (ide_drive_t *drive, int good_bad);
+int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+int ide_release_dma (ide_hwif_t *hwif);
+void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
+unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
+#endif
+
+#endif /* _IDE_H */
diff -urN linux-2.2.10-pristine/include/linux/major.h linux/include/linux/major.h
--- linux-2.2.10-pristine/include/linux/major.h	Tue Jul 20 19:11:29 1999
+++ linux/include/linux/major.h	Thu Jul 22 20:38:43 1999
@@ -94,6 +94,9 @@
 
 #define AURORA_MAJOR 79
 
+#define IDE6_MAJOR	88
+#define IDE7_MAJOR	89
+
 #define UNIX98_PTY_MASTER_MAJOR	128
 #define UNIX98_PTY_MAJOR_COUNT	8
 #define UNIX98_PTY_SLAVE_MAJOR	(UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
diff -urN linux-2.2.10-pristine/include/linux/pci.h linux/include/linux/pci.h
--- linux-2.2.10-pristine/include/linux/pci.h	Tue Jul 20 19:11:29 1999
+++ linux/include/linux/pci.h	Thu Jul 22 20:38:43 1999
@@ -452,13 +452,17 @@
 #define PCI_DEVICE_ID_SI_6205		0x0205
 #define PCI_DEVICE_ID_SI_501		0x0406
 #define PCI_DEVICE_ID_SI_496		0x0496
+#define PCI_DEVICE_ID_SI_530		0x0530
 #define PCI_DEVICE_ID_SI_601		0x0601
+#define PCI_DEVICE_ID_SI_620		0x0620
 #define PCI_DEVICE_ID_SI_5107		0x5107
 #define PCI_DEVICE_ID_SI_5511		0x5511
 #define PCI_DEVICE_ID_SI_5513		0x5513
 #define PCI_DEVICE_ID_SI_5571		0x5571
 #define PCI_DEVICE_ID_SI_5591		0x5591
 #define PCI_DEVICE_ID_SI_5597		0x5597
+#define PCI_DEVICE_ID_SI_5600		0x5600
+#define PCI_DEVICE_ID_SI_6306		0x6306
 #define PCI_DEVICE_ID_SI_7001		0x7001
 
 #define PCI_VENDOR_ID_HP		0x103c
@@ -522,6 +526,7 @@
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
 #define PCI_DEVICE_ID_PROMISE_20246	0x4d33
+#define PCI_DEVICE_ID_PROMISE_20262	0x4d38
 #define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
 #define PCI_VENDOR_ID_N9		0x105d
@@ -665,11 +670,14 @@
 #define PCI_DEVICE_ID_AL_M1523		0x1523
 #define PCI_DEVICE_ID_AL_M1531		0x1531
 #define PCI_DEVICE_ID_AL_M1533		0x1533
+#define PCI_DEVICE_ID_AL_M1541		0x1541
+#define PCI_DEVICE_ID_AL_M1543		0x1543
 #define PCI_DEVICE_ID_AL_M3307		0x3307
 #define PCI_DEVICE_ID_AL_M4803		0x5215
 #define PCI_DEVICE_ID_AL_M5219		0x5219
 #define PCI_DEVICE_ID_AL_M5229		0x5229
 #define PCI_DEVICE_ID_AL_M5237		0x5237
+#define PCI_DEVICE_ID_AL_M5243		0x5243
 #define PCI_DEVICE_ID_AL_M7101		0x7101
 
 #define PCI_VENDOR_ID_MITSUBISHI	0x10ba
@@ -733,6 +741,7 @@
 
 #define PCI_VENDOR_ID_TTI		0x1103
 #define PCI_DEVICE_ID_TTI_HPT343	0x0003
+#define PCI_DEVICE_ID_TTI_HPT366	0x0004
 
 #define PCI_VENDOR_ID_VIA		0x1106
 #define PCI_DEVICE_ID_VIA_82C505	0x0505
@@ -742,13 +751,21 @@
 #define PCI_DEVICE_ID_VIA_82C585	0x0585
 #define PCI_DEVICE_ID_VIA_82C586_0	0x0586
 #define PCI_DEVICE_ID_VIA_82C595	0x0595
+#define PCI_DEVICE_ID_VIA_82C596	0x0596
 #define PCI_DEVICE_ID_VIA_82C597_0	0x0597
 #define PCI_DEVICE_ID_VIA_82C598_0      0x0598
+#define PCI_DEVICE_ID_VIA_82C680	0x0680
+#define PCI_DEVICE_ID_VIA_82C686	0x0686
+#define PCI_DEVICE_ID_VIA_82C691	0x0691
+#define PCI_DEVICE_ID_VIA_82C693	0x0693
 #define PCI_DEVICE_ID_VIA_82C926	0x0926
 #define PCI_DEVICE_ID_VIA_82C416	0x1571
 #define PCI_DEVICE_ID_VIA_82C595_97	0x1595
 #define PCI_DEVICE_ID_VIA_82C586_2	0x3038
 #define PCI_DEVICE_ID_VIA_82C586_3	0x3040
+#define PCI_DEVICE_ID_VIA_82C686_4	0x3057
+#define PCI_DEVICE_ID_VIA_82C686_5	0x3058
+#define PCI_DEVICE_ID_VIA_82C686_6	0x3068
 #define PCI_DEVICE_ID_VIA_86C100A	0x6100
 #define PCI_DEVICE_ID_VIA_82C597_1	0x8597
 #define PCI_DEVICE_ID_VIA_82C598_1      0x8598
@@ -949,6 +966,9 @@
 #define PCI_DEVICE_ID_OPTIBASE_VPLEX	0x2110
 #define PCI_DEVICE_ID_OPTIBASE_VPLEXCC	0x2120
 #define PCI_DEVICE_ID_OPTIBASE_VQUEST	0x2130
+
+#define PCI_VENDOR_ID_ESS		0x125d
+#define PCI_DEVICE_ID_ESS_AUDIOPCI	0x1969
 
 #define PCI_VENDOR_ID_SATSAGEM		0x1267
 #define PCI_DEVICE_ID_SATSAGEM_PCR2101	0x5352
diff -urN linux-2.2.10-pristine/init/main.c linux/init/main.c
--- linux-2.2.10-pristine/init/main.c	Tue Jul 20 19:11:29 1999
+++ linux/init/main.c	Thu Jul 22 20:38:43 1999
@@ -416,6 +416,10 @@
 	{ "hdj",     0x3840 },
 	{ "hdk",     0x3900 },
 	{ "hdl",     0x3940 },
+	{ "hdm",     0x5800 },
+	{ "hdn",     0x5840 },
+	{ "hdo",     0x5900 },
+	{ "hdp",     0x5940 },
 #endif
 #ifdef CONFIG_BLK_DEV_SD
 	{ "sda",     0x0800 },
@@ -929,7 +933,11 @@
 
 #ifdef CONFIG_BLK_DEV_IDE
 	/* ide driver needs the basic string, rather than pre-processed values */
-	if (!strncmp(line,"ide",3) || (!strncmp(line,"hd",2) && line[2] != '=')) {
+	if (!strncmp(line,"ide",3) ||
+#ifdef CONFIG_BLK_DEV_VIA82C586
+	    !strncmp(line,"splitfifo",9) ||
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+	    (!strncmp(line,"hd",2) && line[2] != '=')) {
 		ide_setup(line);
 		return 1;
 	}
