## Automatically generated incremental diff
## From:   linux-2.4.9-pre2
## To:     linux-2.4.9-pre3
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.9-pre2/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt
--- linux-2.4.9-pre2/Documentation/filesystems/ntfs.txt	Mon Jul 16 15:14:10 2001
+++ linux/Documentation/filesystems/ntfs.txt	Mon Dec  3 23:02:44 2001
@@ -1,8 +1,8 @@
 NTFS Overview
 =============
 
-Driver development has as of recently (since June '01) been sponsored
-by Legato Systems, Inc. (http://www.legato.com)
+Legato Systems, Inc. (http://www.legato.com) have sponsored Anton Altaparmakov
+to develop NTFS on Linux since June 2001.
 
 To mount an NTFS volume, use the filesystem type 'ntfs'. The driver
 currently works only in read-only mode, with no fault-tolerance supported.
@@ -36,15 +36,17 @@
 
 iocharset=name		Character set to use when returning file names.
 			Unlike VFAT, NTFS suppresses names that contain
-			unconvertible characters
-
-utf8=<bool>		Use UTF-8 for converting file names
-
-uni_xlate=<bool>,2	Use the VFAT-style encoding for file names outside
-			the current character set. A boolean value will
-			enable the feature, a value of 2 will enable the
-			encoding as documented in vfat.txt:
-				':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12),
+			unconvertible characters. Note that most character
+			sets contain insufficient characters to represent all
+			possible Unicode characters that can exist on NTFS. To
+			be sure you are not missing any files, you are advised
+			to use the iocharset=utf8 which should be capable of
+			representing all Unicode characters.
+
+utf8=<bool>		Use UTF-8 for converting file names. - It is preferable
+			to use iocharset=utf8 instead, but if the utf8 NLS is
+			not available, you can use this utf8 option, which
+			enables the driver's builtin utf8 conversion functions.
 
 uid=
 gid=
@@ -80,6 +82,27 @@
 
 ChangeLog
 =========
+
+NTFS 1.1.16:
+
+	- Removed non-functional uni_xlate mount options.
+	- Clarified the semantics of the utf8 and iocharset mount options.
+	- Threw out the non-functional mount options for using hard coded
+	  character set conversion. Only kept utf8 one.
+	- Fixed handling of mount options and proper handling of faulty mount
+	  options on remount.
+	- Cleaned up character conversion which basically became simplified a
+	  lot due to the removal of the above mentioned mount options.
+	- Made character conversion to be always consistent. Previously we
+	  could output to the VFS file names which we would then not accept
+	  back from the VFS so in effect we were generating ghost entries in
+	  the directory listings which could not be accessed by any means.
+	- Simplified time conversion functions drastically without sacrificing
+	  accuracy. (-8
+	- Fixed a use of a pointer before the check for the pointer being
+	  NULL, reported by the Stanford checker.
+	- Fixed several missing error checks, reported by the Stanford
+	  checker and fixed by Rasmus Andersen.
 
 NTFS 1.1.15 (changes since kernel 2.4.4's NTFS driver):
 
diff -urN linux-2.4.9-pre2/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax
--- linux-2.4.9-pre2/Documentation/isdn/README.HiSax	Thu Feb  8 10:40:25 2001
+++ linux/Documentation/isdn/README.HiSax	Mon Dec  3 23:02:44 2001
@@ -69,12 +69,7 @@
 
 Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
       PCC-8: not tested yet
-      Teles PCMCIA is EXPERIMENTAL
-      Teles 16.3c is EXPERIMENTAL
-      Teles PCI is EXPERIMENTAL
-      Teles S0Box is EXPERIMENTAL
       Eicon.Diehl Diva U interface not tested
-      HFC-S+, HFC-SP/PCMCIA are experimental
 
 If you know other passive cards with the Siemens chipset, please let me know.
 To use the PNP cards you need the isapnptools.
diff -urN linux-2.4.9-pre2/Documentation/sonypi.txt linux/Documentation/sonypi.txt
--- linux-2.4.9-pre2/Documentation/sonypi.txt	Wed Jul  4 14:41:33 2001
+++ linux/Documentation/sonypi.txt	Mon Dec  3 23:02:44 2001
@@ -65,6 +65,19 @@
 Bugs:
 -----
 
+	- several users reported that this driver disables the BIOS-managed
+	  Fn-keys which put the laptop in sleeping state, or switch the
+	  external monitor on/off. There is no workaround yet, since this
+	  driver disables all APM management for those keys, by enabling the
+	  ACPI management (and the ACPI core stuff is not complete yet). If
+	  you have one of those laptops with working Fn keys and want to 
+	  continue to use them, don't use this driver.
+
+	- some users reported that the laptop speed is lower (dhrystone
+	  tested) when using the driver with the fnkeyinit parameter. I cannot
+	  reproduce it on my laptop and not all users have this problem.
+	  Still under investigation.
+	
 	- since all development was done by reverse engineering, there is
 	  _absolutely no guarantee_ that this driver will not crash your
 	  laptop. Permanently.
diff -urN linux-2.4.9-pre2/Makefile linux/Makefile
--- linux-2.4.9-pre2/Makefile	Mon Dec  3 23:02:35 2001
+++ linux/Makefile	Mon Dec  3 23:02:44 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 9
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.9-pre2/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.9-pre2/arch/i386/defconfig	Mon Dec  3 23:02:35 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 23:02:45 2001
@@ -218,6 +218,7 @@
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_BLK_DEV_IDEDMA=y
@@ -227,8 +228,8 @@
 # CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
@@ -241,7 +242,8 @@
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC202XX is not set
 # CONFIG_PDC202XX_BURST is not set
-# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
diff -urN linux-2.4.9-pre2/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- linux-2.4.9-pre2/arch/i386/kernel/apm.c	Fri Apr  6 10:42:47 2001
+++ linux/arch/i386/kernel/apm.c	Mon Dec  3 23:02:45 2001
@@ -148,6 +148,12 @@
  *   1.14: Make connection version persist across module unload/load.
  *         Enable and engage power management earlier.
  *         Disengage power management on module unload.
+ *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
+ *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
+ *         Work around byte swap bug in one of the Vaio's BIOS's
+ *         (Marc Boucher <marc@mbsi.ca>).
+ *         Exposed the disable flag to dmi so that we can handle known
+ *	   broken APM (Alan Cox <alan@redhat.com>).
  *
  * APM 1.1 Reference:
  *
@@ -339,14 +345,25 @@
 static int			got_clock_diff;
 #endif
 static int			debug;
-static int			apm_disabled;
+static int			apm_disabled = -1;
 #ifdef CONFIG_SMP
 static int			power_off;
 #else
 static int			power_off = 1;
 #endif
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+static int			realmode_power_off = 1;
+#else
+static int			realmode_power_off;
+#endif
 static int			exit_kapmd;
 static int			kapmd_running;
+#ifdef CONFIG_APM_ALLOW_INTS
+static int			allow_ints = 1;
+#else
+static int			allow_ints;
+#endif
+static int			broken_psr;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
@@ -413,11 +430,12 @@
  * Also, we KNOW that for the non error case of apm_bios_call, there
  * is no useful data returned in the low order 8 bits of eax.
  */
-#ifndef CONFIG_APM_ALLOW_INTS
-#	define APM_DO_CLI	__cli()
-#else
-#	define APM_DO_CLI	__sti()
-#endif
+#define APM_DO_CLI	\
+	if (apm_info.allow_ints) \
+		__sti(); \
+	else \
+		__cli();
+
 #ifdef APM_ZERO_SEGS
 #	define APM_DECL_SEGS \
 		unsigned int saved_fs; unsigned int saved_gs;
@@ -641,7 +659,6 @@
 
 static void apm_power_off(void)
 {
-#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
 	unsigned char	po_bios_call[] = {
 		0xb8, 0x00, 0x10,	/* movw  $0x1000,ax  */
 		0x8e, 0xd0,		/* movw  ax,ss       */
@@ -651,7 +668,6 @@
 		0xb9, 0x03, 0x00,	/* movw  $0x0003,cx  */
 		0xcd, 0x15		/* int   $0x15       */
 	};
-#endif
 
 	/*
 	 * This may be called on an SMP machine.
@@ -664,11 +680,10 @@
 		schedule();
 	}
 #endif
-#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
-	machine_real_restart(po_bios_call, sizeof(po_bios_call));
-#else
-	(void) apm_set_power_state(APM_STATE_OFF);
-#endif
+	if (apm_info.realmode_power_off)
+		machine_real_restart(po_bios_call, sizeof(po_bios_call));
+	else
+		(void) apm_set_power_state(APM_STATE_OFF);
 }
 
 #ifdef CONFIG_APM_DO_ENABLE
@@ -704,7 +719,11 @@
 		return (eax >> 8) & 0xff;
 	*status = ebx;
 	*bat = ecx;
-	*life = edx;
+	if (apm_info.get_power_status_swabinminutes) {
+		*life = swab16((u16)edx);
+		*life |= 0x8000;
+	} else
+		*life = edx;
 	return APM_SUCCESS;
 }
 
@@ -1552,9 +1571,15 @@
 			apm_disabled = 1;
 		if (strncmp(str, "on", 2) == 0)
 			apm_disabled = 0;
+		if ((strncmp(str, "allow-ints", 10) == 0) ||
+		    (strncmp(str, "allow_ints", 10) == 0))
+ 			apm_info.allow_ints = 1;
 		if ((strncmp(str, "broken-psr", 10) == 0) ||
 		    (strncmp(str, "broken_psr", 10) == 0))
 			apm_info.get_power_status_broken = 1;
+		if ((strncmp(str, "realmode-power-off", 18) == 0) ||
+		    (strncmp(str, "realmode_power_off", 18) == 0))
+			apm_info.realmode_power_off = 1;
 		invert = (strncmp(str, "no-", 3) == 0);
 		if (invert)
 			str += 3;
@@ -1620,6 +1645,16 @@
 		return -ENODEV;
 	}
 
+	if (allow_ints)
+		apm_info.allow_ints = 1;
+	if (broken_psr)
+		apm_info.get_power_status_broken = 1;
+	if (realmode_power_off)
+		apm_info.realmode_power_off = 1;
+	/* User can override, but default is to trust DMI */
+	if (apm_disabled != -1)
+		apm_info.disabled = 1;
+
 	/*
 	 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
 	 * but is reportedly a 1.0 BIOS.
@@ -1644,8 +1679,9 @@
 		printk("\n");
 	}
 
-	if (apm_disabled) {
-		printk(KERN_NOTICE "apm: disabled on user request.\n");
+	if (apm_info.disabled) {
+		if(apm_disabled == 1)
+			printk(KERN_NOTICE "apm: disabled on user request.\n");
 		return -ENODEV;
 	}
 	if ((smp_num_cpus > 1) && !power_off) {
@@ -1747,5 +1783,9 @@
 MODULE_PARM_DESC(power_off, "Enable power off");
 MODULE_PARM(bounce_interval, "i");
 MODULE_PARM_DESC(bounce_interval, "Set the number of ticks to ignore suspend bounces");
+MODULE_PARM(allow_ints, "i");
+MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
+MODULE_PARM(broken_psr, "i");
+MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
 
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.9-pre2/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- linux-2.4.9-pre2/arch/i386/kernel/dmi_scan.c	Mon Dec  3 23:02:35 2001
+++ linux/arch/i386/kernel/dmi_scan.c	Mon Dec  3 23:02:45 2001
@@ -271,6 +271,18 @@
 	return 0;
 }		
 
+
+/*
+ * This bios swaps the APM minute reporting bytes over (Many sony laptops
+ * have this problem).
+ */
+ 
+static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
+{
+	apm_info.get_power_status_swabinminutes = 1;
+	printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
+	return 0;
+}
 /*
  *	Process the DMI blacklists
  */
@@ -312,6 +324,11 @@
 			MATCH(DMI_SYS_VENDOR, "IBM"),
 			NO_MATCH, NO_MATCH, NO_MATCH
 			} },
+	{ set_apm_ints, "Dell Inspiron", {	/* Allow interrupts during suspend on Dell Inspiron laptops*/
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
+			NO_MATCH, NO_MATCH
+			} },
 	{ set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
 			MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 			MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
@@ -321,6 +338,21 @@
 			MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
 			MATCH(DMI_PRODUCT_NAME, "Delhi3"),
 			NO_MATCH, NO_MATCH,
+			} },
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0203Z3"),
+			MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
+			} },
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0203D0"),
+			MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
+			} },
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0121Z1"),
+			MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
 			} },
 	{ NULL, }
 };
diff -urN linux-2.4.9-pre2/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- linux-2.4.9-pre2/drivers/char/ChangeLog	Tue Sep  1 10:32:13 1998
+++ linux/drivers/char/ChangeLog	Mon Dec  3 23:02:45 2001
@@ -1,3 +1,7 @@
+2001-08-11  Tim Waugh  <twaugh@redhat.com>
+
+	* serial.c (get_pci_port): Deal with awkward Titan cards.
+
 1998-08-26  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
 	* serial.c (rs_open): Correctly decrement the module in-use count
diff -urN linux-2.4.9-pre2/drivers/char/serial.c linux/drivers/char/serial.c
--- linux-2.4.9-pre2/drivers/char/serial.c	Sun Aug  5 13:12:41 2001
+++ linux/drivers/char/serial.c	Mon Dec  3 23:02:45 2001
@@ -3886,6 +3886,22 @@
 			case 6: /* BAR 4*/
 			case 7: base_idx=idx-2; /* BAR 5*/
 		}
+
+	/* Some Titan cards are also a little weird */
+	if (dev->vendor == PCI_VENDOR_ID_TITAN &&
+	    (dev->device == PCI_DEVICE_ID_TITAN_400L ||
+	     dev->device == PCI_DEVICE_ID_TITAN_800L)) {
+		switch (idx) {
+		case 0: base_idx = 1;
+			break;
+		case 1: base_idx = 2;
+			break;
+		default:
+			base_idx = 4;
+			offset = 8 * (idx - 2);
+		}
+		
+	}
   
 	port =  pci_resource_start(dev, base_idx) + offset;
 
@@ -4656,6 +4672,19 @@
 	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 		pbn_b0_4_921600 },
+	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE1, 1, 921600 },
+	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
+	/* The 400L and 800L have a custom hack in get_pci_port */
+	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE_TABLE, 4, 921600 },
+	{	PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE_TABLE, 8, 921600 },
 
 	{	PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
diff -urN linux-2.4.9-pre2/drivers/ide/Config.in linux/drivers/ide/Config.in
--- linux-2.4.9-pre2/drivers/ide/Config.in	Thu Feb 15 17:22:08 2001
+++ linux/drivers/ide/Config.in	Mon Dec  3 23:02:45 2001
@@ -43,17 +43,21 @@
 	 if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
 	    bool '    Sharing PCI IDE interrupts support' CONFIG_IDEPCI_SHARE_IRQ
 	    bool '    Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI
+#	    bool '    Asynchronous DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI
+	    define_bool CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI
 	    bool '    Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
 	    dep_bool '      Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
 	    define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '      ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
+#	    dep_bool '      Attempt to HACK around Chipsets that TIMEOUT (WIP)' CONFIG_BLK_DEV_IDEDMA_TIMEOUT $CONFIG_IDEDMA_PCI_WIP
 	    dep_bool '      Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
+
 	    dep_bool '    AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_mbool '      AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX
 	    dep_bool '    ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_mbool '      ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
-	    dep_bool '    AMD Viper support' CONFIG_BLK_DEV_AMD7409 $CONFIG_BLK_DEV_IDEDMA_PCI
-	    dep_mbool '      AMD Viper ATA-66 Override (WIP)' CONFIG_AMD7409_OVERRIDE $CONFIG_BLK_DEV_AMD7409 $CONFIG_IDEDMA_PCI_WIP
+	    dep_bool '    AMD Viper support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
+	    dep_mbool '      AMD Viper ATA-66 Override (WIP)' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX $CONFIG_IDEDMA_PCI_WIP
 	    dep_bool '    CMD64X chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '    CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '    Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI
@@ -64,16 +68,24 @@
 	       dep_mbool '    Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI
 	       dep_mbool '      PIIXn Tuning support' CONFIG_PIIX_TUNING $CONFIG_BLK_DEV_PIIX $CONFIG_IDEDMA_PCI_AUTO
 	    fi
+	    if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then
+	       dep_mbool '    IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI
+	       dep_mbool '      IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO
+	    fi
 	    dep_bool '    NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '    OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL
-	    dep_bool '    PROMISE PDC20246/PDC20262/PDC20267 support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI
+	    dep_bool '    PROMISE PDC202{46|62|65|67|68} support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '      Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX
-	    dep_bool '    ServerWorks OSB4 chipset support' CONFIG_BLK_DEV_OSB4 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
+	    dep_bool '      Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX
+	    dep_bool '    ServerWorks OSB4/CSB5 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
 	    dep_bool '    SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
 	    dep_bool '    SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
 	    dep_bool '    Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_bool '    VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
          fi
+
+#	 dep_mbool '   Pacific Digital A-DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC_ADMA $CONFIG_BLK_DEV_ADMA $CONFIG_IDEDMA_PCI_WIP
+
 	 if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
 	    bool '    Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
 	 fi
@@ -97,17 +109,20 @@
 	 dep_bool '    RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN
       fi
       if [ "$CONFIG_AMIGA" = "y" ]; then
-	 dep_bool '    Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
-	 dep_mbool '      Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
+	 dep_bool '  Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
+	 dep_mbool '    Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
       fi
       if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	 dep_mbool '    Buddha/Catweasel IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL
+	 dep_mbool '  Buddha/Catweasel IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA $CONFIG_ZORRO $CONFIG_EXPERIMENTAL
       fi
       if [ "$CONFIG_ATARI" = "y" ]; then
-	 dep_bool '    Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI
+	 dep_bool '  Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE $CONFIG_ATARI
       fi
       if [ "$CONFIG_MAC" = "y" ]; then
-	 dep_bool '    Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE $CONFIG_MAC
+	 dep_bool '  Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE $CONFIG_MAC
+      fi
+      if [ "$CONFIG_Q40" = "y" ]; then
+	 dep_bool '  Q40/Q60 IDE interface support' CONFIG_BLK_DEV_Q40IDE $CONFIG_Q40
       fi
 
       bool '  Other IDE chipset support' CONFIG_IDE_CHIPSETS
@@ -151,7 +166,7 @@
 if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
      "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \
      "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
-     "$CONFIG_BLK_DEV_AMD7409" = "y" -o \
+     "$CONFIG_BLK_DEV_AMD74XX" = "y" -o \
      "$CONFIG_BLK_DEV_CMD640" = "y" -o \
      "$CONFIG_BLK_DEV_CMD64X" = "y" -o \
      "$CONFIG_BLK_DEV_CS5530" = "y" -o \
@@ -160,9 +175,10 @@
      "$CONFIG_BLK_DEV_HPT366" = "y" -o \
      "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \
      "$CONFIG_BLK_DEV_OPTI621" = "y" -o \
-     "$CONFIG_BLK_DEV_OSB4" = "y" -o \
+     "$CONFIG_BLK_DEV_SVWKS" = "y" -o \
      "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \
      "$CONFIG_BLK_DEV_PIIX" = "y" -o \
+     "$CONFIG_BLK_DEV_IT8172" = "y" -o \
      "$CONFIG_BLK_DEV_SIS5513" = "y" -o \
      "$CONFIG_BLK_DEV_SLC90E66" = "y" -o \
      "$CONFIG_BLK_DEV_SL82C105" = "y" -o \
diff -urN linux-2.4.9-pre2/drivers/ide/Makefile linux/drivers/ide/Makefile
--- linux-2.4.9-pre2/drivers/ide/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/ide/Makefile	Mon Dec  3 23:02:45 2001
@@ -24,11 +24,12 @@
 obj-$(CONFIG_BLK_DEV_IDECD)     += ide-cd.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)   += ide-tape.o
 obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
+obj-$(CONFIG_BLK_DEV_IT8172)    += it8172.o
 
 ide-obj-$(CONFIG_BLK_DEV_AEC62XX)	+= aec62xx.o
 ide-obj-$(CONFIG_BLK_DEV_ALI14XX)	+= ali14xx.o
 ide-obj-$(CONFIG_BLK_DEV_ALI15X3)	+= alim15x3.o
-ide-obj-$(CONFIG_BLK_DEV_AMD7409)	+= amd7409.o
+ide-obj-$(CONFIG_BLK_DEV_AMD74XX)	+= amd74xx.o
 ide-obj-$(CONFIG_BLK_DEV_BUDDHA)	+= buddha.o
 ide-obj-$(CONFIG_BLK_DEV_CMD640)	+= cmd640.o
 ide-obj-$(CONFIG_BLK_DEV_CMD64X)	+= cmd64x.o
@@ -42,16 +43,18 @@
 ide-obj-$(CONFIG_BLK_DEV_HPT366)	+= hpt366.o
 ide-obj-$(CONFIG_BLK_DEV_HT6560B)	+= ht6560b.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
-ide-obj-$(CONFIG_BLK_DEV_IDEDMA)	+= ide-dma.o
+ide-obj-$(CONFIG_BLK_DEV_ADMA)		+= ide-adma.o
+ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI)	+= ide-dma.o
 ide-obj-$(CONFIG_BLK_DEV_IDEPCI)	+= ide-pci.o
 ide-obj-$(CONFIG_BLK_DEV_ISAPNP)	+= ide-pnp.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC)	+= ide-pmac.o
 ide-obj-$(CONFIG_BLK_DEV_MAC_IDE)	+= macide.o
 ide-obj-$(CONFIG_BLK_DEV_NS87415)	+= ns87415.o
 ide-obj-$(CONFIG_BLK_DEV_OPTI621)	+= opti621.o
-ide-obj-$(CONFIG_BLK_DEV_OSB4)		+= osb4.o
+ide-obj-$(CONFIG_BLK_DEV_SVWKS)		+= serverworks.o
 ide-obj-$(CONFIG_BLK_DEV_PDC202XX)	+= pdc202xx.o
 ide-obj-$(CONFIG_BLK_DEV_PDC4030)	+= pdc4030.o
+ide-obj-$(CONFIG_BLK_DEV_PDC_ADMA)	+= pdcadma.o
 ide-obj-$(CONFIG_BLK_DEV_PIIX)		+= piix.o
 ide-obj-$(CONFIG_BLK_DEV_QD6580)	+= qd6580.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
diff -urN linux-2.4.9-pre2/drivers/ide/amd74xx.c linux/drivers/ide/amd74xx.c
--- linux-2.4.9-pre2/drivers/ide/amd74xx.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ide/amd74xx.c	Mon Dec  3 23:02:45 2001
@@ -0,0 +1,485 @@
+/*
+ * linux/drivers/ide/amd74xx.c		Version 0.05	June 9, 2000
+ *
+ * Copyright (C) 1999-2000		Andre Hedrick <andre@linux-ide.org>
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ */
+
+#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/init.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#define DISPLAY_VIPER_TIMINGS
+
+#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int amd74xx_get_info(char *, char **, off_t, int);
+extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+static struct pci_dev *bmide_dev;
+
+static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	u32 bibma = pci_resource_start(bmide_dev, 4);
+	u8 c0 = 0, c1 = 0;
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb_p((unsigned short)bibma + 0x02);
+	c1 = inb_p((unsigned short)bibma + 0x0a);
+
+	p += sprintf(p, "\n                                AMD %04X VIPER Chipset.\n", bmide_dev->device);
+	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+	p += sprintf(p, "                %sabled                         %sabled\n",
+			(c0&0x80) ? "dis" : " en",
+			(c1&0x80) ? "dis" : " en");
+	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
+			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
+	p += sprintf(p, "UDMA\n");
+	p += sprintf(p, "DMA\n");
+	p += sprintf(p, "PIO\n");
+
+	return p-buffer;	/* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+byte amd74xx_proc = 0;
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static unsigned int amd74xx_swdma_check (struct pci_dev *dev)
+{
+	unsigned int class_rev;
+
+	if (dev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
+		return 0;
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+	return ((int) (class_rev >= 7) ? 1 : 0);
+}
+
+static int amd74xx_swdma_error(ide_drive_t *drive)
+{
+	printk("%s: single-word DMA not support (revision < C4)\n", drive->name);
+	return 0;
+}
+
+/*
+ * Here is where all the hard work goes to program the chipset.
+ *
+ */
+static int amd74xx_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	int err			= 0;
+	byte unit		= (drive->select.b.unit & 0x01);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	unsigned long dma_base	= hwif->dma_base;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+	byte drive_pci		= 0x00;
+	byte drive_pci2		= 0x00;
+	byte ultra_timing	= 0x00;
+	byte dma_pio_timing	= 0x00;
+	byte pio_timing		= 0x00;
+
+        switch (drive->dn) {
+		case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break;
+		case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break;
+		case 2: drive_pci = 0x51; drive_pci2 = 0x49; break;
+		case 3: drive_pci = 0x50; drive_pci2 = 0x48; break;
+		default:
+                        return -1;
+        }
+
+	pci_read_config_byte(dev, drive_pci, &ultra_timing);
+	pci_read_config_byte(dev, drive_pci2, &dma_pio_timing);
+	pci_read_config_byte(dev, 0x4c, &pio_timing);
+
+#ifdef DEBUG
+	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+		drive->name, ultra_timing, dma_pio_timing, pio_timing);
+#endif
+
+	ultra_timing	&= ~0xC7;
+	dma_pio_timing	&= ~0xFF;
+	pio_timing	&= ~(0x03 << drive->dn);
+
+#ifdef DEBUG
+	printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+		ultra_timing, dma_pio_timing, pio_timing);
+#endif
+
+	switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+		case XFER_UDMA_5:
+#undef __CAN_MODE_5
+#ifdef __CAN_MODE_5
+			ultra_timing |= 0x46;
+			dma_pio_timing |= 0x20;
+			break;
+#else
+			printk("%s: setting to mode 4, driver problems in mode 5.\n", drive->name);
+			speed = XFER_UDMA_4;
+#endif /* __CAN_MODE_5 */
+		case XFER_UDMA_4:
+			ultra_timing |= 0x45;
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_UDMA_3:
+			ultra_timing |= 0x44;
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_UDMA_2:
+			ultra_timing |= 0x40;
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_UDMA_1:
+			ultra_timing |= 0x41;
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_UDMA_0:
+			ultra_timing |= 0x42;
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_MW_DMA_2:
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_MW_DMA_1:
+			dma_pio_timing |= 0x21;
+			break;
+		case XFER_MW_DMA_0:
+			dma_pio_timing |= 0x77;
+			break;
+		case XFER_SW_DMA_2:
+			if (!amd74xx_swdma_check(dev))
+				return amd74xx_swdma_error(drive);
+			dma_pio_timing |= 0x42;
+			break;
+		case XFER_SW_DMA_1:
+			if (!amd74xx_swdma_check(dev))
+				return amd74xx_swdma_error(drive);
+			dma_pio_timing |= 0x65;
+			break;
+		case XFER_SW_DMA_0:
+			if (!amd74xx_swdma_check(dev))
+				return amd74xx_swdma_error(drive);
+			dma_pio_timing |= 0xA8;
+			break;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+		case XFER_PIO_4:
+			dma_pio_timing |= 0x20;
+			break;
+		case XFER_PIO_3:
+			dma_pio_timing |= 0x22;
+			break;
+		case XFER_PIO_2:
+			dma_pio_timing |= 0x42;
+			break;
+		case XFER_PIO_1:
+			dma_pio_timing |= 0x65;
+			break;
+		case XFER_PIO_0:
+		default:
+			dma_pio_timing |= 0xA8;
+			break;
+        }
+
+	pio_timing |= (0x03 << drive->dn);
+
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	pci_write_config_byte(dev, drive_pci, ultra_timing);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+	pci_write_config_byte(dev, drive_pci2, dma_pio_timing);
+	pci_write_config_byte(dev, 0x4c, pio_timing);
+
+#ifdef DEBUG
+	printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+		ultra_timing, dma_pio_timing, pio_timing);
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	if (speed > XFER_PIO_4) {
+		outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+	} else {
+		outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+	}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+	err = ide_config_drive_speed(drive, speed);
+	drive->current_speed = speed;
+	return (err);
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+	unsigned short xfer_pio	= drive->id->eide_pio_modes;
+	byte			timing, speed, pio;
+
+	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+	if (xfer_pio> 4)
+		xfer_pio = 0;
+
+	if (drive->id->eide_pio_iordy > 0) {
+		for (xfer_pio = 5;
+			xfer_pio>0 &&
+			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+			xfer_pio--);
+	} else {
+		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+			   (drive->id->eide_pio_modes & 2) ? 0x04 :
+			   (drive->id->eide_pio_modes & 1) ? 0x03 :
+			   (drive->id->tPIO & 2) ? 0x02 :
+			   (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+	}
+
+	timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+	switch(timing) {
+		case 4: speed = XFER_PIO_4;break;
+		case 3: speed = XFER_PIO_3;break;
+		case 2: speed = XFER_PIO_2;break;
+		case 1: speed = XFER_PIO_1;break;
+		default:
+			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+			break;
+	}
+	(void) amd74xx_tune_chipset(drive, speed);
+	drive->current_speed = speed;
+}
+
+static void amd74xx_tune_drive (ide_drive_t *drive, byte pio)
+{
+	byte speed;
+	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) amd74xx_tune_chipset(drive, speed);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+/*
+ * 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.
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	struct hd_driveid *id	= drive->id;
+	byte udma_66		= eighty_ninty_three(drive);
+	byte udma_100		= (dev->device==PCI_DEVICE_ID_AMD_VIPER_7411) ? 1 : 0;
+	byte speed		= 0x00;
+	int  rval;
+
+	if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) {
+		speed = XFER_UDMA_5;
+	} else if ((id->dma_ultra & 0x0010) && (udma_66)) {
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (udma_66)) {
+		speed = XFER_UDMA_3;
+	} else if (id->dma_ultra & 0x0004) {
+		speed = XFER_UDMA_2;
+	} else if (id->dma_ultra & 0x0002) {
+		speed = XFER_UDMA_1;
+	} else if (id->dma_ultra & 0x0001) {
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		speed = XFER_MW_DMA_0;
+	} else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) amd74xx_tune_chipset(drive, speed);
+
+	rval = (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 :
+						     ide_dma_off_quietly);
+
+	return rval;
+}
+
+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 & 0x002F) {
+				/* 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 & 0x007) &&
+			     (amd74xx_swdma_check(HWIF(drive)->pci_dev)))) {
+				/* 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);
+}
+
+/*
+ * amd74xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+
+int amd74xx_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 */
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+unsigned int __init pci_init_amd74xx (struct pci_dev *dev, const char *name)
+{
+	unsigned long fixdma_base = pci_resource_start(dev, 4);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	if (!amd74xx_swdma_check(dev))
+		printk("%s: disabling single-word DMA support (revision < C4)\n", name);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+	if (!fixdma_base) {
+		/*
+		 *
+		 */
+	} else {
+		/*
+		 * enable DMA capable bit, and "not" simplex only
+		 */
+		outb(inb(fixdma_base+2) & 0x60, fixdma_base+2);
+
+		if (inb(fixdma_base+2) & 0x80)
+			printk("%s: simplex device: DMA will fail!!\n", name);
+	}
+#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!amd74xx_proc) {
+		amd74xx_proc = 1;
+		bmide_dev = dev;
+		amd74xx_display_info = &amd74xx_get_info;
+	}
+#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */
+
+	return 0;
+}
+
+unsigned int __init ata66_amd74xx (ide_hwif_t *hwif)
+{
+#ifdef CONFIG_AMD74XX_OVERRIDE
+	byte ata66 = 1;
+#else
+	byte ata66 = 0;
+#endif /* CONFIG_AMD74XX_OVERRIDE */
+
+#if 0
+	pci_read_config_byte(hwif->pci_dev, 0x48, &ata66);
+	return ((ata66 & 0x02) ? 0 : 1);
+#endif
+	return ata66;
+}
+
+void __init ide_init_amd74xx (ide_hwif_t *hwif)
+{
+	hwif->tuneproc = &amd74xx_tune_drive;
+	hwif->speedproc = &amd74xx_tune_chipset;
+
+#ifndef CONFIG_BLK_DEV_IDEDMA
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+	hwif->autodma = 0;
+	return;
+#else
+
+	if (hwif->dma_base) {
+		hwif->dmaproc = &amd74xx_dmaproc;
+		if (!noautodma)
+			hwif->autodma = 1;
+	} else {
+		hwif->autodma = 0;
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+}
+
+void __init ide_dmacapable_amd74xx (ide_hwif_t *hwif, unsigned long dmabase)
+{
+	ide_setup_dma(hwif, dmabase, 8);
+}
diff -urN linux-2.4.9-pre2/drivers/ide/ide-adma.c linux/drivers/ide/ide-adma.c
--- linux-2.4.9-pre2/drivers/ide/ide-adma.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ide/ide-adma.c	Mon Dec  3 23:02:45 2001
@@ -0,0 +1,9 @@
+/*
+ *  linux/drivers/ide/ide-adma.c         Version 0.00	June 24, 2001
+ *
+ *  Copyright (c) 2001		Andre Hedrick <andre@linux-ide.org>
+ *
+ *  Asynchronous DMA -- TBA, this is a holding file.
+ *
+ */
+
diff -urN linux-2.4.9-pre2/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- linux-2.4.9-pre2/drivers/ide/ide-cd.c	Thu Jul 19 21:04:55 2001
+++ linux/drivers/ide/ide-cd.c	Mon Dec  3 23:02:45 2001
@@ -978,8 +978,7 @@
 
 		/* If we've filled the present buffer but there's another
 		   chained buffer after it, move on. */
-		if (rq->current_nr_sectors == 0 &&
-		    rq->nr_sectors > 0)
+		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
 			cdrom_end_request (1, drive);
 
 		/* If the buffers are full, cache the rest of the data in our
@@ -1193,6 +1192,55 @@
 	return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
 }
 
+static inline int cdrom_merge_requests(struct request *rq, struct request *nxt)
+{
+	int ret = 1;
+
+	/*
+	 * partitions not really working, but better check anyway...
+	 */
+	if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) {
+		rq->nr_sectors += nxt->nr_sectors;
+		rq->hard_nr_sectors += nxt->nr_sectors;
+		rq->bhtail->b_reqnext = nxt->bh;
+		rq->bhtail = nxt->bhtail;
+		list_del(&nxt->queue);
+		blkdev_release_request(nxt);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * the current request will always be the first one on the list
+ */
+static void cdrom_attempt_remerge(ide_drive_t *drive, struct request *rq)
+{
+	struct list_head *entry;
+	struct request *nxt;
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+
+	while (1) {
+		entry = rq->queue.next;
+		if (entry == &drive->queue.queue_head)
+			break;
+
+		nxt = blkdev_entry_to_request(entry);
+		if (rq->sector + rq->nr_sectors != nxt->sector)
+			break;
+		else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX)
+			break;
+
+		if (cdrom_merge_requests(rq, nxt))
+			break;
+	}
+
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
 /* Fix up a possibly partially-processed request so that we can
    start it over entirely, or even put it back on the request queue. */
 static void restore_request (struct request *rq)
@@ -1204,6 +1252,8 @@
 		rq->sector -= n;
 	}
 	rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
+	rq->hard_nr_sectors = rq->nr_sectors;
+	rq->hard_sector = rq->sector;
 }
 
 /*
@@ -1217,20 +1267,22 @@
 
 	/* If the request is relative to a partition, fix it up to refer to the
 	   absolute address.  */
-	if ((minor & PARTN_MASK) != 0) {
+	if (minor & PARTN_MASK) {
 		rq->sector = block;
 		minor &= ~PARTN_MASK;
-		rq->rq_dev = MKDEV (MAJOR(rq->rq_dev), minor);
+		rq->rq_dev = MKDEV(MAJOR(rq->rq_dev), minor);
 	}
 
 	/* We may be retrying this request after an error.  Fix up
 	   any weirdness which might be present in the request packet. */
-	restore_request (rq);
+	restore_request(rq);
 
 	/* Satisfy whatever we can of this request from our cached sector. */
 	if (cdrom_read_from_buffer(drive))
 		return ide_stopped;
 
+	cdrom_attempt_remerge(drive, rq);
+
 	/* Clear the local sector buffer. */
 	info->nsectors_buffered = 0;
 
@@ -1478,7 +1530,7 @@
 
 static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
 {
-	int stat, ireason, len, sectors_to_transfer;
+	int stat, ireason, len, sectors_to_transfer, uptodate;
 	struct cdrom_info *info = drive->driver_data;
 	int i, dma_error = 0, dma = info->dma;
 	ide_startstop_t startstop;
@@ -1499,6 +1551,9 @@
 		return startstop;
 	}
  
+	/*
+	 * using dma, transfer is complete now
+	 */
 	if (dma) {
 		if (dma_error)
 			return ide_error(drive, "dma error", stat);
@@ -1520,12 +1575,13 @@
 		/* If we're not done writing, complain.
 		 * Otherwise, complete the command normally.
 		 */
+		uptodate = 1;
 		if (rq->current_nr_sectors > 0) {
 			printk("%s: write_intr: data underrun (%ld blocks)\n",
-				drive->name, rq->current_nr_sectors);
-			cdrom_end_request(0, drive);
-		} else
-			cdrom_end_request(1, drive);
+			drive->name, rq->current_nr_sectors);
+			uptodate = 0;
+		}
+		cdrom_end_request(uptodate, drive);
 		return ide_stopped;
 	}
 
@@ -1534,26 +1590,42 @@
 		if (cdrom_write_check_ireason(drive, len, ireason))
 			return ide_stopped;
 
-	/* The number of sectors we need to read from the drive. */
 	sectors_to_transfer = len / SECTOR_SIZE;
 
-	/* Now loop while we still have data to read from the drive. DMA
-	 * transfers will already have been complete
+	/*
+	 * now loop and write out the data
 	 */
 	while (sectors_to_transfer > 0) {
-		/* If we've filled the present buffer but there's another
-		   chained buffer after it, move on. */
-		if (rq->current_nr_sectors == 0 && rq->nr_sectors > 0)
-			cdrom_end_request(1, drive);
+		int this_transfer;
+
+		if (!rq->current_nr_sectors) {
+			printk("ide-cd: write_intr: oops\n");
+			break;
+		}
 
-		atapi_output_bytes(drive, rq->buffer, rq->current_nr_sectors);
-		rq->nr_sectors -= rq->current_nr_sectors;
-		rq->current_nr_sectors = 0;
-		rq->sector += rq->current_nr_sectors;
-		sectors_to_transfer -= rq->current_nr_sectors;
+		/*
+		 * Figure out how many sectors we can transfer
+		 */
+		this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors);
+
+		while (this_transfer > 0) {
+			atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
+			rq->buffer += SECTOR_SIZE;
+			--rq->nr_sectors;
+			--rq->current_nr_sectors;
+			++rq->sector;
+			--this_transfer;
+			--sectors_to_transfer;
+		}
+
+		/*
+		 * current buffer complete, move on
+		 */
+		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+			cdrom_end_request (1, drive);
 	}
 
-	/* arm handler */
+	/* re-arm handler */
 	ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
 	return ide_started;
 }
@@ -1584,10 +1656,26 @@
 	return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);
 }
 
-static ide_startstop_t cdrom_start_write(ide_drive_t *drive)
+static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
 {
 	struct cdrom_info *info = drive->driver_data;
 
+	/*
+	 * writes *must* be 2kB frame aligned
+	 */
+	if ((rq->nr_sectors & 3) || (rq->sector & 3)) {
+		cdrom_end_request(0, drive);
+		return ide_stopped;
+	}
+
+	/*
+	 * for dvd-ram and such media, it's a really big deal to get
+	 * big writes all the time. so scour the queue and attempt to
+	 * remerge requests, often the plugging will not have had time
+	 * to do this properly
+	 */
+	cdrom_attempt_remerge(drive, rq);
+
 	info->nsectors_buffered = 0;
 
         /* use dma, if possible. we don't need to check more, since we
@@ -1630,7 +1718,7 @@
 				if (rq->cmd == READ)
 					action = cdrom_start_read(drive, block);
 				else
-					action = cdrom_start_write(drive);
+					action = cdrom_start_write(drive, rq);
 			}
 			info->last_block = block;
 			return action;
@@ -1833,6 +1921,7 @@
 
 	pc.buffer =  buf;
 	pc.buflen = buflen;
+	pc.quiet = 1;
 	pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
 	pc.c[6] = trackno;
 	pc.c[7] = (buflen >> 8);
@@ -1985,7 +2074,7 @@
 	/* Now try to get the total cdrom capacity. */
 	minor = (drive->select.b.unit) << PARTN_BITS;
 	dev = MKDEV(HWIF(drive)->major, minor);
-	stat = cdrom_get_last_written(dev, (long *)&toc->capacity);
+	stat = cdrom_get_last_written(dev, &toc->capacity);
 	if (stat)
 		stat = cdrom_read_capacity(drive, &toc->capacity, sense);
 	if (stat)
@@ -2786,7 +2875,7 @@
 	MOD_INC_USE_COUNT;
 	if (info->buffer == NULL)
 		info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
-	if ((info->buffer == NULL) || (rc = cdrom_fops.open(ip, fp))) {
+        if ((info->buffer == NULL) || (rc = cdrom_fops.open(ip, fp))) {
 		drive->usage--;
 		MOD_DEC_USE_COUNT;
 	}
@@ -2827,7 +2916,12 @@
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
 	HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
 
+	/*
+	 * reset block size, ide_revalidate_disk incorrectly sets it to
+	 * 1024 even for CDROM's
+	 */
 	blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
+	set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
 }
 
 static
@@ -2862,20 +2956,32 @@
 	return 0;
 }
 
+static
+int ide_cdrom_reinit (ide_drive_t *drive)
+{
+	return 0;
+}
+
 static ide_driver_t ide_cdrom_driver = {
 	name:			"ide-cdrom",
 	version:		IDECD_VERSION,
 	media:			ide_cdrom,
+	busy:			0,
 	supports_dma:		1,
 	supports_dsc_overlap:	1,
 	cleanup:		ide_cdrom_cleanup,
 	do_request:		ide_do_rw_cdrom,
+	end_request:		NULL,
 	ioctl:			ide_cdrom_ioctl,
 	open:			ide_cdrom_open,
 	release:		ide_cdrom_release,
 	media_change:		ide_cdrom_check_media_change,
 	revalidate:		ide_cdrom_revalidate,
+	pre_reset:		NULL,
 	capacity:		ide_cdrom_capacity,
+	special:		NULL,
+	proc:			NULL,
+	driver_reinit:		ide_cdrom_reinit,
 };
 
 int ide_cdrom_init(void);
diff -urN linux-2.4.9-pre2/drivers/ide/ide-cd.h linux/drivers/ide/ide-cd.h
--- linux-2.4.9-pre2/drivers/ide/ide-cd.h	Fri Aug 10 18:14:29 2001
+++ linux/drivers/ide/ide-cd.h	Mon Dec  3 23:02:45 2001
@@ -37,11 +37,12 @@
 
 /************************************************************************/
 
-#define SECTOR_SIZE		512
 #define SECTOR_BITS 		9
-#define SECTORS_PER_FRAME	(CD_FRAMESIZE / SECTOR_SIZE)
+#define SECTOR_SIZE		(1 << SECTOR_BITS)
+#define SECTORS_PER_FRAME	(CD_FRAMESIZE >> SECTOR_BITS)
 #define SECTOR_BUFFER_SIZE	(CD_FRAMESIZE * 32)
-#define SECTORS_BUFFER		(SECTOR_BUFFER_SIZE / SECTOR_SIZE)
+#define SECTORS_BUFFER		(SECTOR_BUFFER_SIZE >> SECTOR_BITS)
+#define SECTORS_MAX		(131072 >> SECTOR_BITS)
 
 #define BLOCKS_PER_FRAME	(CD_FRAMESIZE / BLOCK_SIZE)
 
diff -urN linux-2.4.9-pre2/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- linux-2.4.9-pre2/drivers/ide/ide-disk.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/ide/ide-disk.c	Mon Dec  3 23:02:45 2001
@@ -369,6 +369,7 @@
 {
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+	OUT_BYTE(0x00, IDE_FEATURE_REG);
 	OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
 #ifdef CONFIG_BLK_DEV_PDC4030
 	if (drive->select.b.lba || IS_PDC4030_DRIVE) {
@@ -692,43 +693,8 @@
 	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	INT_MAX,			1,	1024,	&max_readahead[major][minor],	NULL);
 	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	2,	&max_sectors[major][minor],	NULL);
 	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);
-}
-
-/*
- *	IDE subdriver functions, registered with ide.c
- */
-static ide_driver_t idedisk_driver = {
-	"ide-disk",		/* name */
-	IDEDISK_VERSION,	/* version */
-	ide_disk,		/* media */
-	0,			/* busy */
-	1,			/* supports_dma */
-	0,			/* supports_dsc_overlap */
-	NULL,			/* cleanup */
-	do_rw_disk,		/* do_request */
-	NULL,			/* end_request */
-	NULL,			/* ioctl */
-	idedisk_open,		/* open */
-	idedisk_release,	/* release */
-	idedisk_media_change,	/* media_change */
-	idedisk_revalidate,	/* revalidate */
-	idedisk_pre_reset,	/* pre_reset */
-	idedisk_capacity,	/* capacity */
-	idedisk_special,	/* special */
-	idedisk_proc		/* proc */
-};
-
-int idedisk_init (void);
-static ide_module_t idedisk_module = {
-	IDE_DRIVER_MODULE,
-	idedisk_init,
-	&idedisk_driver,
-	NULL
-};
-
-static int idedisk_cleanup (ide_drive_t *drive)
-{
-	return ide_unregister_subdriver(drive);
+	ide_add_setting(drive,	"failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->failures,		NULL);
+	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);
 }
 
 static void idedisk_setup (ide_drive_t *drive)
@@ -835,6 +801,69 @@
 	drive->no_io_32bit = id->dword_io ? 1 : 0;
 }
 
+static int idedisk_reinit (ide_drive_t *drive)
+{
+	return 0;
+}
+
+static int idedisk_cleanup (ide_drive_t *drive)
+{
+	return ide_unregister_subdriver(drive);
+}
+
+/*
+ *      IDE subdriver functions, registered with ide.c
+ */
+static ide_driver_t idedisk_driver = {
+	name:			"ide-disk",
+	version:		IDEDISK_VERSION,
+	media:			ide_disk,
+	busy:			0,
+	supports_dma:		1,
+	supports_dsc_overlap:	0,
+	cleanup:		idedisk_cleanup,
+	do_request:		do_rw_disk,
+	end_request:		NULL,
+	ioctl:			NULL,
+	open:			idedisk_open,
+	release:		idedisk_release,
+	media_change:		idedisk_media_change,
+	revalidate:		idedisk_revalidate,
+	pre_reset:		idedisk_pre_reset,
+	capacity:		idedisk_capacity,
+	special:		idedisk_special,
+	proc:			idedisk_proc,
+	driver_reinit:		idedisk_reinit,
+};
+
+int idedisk_init (void);
+static ide_module_t idedisk_module = {
+	IDE_DRIVER_MODULE,
+	idedisk_init,
+	&idedisk_driver,
+	NULL
+};
+
+MODULE_DESCRIPTION("ATA DISK Driver");
+
+static void __exit idedisk_exit (void)
+{
+	ide_drive_t *drive;
+	int failed = 0;
+
+	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);
+}
+
 int idedisk_init (void)
 {
 	ide_drive_t *drive;
@@ -859,27 +888,5 @@
 	return 0;
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-	return idedisk_init();
-}
-
-void cleanup_module (void)
-{
-	ide_drive_t *drive;
-	int failed = 0;
-
-	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 */
+module_init(idedisk_init);
+module_exit(idedisk_exit);
diff -urN linux-2.4.9-pre2/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c
--- linux-2.4.9-pre2/drivers/ide/ide-dma.c	Mon Jan 15 13:08:15 2001
+++ linux/drivers/ide/ide-dma.c	Mon Dec  3 23:02:45 2001
@@ -90,7 +90,16 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#undef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
+/*
+ * Long lost data from 2.0.34 that is now in 2.0.39
+ *
+ * This was used in ./drivers/block/triton.c to do DMA Base address setup
+ * when PnP failed.  Oh the things we forget.  I believe this was part
+ * of SFF-8038i that has been withdrawn from public access... :-((
+ */
+#define DEFAULT_BMIBA	0xe800	/* in case BIOS did not init it */
+#define DEFAULT_BMCRBA	0xcc00	/* VIA's default value */
+#define DEFAULT_BMALIBA	0xd400	/* ALI's default value */
 
 extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
 
@@ -119,6 +128,12 @@
 	{ "WDC AC31600H"	,	"ALL"		},
 	{ "WDC AC32100H"	,	"24.09P07"	},
 	{ "WDC AC23200L"	,	"21.10N21"	},
+	{ "Compaq CRD-8241B"	,	"ALL"		},
+	{ "CRD-8400B"		,	"ALL"		},
+	{ "SanDisk SDP3B-64"	,	"ALL"		},
+	{ "SAMSUNG CD-ROM SN-124",	"ALL"		},
+	{ "PLEXTOR CD-R PX-W8432T",	"ALL"		},
+	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",	"ALL"		},
 	{ 0			,	0		}
 
 };
@@ -206,7 +221,8 @@
 			}
 			return ide_stopped;
 		}
-		printk("%s: dma_intr: bad DMA status\n", drive->name);
+		printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
+		       drive->name, dma_stat);
 	}
 	return ide_error(drive, "dma_intr", stat);
 }
@@ -217,6 +233,9 @@
 	struct scatterlist *sg = hwif->sg_table;
 	int nents = 0;
 
+	if (hwif->sg_dma_active)
+		BUG();
+		
 	if (rq->cmd == READ)
 		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
 	else
@@ -282,11 +301,7 @@
 		while (cur_len) {
 			if (count++ >= PRD_ENTRIES) {
 				printk("%s: DMA table too small\n", drive->name);
-				pci_unmap_sg(HWIF(drive)->pci_dev,
-					     HWIF(drive)->sg_table,
-					     HWIF(drive)->sg_nents,
-					     HWIF(drive)->sg_dma_direction);
-				return 0; /* revert to PIO for this request */
+				goto use_pio_instead;
 			} else {
 				u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
 
@@ -296,6 +311,20 @@
 				xcount = bcount & 0xffff;
 				if (is_trm290_chipset)
 					xcount = ((xcount >> 2) - 1) << 16;
+				if (xcount == 0x0000) {
+					/* 
+					 * Most chipsets correctly interpret a length of 0x0000 as 64KB,
+					 * but at least one (e.g. CS5530) misinterprets it as zero (!).
+					 * So here we break the 64KB entry into two 32KB entries instead.
+					 */
+					if (count++ >= PRD_ENTRIES) {
+						printk("%s: DMA table too small\n", drive->name);
+						goto use_pio_instead;
+					}
+					*table++ = cpu_to_le32(0x8000);
+					*table++ = cpu_to_le32(cur_addr + 0x8000);
+					xcount = 0x8000;
+				}
 				*table++ = cpu_to_le32(xcount);
 				cur_addr += bcount;
 				cur_len -= bcount;
@@ -306,12 +335,19 @@
 		i--;
 	}
 
-	if (!count)
-		printk("%s: empty DMA table?\n", drive->name);
-	else if (!is_trm290_chipset)
-		*--table |= cpu_to_le32(0x80000000);
-
-	return count;
+	if (count) {
+		if (!is_trm290_chipset)
+			*--table |= cpu_to_le32(0x80000000);
+		return count;
+	}
+	printk("%s: empty DMA table?\n", drive->name);
+use_pio_instead:
+	pci_unmap_sg(HWIF(drive)->pci_dev,
+		     HWIF(drive)->sg_table,
+		     HWIF(drive)->sg_nents,
+		     HWIF(drive)->sg_dma_direction);
+	HWIF(drive)->sg_dma_active = 0;
+	return 0; /* revert to PIO for this request */
 }
 
 /* Teardown mappings after DMA has completed.  */
@@ -322,6 +358,7 @@
 	int nents = HWIF(drive)->sg_nents;
 
 	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+	HWIF(drive)->sg_dma_active = 0;
 }
 
 /*
@@ -426,6 +463,7 @@
 	return hwif->dmaproc(ide_dma_off_quietly, drive);
 }
 
+#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
 /*
  * 1 dmaing, 2 error, 4 intr
  */
@@ -449,6 +487,30 @@
 		return WAIT_CMD;
 	return 0;
 }
+#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
+static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive)
+{
+	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
+	ide_hwif_t *hwif	= HWIF(drive);
+	int enable_dma		= drive->using_dma;
+	unsigned long flags;
+	ide_startstop_t startstop;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	hwgroup->handler = NULL;
+	del_timer(&hwgroup->timer);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	drive->waiting_for_dma = 0;
+
+	startstop = ide_do_reset(drive);
+
+	if ((enable_dma) && !(drive->using_dma))
+		(void) hwif->dmaproc(ide_dma_on, drive);
+
+	return startstop;
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
 
 /*
  * ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
@@ -468,10 +530,11 @@
  */
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long dma_base = hwif->dma_base;
-	byte unit = (drive->select.b.unit & 0x01);
-	unsigned int count, reading = 0;
+//	ide_hwgroup_t *hwgroup		= HWGROUP(drive);
+	ide_hwif_t *hwif		= HWIF(drive);
+	unsigned long dma_base		= hwif->dma_base;
+	byte unit			= (drive->select.b.unit & 0x01);
+	unsigned int count, reading	= 0;
 	byte dma_stat;
 
 	switch (func) {
@@ -498,7 +561,11 @@
 			drive->waiting_for_dma = 1;
 			if (drive->media != ide_disk)
 				return 0;
+#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
+			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);	/* issue cmd to drive */
+#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry);	/* issue cmd to drive */
+#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
 			OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 		case ide_dma_begin:
 			/* Note that this is done *after* the cmd has
@@ -514,7 +581,7 @@
 			dma_stat = inb(dma_base+2);		/* get DMA status */
 			outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
 			ide_destroy_dmatable(drive);	/* purge DMA mappings */
-			return (dma_stat & 7) != 4;	/* verify good DMA status */
+			return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;	/* verify good DMA status */
 		case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
 			dma_stat = inb(dma_base+2);
 #if 0	/* do not set unless you know what you are doing */
@@ -530,6 +597,14 @@
 		case ide_dma_verbose:
 			return report_drive_dmaing(drive);
 		case ide_dma_timeout:
+			// FIXME: Many IDE chipsets do not permit command file register access
+			// FIXME: while the bus-master function is still active.
+			// FIXME: To prevent deadlock with those chipsets, we must be extremely
+			// FIXME: careful here (and in ide_intr() as well) to NOT access any
+			// FIXME: registers from the 0x1Fx/0x17x sets before terminating the
+			// FIXME: bus-master operation via the bus-master control reg.
+			// FIXME: Otherwise, chipset deadlock will occur, and some systems will
+			// FIXME: lock up completely!!
 #ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
 			/*
 			 * Have to issue an abort and requeue the request
@@ -537,6 +612,23 @@
 			 * we have to clean up the mess, and here is as good
 			 * as any.  Do it globally for all chipsets.
 			 */
+			outb(0x00, dma_base);		/* stop DMA */
+			dma_stat = inb(dma_base+2);	/* get DMA status */
+			outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
+			printk("%s: %s: Lets do it again!" \
+				"stat = 0x%02x, dma_stat = 0x%02x\n",
+				drive->name, ide_dmafunc_verbose(func),
+				GET_STAT(), dma_stat);
+
+			if (dma_stat & 0xF0)
+				return ide_dma_timeout_revovery(drive);
+
+			printk("%s: %s: (restart_request) Lets do it again!" \
+				"stat = 0x%02x, dma_stat = 0x%02x\n",
+				drive->name, ide_dmafunc_verbose(func),
+				GET_STAT(), dma_stat);
+
+			return restart_request(drive);  // BUG: return types do not match!!
 #endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
 		case ide_dma_retune:
 		case ide_dma_lostirq:
@@ -620,6 +712,12 @@
 	unsigned long	dma_base = 0;
 	struct pci_dev	*dev = hwif->pci_dev;
 
+#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
+	int second_chance = 0;
+
+second_chance_to_dma:
+#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
+
 	if (hwif->mate && hwif->mate->dma_base) {
 		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
 	} else {
@@ -629,6 +727,26 @@
 			dma_base = 0;
 		}
 	}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
+	if ((!dma_base) && (!second_chance)) {
+		unsigned long set_bmiba = 0;
+		second_chance++;
+		switch(dev->vendor) {
+			case PCI_VENDOR_ID_AL:
+				set_bmiba = DEFAULT_BMALIBA; break;
+			case PCI_VENDOR_ID_VIA:
+				set_bmiba = DEFAULT_BMCRBA; break;
+			case PCI_VENDOR_ID_INTEL:
+				set_bmiba = DEFAULT_BMIBA; break;
+			default:
+				return dma_base;
+		}
+		pci_write_config_dword(dev, 0x20, set_bmiba|1);
+		goto second_chance_to_dma;
+	}
+#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
+
 	if (dma_base) {
 		if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
 			request_region(dma_base+16, extra, name);
diff -urN linux-2.4.9-pre2/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c
--- linux-2.4.9-pre2/drivers/ide/ide-floppy.c	Thu Jun 14 14:16:58 2001
+++ linux/drivers/ide/ide-floppy.c	Mon Dec  3 23:02:45 2001
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/ide-floppy.c	Version 0.9	Jul   4, 1999
+ * linux/drivers/ide/ide-floppy.c	Version 0.9.sv	Jan 6 2001
  *
  * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
  */
@@ -29,9 +29,29 @@
  * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
  *                        bytes requested on each interrupt to be zero.
  *                        Thanks to <shanos@es.co.nz> for pointing this out.
+ * Ver 0.9.sv Jan 6 01   Sam Varshavchik <mrsam@courier-mta.com>
+ *                       Implement low level formatting.  Reimplemented
+ *                       IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
+ *                       bit.  My LS-120 drive barfs on
+ *                       IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
+ *                       Compromise by not reporting a failure to get this
+ *                       mode page.  Implemented four IOCTLs in order to
+ *                       implement formatting.  IOCTls begin with 0x4600,
+ *                       0x46 is 'F' as in Format.
+ * Ver 0.91  Dec 11 99   Added IOMEGA Clik! drive support by 
+ *     		   <paul@paulbristow.net>
+ * Ver 0.92  Oct 22 00   Paul Bristow became official maintainer for this 
+ *           		   driver.  Included Powerbook internal zip kludge.
+ * Ver 0.93  Oct 24 00   Fixed bugs for Clik! drive
+ *                        no disk on insert and disk change now works
+ * Ver 0.94  Oct 27 00   Tidied up to remove strstr(Clik) everywhere
+ * Ver 0.95  Nov  7 00   Brought across to kernel 2.4
+ * Ver 0.96  Jan  7 01   Actually in line with release version of 2.4.0
+ *                       including set_bit patch from Rusty Russel
+ * Ver 0.97  Jul 22 01   Merge 0.91-0.96 onto 0.9.sv for ac series
  */
 
-#define IDEFLOPPY_VERSION "0.9"
+#define IDEFLOPPY_VERSION "0.97"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -63,6 +83,10 @@
 #define IDEFLOPPY_DEBUG_INFO		0
 #define IDEFLOPPY_DEBUG_BUGS		1
 
+/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
+#define IDEFLOPPY_DEBUG( fmt, args... )
+
+
 /*
  *	Some drives require a longer irq timeout.
  */
@@ -228,6 +252,7 @@
 	 *	Last error information
 	 */
 	byte sense_key, asc, ascq;
+	int progress_indication;
 
 	/*
 	 *	Device information
@@ -236,7 +261,7 @@
 	idefloppy_capacity_descriptor_t capacity;		/* Last format capacity */
 	idefloppy_flexible_disk_page_t flexible_disk_page;	/* Copy of the flexible disk page */
 	int wp;							/* Write protect */
-
+	int srfp;			/* Supports format progress report */
 	unsigned long flags;			/* Status/Action flags */
 } idefloppy_floppy_t;
 
@@ -246,6 +271,9 @@
 #define IDEFLOPPY_DRQ_INTERRUPT		0	/* DRQ interrupt device */
 #define IDEFLOPPY_MEDIA_CHANGED		1	/* Media may have changed */
 #define IDEFLOPPY_USE_READ12		2	/* Use READ12/WRITE12 or READ10/WRITE10 */
+#define	IDEFLOPPY_FORMAT_IN_PROGRESS	3	/* Format in progress */
+#define IDEFLOPPY_CLIK_DRIVE	        4       /* Avoid commands not supported in Clik drive */
+
 
 /*
  *	ATAPI floppy drive packet commands
@@ -276,6 +304,15 @@
 #define MODE_SENSE_SAVED		0x03
 
 /*
+ *	IOCTLs used in low-level formatting.
+ */
+
+#define	IDEFLOPPY_IOCTL_FORMAT_SUPPORTED	0x4600
+#define	IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY	0x4601
+#define	IDEFLOPPY_IOCTL_FORMAT_START		0x4602
+#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS	0x4603
+
+/*
  *	Special requests for our block device strategy routine.
  */
 #define	IDEFLOPPY_FIRST_RQ		90
@@ -559,7 +596,7 @@
 	u8		asc;			/* Additional Sense Code */
 	u8		ascq;			/* Additional Sense Code Qualifier */
 	u8		replaceable_unit_code;	/* Field Replaceable Unit Code */
-	u8		reserved[3];
+	u8		sksv[3];
 	u8		pad[2];			/* Padding to 20 bytes */
 } idefloppy_request_sense_result_t;
 
@@ -746,6 +783,8 @@
 	idefloppy_floppy_t *floppy = drive->driver_data;
 
 	floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq;
+	floppy->progress_indication= result->sksv[0] & 0x80 ?
+		(unsigned short)get_unaligned((u16 *)(result->sksv+1)):0x10000;
 #if IDEFLOPPY_DEBUG_LOG
 	if (floppy->failed_pc)
 		printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq);
@@ -954,7 +993,7 @@
 		return ide_do_reset (drive);
 	}
 	ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);	/* Set the interrupt routine */
-	atapi_output_bytes (drive, floppy->pc->c, 12);		/* Send the actual packet */
+	atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
 	return ide_started;
 }
 
@@ -1062,6 +1101,22 @@
 	pc->request_transfer = 255;
 }
 
+static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l)
+{
+	idefloppy_init_pc (pc);
+	pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD;
+	pc->c[1] = 0x17;
+
+	memset(pc->buffer, 0, 12);
+	pc->buffer[1] = 0xA2;	/* Format list header, byte 1: FOV/DCRT/IMM */
+	pc->buffer[3] = 8;
+
+	put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4]));
+	put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8]));
+	pc->buffer_size=12;
+	set_bit(PC_WRITING, &pc->flags);
+}
+
 /*
  *	A mode sense command is used to "sense" floppy parameters.
  */
@@ -1235,6 +1290,25 @@
 	return 0;
 }
 
+static int idefloppy_get_capability_page(ide_drive_t *drive)
+{
+	idefloppy_floppy_t *floppy = drive->driver_data;
+	idefloppy_pc_t pc;
+	idefloppy_mode_parameter_header_t *header;
+	idefloppy_capabilities_page_t *page;
+
+	floppy->srfp=0;
+	idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_CAPABILITIES_PAGE,
+						 MODE_SENSE_CURRENT);
+	if (idefloppy_queue_pc_tail (drive,&pc)) {
+		return 1;
+	}
+	header = (idefloppy_mode_parameter_header_t *) pc.buffer;
+	page= (idefloppy_capabilities_page_t *)(header+1);
+	floppy->srfp=page->srfp;
+	return (0);
+}
+
 /*
  *	Determine if a media is present in the floppy drive, and if so,
  *	its LBA capacity.
@@ -1260,37 +1334,217 @@
 	header = (idefloppy_capacity_header_t *) pc.buffer;
 	descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t);
 	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
+
 	for (i = 0; i < descriptors; i++, descriptor++) {
-		blocks = descriptor->blocks = ntohl (descriptor->blocks);
-		length = descriptor->length = ntohs (descriptor->length);
-		if (!i && descriptor->dc == CAPACITY_CURRENT) {
-			if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) {
-				printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n",
-					drive->name, blocks * length / 1024, blocks, length,
-					drive->using_dma ? ", DMA":"");
-			}
-			floppy->capacity = *descriptor;
-			if (!length || length % 512)
-				printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length);
-			else {
-				floppy->blocks = blocks;
-				floppy->block_size = length;
-				if ((floppy->bs_factor = length / 512) != 1)
-					printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name);
-				rc = 0;
-			}
+                blocks = descriptor->blocks = ntohl (descriptor->blocks);
+                length = descriptor->length = ntohs (descriptor->length);
+
+		if (!i) 
+		{
+          	switch (descriptor->dc) {
+                case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */
+                        if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+                                break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */
+                case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */
+                        if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
+                                printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length);
+                        floppy->capacity = *descriptor;
+                        if (!length || length % 512)
+                                printk (KERN_NOTICE "%s: %d bytes block size not supported\n", drive->name, length);
+                        else {
+                                floppy->blocks = blocks;
+                                floppy->block_size = length;
+                                if ((floppy->bs_factor = length / 512) != 1)
+                                        printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name);
+                                rc = 0;
+                        }
+                        break;
+                case CAPACITY_NO_CARTRIDGE:
+                        /* This is a KERN_ERR so it appears on screen for the user to see */
+                        printk (KERN_ERR "%s: No disk in drive\n", drive->name);
+                                        break;
+                case CAPACITY_INVALID:
+                        printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name);
+                                        break;
 		}
-#if IDEFLOPPY_DEBUG_INFO
-		if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc);
-		printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
-#endif /* IDEFLOPPY_DEBUG_INFO */
+		}
+		if (!i) {
+		IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc);
+		}
+		IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
 	}
-	(void) idefloppy_get_flexible_disk_page (drive);
+
+	/* Clik! disk does not support get_flexible_disk_page */
+        if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+	{
+		(void) idefloppy_get_flexible_disk_page (drive);
+		(void) idefloppy_get_capability_page (drive);
+	}
+
 	drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor;
 	return rc;
 }
 
 /*
+** Obtain the list of formattable capacities.
+** Very similar to idefloppy_get_capacity, except that we push the capacity
+** descriptors to userland, instead of our own structures.
+**
+** Userland gives us the following structure:
+**
+** struct idefloppy_format_capacities {
+**        int nformats;
+**        struct {
+**                int nblocks;
+**                int blocksize;
+**                } formats[];
+**        } ;
+**
+** userland initializes nformats to the number of allocated formats[]
+** records.  On exit we set nformats to the number of records we've
+** actually initialized.
+**
+*/
+
+static int idefloppy_get_format_capacities (ide_drive_t *drive,
+					    struct inode *inode,
+					    struct file *file,
+					    int *arg)	/* Cheater */
+{
+        idefloppy_pc_t pc;
+	idefloppy_capacity_header_t *header;
+        idefloppy_capacity_descriptor_t *descriptor;
+	int i, descriptors, blocks, length;
+	int u_array_size;
+	int u_index;
+	int *argp;
+
+	if (get_user(u_array_size, arg))
+		return (-EFAULT);
+
+	if (u_array_size <= 0)
+		return (-EINVAL);
+
+	idefloppy_create_read_capacity_cmd (&pc);
+	if (idefloppy_queue_pc_tail (drive, &pc)) {
+		printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+                return (-EIO);
+        }
+        header = (idefloppy_capacity_header_t *) pc.buffer;
+        descriptors = header->length /
+		sizeof (idefloppy_capacity_descriptor_t);
+	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
+
+	u_index=0;
+	argp=arg+1;
+
+	/*
+	** We always skip the first capacity descriptor.  That's the
+	** current capacity.  We are interested in the remaining descriptors,
+	** the formattable capacities.
+	*/
+
+	for (i=0; i<descriptors; i++, descriptor++)
+	{
+		if (u_index >= u_array_size)
+			break;	/* User-supplied buffer too small */
+		if (i == 0)
+			continue;	/* Skip the first descriptor */
+
+		blocks = ntohl (descriptor->blocks);
+		length = ntohs (descriptor->length);
+
+		if (put_user(blocks, argp))
+			return (-EFAULT);
+		++argp;
+
+		if (put_user(length, argp))
+			return (-EFAULT);
+		++argp;
+
+		++u_index;
+	}
+
+	if (put_user(u_index, arg))
+		return (-EFAULT);
+	return (0);
+}
+
+/*
+** Send ATAPI_FORMAT_UNIT to the drive.
+**
+** Userland gives us the following structure:
+**
+** struct idefloppy_format_command {
+**        int nblocks;
+**        int blocksize;
+**        } ;
+*/
+
+static int idefloppy_begin_format(ide_drive_t *drive,
+				  struct inode *inode,
+				  struct file *file,
+				  int *arg)
+{
+	int blocks;
+	int length;
+	idefloppy_pc_t pc;
+
+	if (get_user(blocks, arg)
+	    || get_user(length, arg+1))
+	{
+		return (-EFAULT);
+	}
+
+	idefloppy_create_format_unit_cmd(&pc, blocks, length);
+	if (idefloppy_queue_pc_tail (drive, &pc))
+	{
+                return (-EIO);
+        }
+	return (0);
+}
+
+/*
+** Get ATAPI_FORMAT_UNIT progress indication.
+**
+** Userland gives a pointer to an int.  The int is set to a progresss
+** indicator 0-65536, with 65536=100%.
+**
+** If the drive does not support format progress indication, we just return
+** a 65536, screw it.
+*/
+
+static int idefloppy_get_format_progress(ide_drive_t *drive,
+					 struct inode *inode,
+					 struct file *file,
+					 int *arg)
+{
+	idefloppy_floppy_t *floppy = drive->driver_data;
+	idefloppy_pc_t pc;
+	int progress_indication=0x10000;
+
+	if (floppy->srfp)
+	{
+		idefloppy_create_request_sense_cmd(&pc);
+		if (idefloppy_queue_pc_tail (drive, &pc))
+		{
+			return (-EIO);
+		}
+
+		if (floppy->sense_key == 2 && floppy->asc == 4 &&
+		    floppy->ascq == 4)
+		{
+			progress_indication=floppy->progress_indication;
+		}
+	}
+
+	if (put_user(progress_indication, arg))
+		return (-EFAULT);
+
+	return (0);
+}
+
+/*
  *	Our special ide-floppy ioctl's.
  *
  *	Currently there aren't any ioctl's.
@@ -1299,15 +1553,72 @@
 				 unsigned int cmd, unsigned long arg)
 {
 	idefloppy_pc_t pc;
+	idefloppy_floppy_t *floppy = drive->driver_data;
+	int prevent = (arg) ? 1 : 0;
 
-	if (cmd == CDROMEJECT) {
+	switch (cmd) {
+	case CDROMEJECT:
+		prevent = 0;
+		/* fall through */
+	case CDROM_LOCKDOOR:
 		if (drive->usage > 1)
 			return -EBUSY;
-		idefloppy_create_prevent_cmd (&pc, 0);
-		(void) idefloppy_queue_pc_tail (drive, &pc);
-		idefloppy_create_start_stop_cmd (&pc, 2);
-		(void) idefloppy_queue_pc_tail (drive, &pc);
+
+		/* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
+                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+			idefloppy_create_prevent_cmd (&pc, prevent);
+			(void) idefloppy_queue_pc_tail (drive, &pc);
+		}
+		if (cmd == CDROMEJECT) {
+			idefloppy_create_start_stop_cmd (&pc, 2);
+			(void) idefloppy_queue_pc_tail (drive, &pc);
+		}
 		return 0;
+	case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
+		return (0);
+	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
+		return (idefloppy_get_format_capacities(drive, inode, file,
+							(int *)arg));
+	case IDEFLOPPY_IOCTL_FORMAT_START:
+
+		if (!(file->f_mode & 2))
+			return (-EPERM);
+
+		{
+			idefloppy_floppy_t *floppy = drive->driver_data;
+
+			set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+
+			if (drive->usage > 1)
+			{
+				/* Don't format if someone is using the disk */
+
+				clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
+					  &floppy->flags);
+				return -EBUSY;
+			}
+			else
+			{
+				int rc=idefloppy_begin_format(drive, inode,
+							      file,
+							      (int *)arg);
+
+				if (rc)
+					clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
+						  &floppy->flags);
+				return (rc);
+
+			/*
+			** Note, the bit will be cleared when the device is
+			** closed.  This is the cleanest way to handle the
+			** situation where the drive does not support
+			** format progress reporting.
+			*/
+			}
+		}
+	case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
+		return (idefloppy_get_format_progress(drive, inode, file,
+						      (int *)arg));
 	}
  	return -EIO;
 }
@@ -1326,26 +1637,41 @@
 
 	MOD_INC_USE_COUNT;
 	if (drive->usage == 1) {
+
+		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+		/* Just in case */
+
 		idefloppy_create_test_unit_ready_cmd(&pc);
 		if (idefloppy_queue_pc_tail(drive, &pc)) {
 			idefloppy_create_start_stop_cmd (&pc, 1);
 			(void) idefloppy_queue_pc_tail (drive, &pc);
 		}
+
 		if (idefloppy_get_capacity (drive)) {
 			drive->usage--;
 			MOD_DEC_USE_COUNT;
 			return -EIO;
 		}
+
 		if (floppy->wp && (filp->f_mode & 2)) {
 			drive->usage--;
 			MOD_DEC_USE_COUNT;
 			return -EROFS;
 		}		
 		set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
-		idefloppy_create_prevent_cmd (&pc, 1);
-		(void) idefloppy_queue_pc_tail (drive, &pc);
+		/* IOMEGA Clik! drives do not support lock/unlock commands */
+                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+			idefloppy_create_prevent_cmd (&pc, 1);
+			(void) idefloppy_queue_pc_tail (drive, &pc);
+		}
 		check_disk_change(inode->i_rdev);
 	}
+	else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags))
+	{
+		drive->usage--;
+		MOD_DEC_USE_COUNT;
+		return -EBUSY;
+	}
 	return 0;
 }
 
@@ -1358,9 +1684,17 @@
 #endif /* IDEFLOPPY_DEBUG_LOG */
 
 	if (!drive->usage) {
+		idefloppy_floppy_t *floppy = drive->driver_data;
+
 		invalidate_buffers (inode->i_rdev);
-		idefloppy_create_prevent_cmd (&pc, 0);
-		(void) idefloppy_queue_pc_tail (drive, &pc);
+
+		/* IOMEGA Clik! drives do not support lock/unlock commands */
+                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+			idefloppy_create_prevent_cmd (&pc, 0);
+			(void) idefloppy_queue_pc_tail (drive, &pc);
+		}
+
+		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
 	}
 	MOD_DEC_USE_COUNT;
 }
@@ -1560,6 +1894,19 @@
 			max_sectors[major][minor + i] = 64;
 	}
 
+	/*
+	*      Guess what?  The IOMEGA Clik! drive also needs the
+	*      above fix.  It makes nasty clicking noises without
+	*      it, so please don't remove this.
+	*/
+	if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) 
+	{
+		for (i = 0; i < 1 << PARTN_BITS; i++)
+			max_sectors[major][minor + i] = 64;
+		set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
+	}
+
+
 	(void) idefloppy_get_capacity (drive);
 	idefloppy_add_settings(drive);
 	for (i = 0; i < MAX_DRIVES; ++i) {
@@ -1597,28 +1944,34 @@
 
 #endif	/* CONFIG_PROC_FS */
 
+static int idefloppy_reinit (ide_drive_t *drive)
+{
+	return 0;
+}
+
 /*
  *	IDE subdriver functions, registered with ide.c
  */
 static ide_driver_t idefloppy_driver = {
-	"ide-floppy",		/* name */
-	IDEFLOPPY_VERSION,	/* version */
-	ide_floppy,		/* media */
-	0,			/* busy */
-	1,			/* supports_dma */
-	0,			/* supports_dsc_overlap */
-	idefloppy_cleanup,	/* cleanup */
-	idefloppy_do_request,	/* do_request */
-	idefloppy_end_request,	/* end_request */
-	idefloppy_ioctl,	/* ioctl */
-	idefloppy_open,		/* open */
-	idefloppy_release,	/* release */
-	idefloppy_media_change,	/* media_change */
-	idefloppy_revalidate,	/* media_change */
-	NULL,			/* pre_reset */
-	idefloppy_capacity,	/* capacity */
-	NULL,			/* special */
-	idefloppy_proc		/* proc */
+	name:			"ide-floppy",
+	version:		IDEFLOPPY_VERSION,
+	media:			ide_floppy,
+	busy:			0,
+	supports_dma:		1,
+	supports_dsc_overlap:	0,
+	cleanup:		idefloppy_cleanup,
+	do_request:		idefloppy_do_request,
+	end_request:		idefloppy_end_request,
+	ioctl:			idefloppy_ioctl,
+	open:			idefloppy_open,
+	release:		idefloppy_release,
+	media_change:		idefloppy_media_change,
+	revalidate:		idefloppy_revalidate,
+	pre_reset:		NULL,
+	capacity:		idefloppy_capacity,
+	special:		NULL,
+	proc:			idefloppy_proc,
+	driver_reinit:		idefloppy_reinit,
 };
 
 int idefloppy_init (void);
@@ -1629,6 +1982,26 @@
 	NULL
 };
 
+MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
+
+static void __exit idefloppy_exit (void)
+{
+	ide_drive_t *drive;
+	int failed = 0;
+
+	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);
+}
+
 /*
  *	idefloppy_init will register the driver for each floppy.
  */
@@ -1638,6 +2011,7 @@
 	idefloppy_floppy_t *floppy;
 	int failed = 0;
 
+	printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
 	MOD_INC_USE_COUNT;
 	while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) {
 		if (!idefloppy_identify_device (drive, drive->id)) {
@@ -1665,27 +2039,5 @@
 	return 0;
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-	return idefloppy_init ();
-}
-
-void cleanup_module (void)
-{
-	ide_drive_t *drive;
-	int failed = 0;
-
-	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 */
+module_init(idefloppy_init);
+module_exit(idefloppy_exit);
diff -urN linux-2.4.9-pre2/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c
--- linux-2.4.9-pre2/drivers/ide/ide-pci.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/ide/ide-pci.c	Mon Dec  3 23:02:45 2001
@@ -27,21 +27,24 @@
 
 #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_MPIIX	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371MX})
 #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_ICH0	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
+#define DEVID_PIIX4E	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
 #define DEVID_PIIX4E2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82443MX_1})
-#define DEVID_ICH	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
+#define DEVID_PIIX4U	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
 #define DEVID_PIIX4U2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82372FB_1})
 #define DEVID_PIIX4NX	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82451NX})
-#define DEVID_ICH2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
-#define DEVID_ICH2M	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
+#define DEVID_PIIX4U3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
+#define DEVID_PIIX4U4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
 #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_PDC20265	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265})
 #define DEVID_PDC20267	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267})
+#define DEVID_PDC20268  ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268})
+#define DEVID_PDC20268R ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R})
 #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})
@@ -71,10 +74,14 @@
 #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_CS5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
-#define DEVID_AMD7403	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_COBRA_7403})
+#define DEVID_AMD7401	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_COBRA_7401})
 #define DEVID_AMD7409	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7409})
+#define DEVID_AMD7411	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7411})
+#define DEVID_PDCADMA	((ide_pci_devid_t){PCI_VENDOR_ID_PDC,     PCI_DEVICE_ID_PDC_1841})
 #define DEVID_SLC90E66	((ide_pci_devid_t){PCI_VENDOR_ID_EFAR,    PCI_DEVICE_ID_EFAR_SLC90E66_1})
 #define DEVID_OSB4	((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE})
+#define DEVID_CSB5	((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE})
+#define DEVID_ITE8172G	((ide_pci_devid_t){PCI_VENDOR_ID_ITE,     PCI_DEVICE_ID_ITE_IT8172G})
 
 #define	IDE_IGNORE	((void *)-1)
 
@@ -110,20 +117,20 @@
 #define DMA_ALI15X3	NULL
 #endif
 
-#ifdef CONFIG_BLK_DEV_AMD7409
-extern unsigned int pci_init_amd7409(struct pci_dev *, const char *);
-extern unsigned int ata66_amd7409(ide_hwif_t *);
-extern void ide_init_amd7409(ide_hwif_t *);
-extern void ide_dmacapable_amd7409(ide_hwif_t *, unsigned long);
-#define PCI_AMD7409	&pci_init_amd7409
-#define ATA66_AMD7409	&ata66_amd7409
-#define INIT_AMD7409	&ide_init_amd7409
-#define DMA_AMD7409	&ide_dmacapable_amd7409
-#else
-#define PCI_AMD7409	NULL
-#define ATA66_AMD7409	NULL
-#define INIT_AMD7409	NULL
-#define DMA_AMD7409	NULL
+#ifdef CONFIG_BLK_DEV_AMD74XX
+extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *);
+extern unsigned int ata66_amd74xx(ide_hwif_t *);
+extern void ide_init_amd74xx(ide_hwif_t *);
+extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long);
+#define PCI_AMD74XX	&pci_init_amd74xx
+#define ATA66_AMD74XX	&ata66_amd74xx
+#define INIT_AMD74XX	&ide_init_amd74xx
+#define DMA_AMD74XX	&ide_dmacapable_amd74xx
+#else
+#define PCI_AMD74XX	NULL
+#define ATA66_AMD74XX	NULL
+#define INIT_AMD74XX	NULL
+#define DMA_AMD74XX	NULL
 #endif
 
 #ifdef CONFIG_BLK_DEV_CMD64X
@@ -186,8 +193,8 @@
 #define INIT_HPT366	&ide_init_hpt366
 #define DMA_HPT366	&ide_dmacapable_hpt366
 #else
-static byte hpt363_shared_irq = 0;
-static byte hpt363_shared_pin = 0;
+static byte hpt363_shared_irq;
+static byte hpt363_shared_pin;
 #define PCI_HPT366	NULL
 #define ATA66_HPT366	NULL
 #define INIT_HPT366	NULL
@@ -208,17 +215,20 @@
 #define INIT_OPTI621	NULL
 #endif
 
-#ifdef CONFIG_BLK_DEV_OSB4
-extern unsigned int pci_init_osb4(struct pci_dev *, const char *);
-extern unsigned int ata66_osb4(ide_hwif_t *);
-extern void ide_init_osb4(ide_hwif_t *);
-#define PCI_OSB4        &pci_init_osb4
-#define ATA66_OSB4      &ata66_osb4
-#define INIT_OSB4       &ide_init_osb4
-#else
-#define PCI_OSB4        NULL
-#define ATA66_OSB4      NULL
-#define INIT_OSB4       NULL
+#ifdef CONFIG_BLK_DEV_PDC_ADMA
+extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *);
+extern unsigned int ata66_pdcadma(ide_hwif_t *);
+extern void ide_init_pdcadma(ide_hwif_t *);
+extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long);
+#define PCI_PDCADMA	&pci_init_pdcadma
+#define ATA66_PDCADMA	&ata66_pdcadma
+#define INIT_PDCADMA	&ide_init_pdcadma
+#define DMA_PDCADMA	&ide_dmacapable_pdcadma
+#else
+#define PCI_PDCADMA	IDE_IGNORE
+#define ATA66_PDCADMA	IDE_IGNORE
+#define INIT_PDCADMA	IDE_IGNORE
+#define DMA_PDCADMA	IDE_IGNORE
 #endif
 
 #ifdef CONFIG_BLK_DEV_PDC202XX
@@ -247,6 +257,18 @@
 #define INIT_PIIX	NULL
 #endif
 
+#ifdef CONFIG_BLK_DEV_IT8172
+extern unsigned int pci_init_it8172(struct pci_dev *, const char *);
+extern unsigned int ata66_it8172(ide_hwif_t *);
+extern void ide_init_it8172(ide_hwif_t *);
+#define PCI_IT8172	&pci_init_it8172
+#define INIT_IT8172	&ide_init_it8172
+#else
+#define PCI_IT8172	NULL
+#define ATA66_IT8172	NULL
+#define INIT_IT8172	NULL
+#endif
+
 #ifdef CONFIG_BLK_DEV_RZ1000
 extern void ide_init_rz1000(ide_hwif_t *);
 #define INIT_RZ1000	&ide_init_rz1000
@@ -256,6 +278,19 @@
 
 #define INIT_SAMURAI	NULL
 
+#ifdef CONFIG_BLK_DEV_SVWKS
+extern unsigned int pci_init_svwks(struct pci_dev *, const char *);
+extern unsigned int ata66_svwks(ide_hwif_t *);
+extern void ide_init_svwks(ide_hwif_t *);
+#define PCI_SVWKS	&pci_init_svwks
+#define ATA66_SVWKS	&ata66_svwks
+#define INIT_SVWKS	&ide_init_svwks
+#else
+#define PCI_SVWKS	NULL
+#define ATA66_SVWKS	NULL
+#define INIT_SVWKS	NULL
+#endif
+
 #ifdef CONFIG_BLK_DEV_SIS5513
 extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
 extern unsigned int ata66_sis5513(ide_hwif_t *);
@@ -339,21 +374,34 @@
 static ide_pci_device_t ide_pci_chipsets[] __initdata = {
 	{DEVID_PIIXa,	"PIIX",		NULL,		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
 	{DEVID_PIIXb,	"PIIX",		NULL,		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_MPIIX,	"MPIIX",	NULL,		NULL,		INIT_PIIX,	NULL,		{{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX3,	"PIIX3",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
 	{DEVID_PIIX4,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_ICH0,	"ICH0",		PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4E,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4E2,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_ICH,	"ICH",		PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4U2,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4NX,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_ICH2,	"ICH2",		PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_ICH2M,	"ICH2-M",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U3,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U4, "PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_VIA_IDE,	"VIA_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_VP_IDE,	"VP_IDE",	PCI_VIA82CXXX,	ATA66_VIA82CXXX,INIT_VIA82CXXX,	DMA_VIA82CXXX,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
+#ifdef CONFIG_PDC202XX_FORCE
+        {DEVID_PDC20246,"PDC20246",	PCI_PDC202XX,	NULL,		INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+        {DEVID_PDC20262,"PDC20262",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	48 },
+        {DEVID_PDC20265,"PDC20265",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	48 },
+        {DEVID_PDC20267,"PDC20267",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	48 },
+#else /* !CONFIG_PDC202XX_FORCE */
 	{DEVID_PDC20246,"PDC20246",	PCI_PDC202XX,	NULL,		INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
 	{DEVID_PDC20262,"PDC20262",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
 	{DEVID_PDC20265,"PDC20265",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
 	{DEVID_PDC20267,"PDC20267",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
+#endif
+	{DEVID_PDC20268,"PDC20268",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+	/* Promise used a different PCI ident for the raid card apparently to try and
+	   prevent Linux detecting it and using our own raid code. We want to detect
+	   it for the ataraid drivers, so we have to list both here.. */
+	{DEVID_PDC20268R,"PDC20268",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
 	{DEVID_RZ1000,	"RZ1000",	NULL,		NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
 	{DEVID_RZ1001,	"RZ1001",	NULL,		NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
 	{DEVID_SAMURAI,	"SAMURAI",	NULL,		NULL,		INIT_SAMURAI,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
@@ -382,10 +430,14 @@
 	{DEVID_CY82C693,"CY82C693",	PCI_CY82C693,	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_CS5530,	"CS5530",	PCI_CS5530,	NULL,		INIT_CS5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_AMD7403,	"AMD7403",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_AMD7409,	"AMD7409",	PCI_AMD7409,	ATA66_AMD7409,	INIT_AMD7409,	DMA_AMD7409,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
+	{DEVID_AMD7401,	"AMD7401",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_AMD7409,	"AMD7409",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
+	{DEVID_AMD7411,	"AMD7411",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
+	{DEVID_PDCADMA,	"PDCADMA",	PCI_PDCADMA,	ATA66_PDCADMA,	INIT_PDCADMA,	DMA_PDCADMA,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	0 },
 	{DEVID_SLC90E66,"SLC90E66",	PCI_SLC90E66,	ATA66_SLC90E66,	INIT_SLC90E66,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-        {DEVID_OSB4,    "ServerWorks OSB4",     PCI_OSB4,       ATA66_OSB4,     INIT_OSB4,      NULL,   {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
+        {DEVID_OSB4,    "ServerWorks OSB4",		PCI_SVWKS,	ATA66_SVWKS,	INIT_SVWKS,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CSB5,	"ServerWorks CSB5",		PCI_SVWKS,	ATA66_SVWKS,	INIT_SVWKS,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_ITE8172G,"IT8172G",	PCI_IT8172,	NULL,	INIT_IT8172,	NULL,		{{0x00,0x00,0x00}, {0x40,0x00,0x01}},	ON_BOARD,	0 },
 	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
 /*
@@ -401,6 +453,7 @@
 		case PCI_DEVICE_ID_PROMISE_20262:
 		case PCI_DEVICE_ID_PROMISE_20265:
 		case PCI_DEVICE_ID_PROMISE_20267:
+		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 		case PCI_DEVICE_ID_ARTOP_ATP860:
 		case PCI_DEVICE_ID_ARTOP_ATP860R:
@@ -528,9 +581,11 @@
 	byte tmp = 0;
 	ide_hwif_t *hwif, *mate = NULL;
 	unsigned int class_rev;
+	static int secondpdc = 0;
 
 #ifdef CONFIG_IDEDMA_AUTO
-	autodma = 1;
+	if (!noautodma)
+		autodma = 1;
 #endif
 
 	pci_enable_device(dev);
@@ -628,8 +683,18 @@
 	for (port = 0; port <= 1; ++port) {
 		unsigned long base = 0, ctl = 0;
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
+	
+		/* 
+		 * If this is a Promise FakeRaid controller, the 2nd controller will be marked as 
+		 * disabled while it is actually there and enabled by the bios for raid purposes. 
+		 * Skip the normal "is it enabled" test for those.
+		 */
+		if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1)  ) 
+			goto controller_ok;
+			
 		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
 			continue;	/* port not enabled */
+controller_ok:			
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03))
 			return;
 		if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
@@ -679,6 +744,9 @@
 			hwif->irq = hwif->channel ? 15 : 14;
 			goto bypass_umc_dma;
 		}
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX))
+			goto bypass_piix_dma;
+
 		if (hwif->udma_four) {
 			printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name);
 		} else {
@@ -688,7 +756,9 @@
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) ||
-		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X))
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)  ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE))
 			autodma = 0;
 		if (autodma)
 			hwif->autodma = 1;
@@ -696,6 +766,7 @@
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) ||
@@ -732,6 +803,7 @@
 			}
 		}
 #endif	/* CONFIG_BLK_DEV_IDEDMA */
+bypass_piix_dma:
 bypass_umc_dma:
 		if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
 			d->init_hwif(hwif);
@@ -760,7 +832,7 @@
 
 	switch(class_rev) {
 		case 4:
-		case 3:	printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
+		case 3:	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
 			ide_setup_pci_device(dev, d);
 			return;
 		default:	break;
@@ -779,16 +851,22 @@
 			if (hpt363_shared_pin && hpt363_shared_irq) {
 				d->bootable = ON_BOARD;
 				printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2);
+#if 0
+				/* I forgot why I did this once, but it fixed something. */
+				pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
+				printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
+				pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
+#endif
 			}
 			break;
 		}
 	}
-	printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
+	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
 	ide_setup_pci_device(dev, d);
 	if (!dev2)
 		return;
 	d2 = d;
-	printk("%s: IDE controller on PCI slot %s\n", d2->name, dev2->slot_name);
+	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
 	ide_setup_pci_device(dev2, d2);
 }
 
@@ -810,16 +888,18 @@
 		return;
 	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
 		return;	/* CY82C693 is more than only a IDE controller */
+	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
+		return;	/* IT8172G is also more than only an IDE controller */
 	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
 		return;	/* UM8886A/BF pair */
 	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366))
 		hpt366_device_order_fixup(dev, d);
 	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 slot %s, VID=%04x, DID=%04x\n",
-			       d->name, dev->slot_name, devid.vid, devid.did);
+			printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
+			       d->name, dev->bus->number, dev->devfn, devid.vid, devid.did);
 		else
-			printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
+			printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
 		ide_setup_pci_device(dev, d);
 	}
 }
diff -urN linux-2.4.9-pre2/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- linux-2.4.9-pre2/drivers/ide/ide-probe.c	Sun Mar 18 09:25:02 2001
+++ linux/drivers/ide/ide-probe.c	Mon Dec  3 23:02:45 2001
@@ -681,9 +681,9 @@
 	 */
 	if (!match || match->irq != hwif->irq) {
 #ifdef CONFIG_IDEPCI_SHARE_IRQ
-		int sa = (hwif->chipset == ide_pci) ? SA_SHIRQ : SA_INTERRUPT;
+		int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT;
 #else /* !CONFIG_IDEPCI_SHARE_IRQ */
-		int sa = (hwif->chipset == ide_pci) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
+		int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
 #endif /* CONFIG_IDEPCI_SHARE_IRQ */
 		if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
 			if (!match)
diff -urN linux-2.4.9-pre2/drivers/ide/ide-proc.c linux/drivers/ide/ide-proc.c
--- linux-2.4.9-pre2/drivers/ide/ide-proc.c	Thu Oct 26 14:11:39 2000
+++ linux/drivers/ide/ide-proc.c	Mon Dec  3 23:02:45 2001
@@ -81,10 +81,10 @@
 extern byte ali_proc;
 int (*ali_display_info)(char *, char **, off_t, int) = NULL;
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
-#ifdef CONFIG_BLK_DEV_AMD7409
-extern byte amd7409_proc;
-int (*amd7409_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_AMD7409 */
+#ifdef CONFIG_BLK_DEV_AMD74XX
+extern byte amd74xx_proc;
+int (*amd74xx_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_AMD74XX */
 #ifdef CONFIG_BLK_DEV_CMD64X
 extern byte cmd64x_proc;
 int (*cmd64x_display_info)(char *, char **, off_t, int) = NULL;
@@ -101,10 +101,6 @@
 extern byte hpt366_proc;
 int (*hpt366_display_info)(char *, char **, off_t, int) = NULL;
 #endif /* CONFIG_BLK_DEV_HPT366 */
-#ifdef CONFIG_BLK_DEV_OSB4
-extern byte osb4_proc;
-int (*osb4_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_OSB4 */
 #ifdef CONFIG_BLK_DEV_PDC202XX
 extern byte pdc202xx_proc;
 int (*pdc202xx_display_info)(char *, char **, off_t, int) = NULL;
@@ -113,6 +109,10 @@
 extern byte piix_proc;
 int (*piix_display_info)(char *, char **, off_t, int) = NULL;
 #endif /* CONFIG_BLK_DEV_PIIX */
+#ifdef CONFIG_BLK_DEV_SVWKS
+extern byte svwks_proc;
+int (*svwks_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_SVWKS */
 #ifdef CONFIG_BLK_DEV_SIS5513
 extern byte sis_proc;
 int (*sis_display_info)(char *, char **, off_t, int) = NULL;
@@ -817,10 +817,10 @@
 	if ((ali_display_info) && (ali_proc))
 		create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
-#ifdef CONFIG_BLK_DEV_AMD7409
-	if ((amd7409_display_info) && (amd7409_proc))
-		create_proc_info_entry("amd7409", 0, proc_ide_root, amd7409_display_info);
-#endif /* CONFIG_BLK_DEV_AMD7409 */
+#ifdef CONFIG_BLK_DEV_AMD74XX
+	if ((amd74xx_display_info) && (amd74xx_proc))
+		create_proc_info_entry("amd74xx", 0, proc_ide_root, amd74xx_display_info);
+#endif /* CONFIG_BLK_DEV_AMD74XX */
 #ifdef CONFIG_BLK_DEV_CMD64X
 	if ((cmd64x_display_info) && (cmd64x_proc))
 		create_proc_info_entry("cmd64x", 0, proc_ide_root, cmd64x_display_info);
@@ -837,10 +837,10 @@
 	if ((hpt366_display_info) && (hpt366_proc))
 		create_proc_info_entry("hpt366", 0, proc_ide_root, hpt366_display_info);
 #endif /* CONFIG_BLK_DEV_HPT366 */
-#ifdef CONFIG_BLK_DEV_OSB4
-	if ((osb4_display_info) && (osb4_proc))
-		create_proc_info_entry("osb4", 0, proc_ide_root, osb4_display_info);
-#endif /* CONFIG_BLK_DEV_OSB4 */
+#ifdef CONFIG_BLK_DEV_SVWKS
+	if ((svwks_display_info) && (svwks_proc))
+		create_proc_info_entry("svwks", 0, proc_ide_root, svwks_display_info);
+#endif /* CONFIG_BLK_DEV_SVWKS */
 #ifdef CONFIG_BLK_DEV_PDC202XX
 	if ((pdc202xx_display_info) && (pdc202xx_proc))
 		create_proc_info_entry("pdc202xx", 0, proc_ide_root, pdc202xx_display_info);
@@ -877,10 +877,10 @@
 	if ((ali_display_info) && (ali_proc))
 		remove_proc_entry("ide/ali",0);
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
-#ifdef CONFIG_BLK_DEV_AMD7409
-	if ((amd7409_display_info) && (amd7409_proc))
-		remove_proc_entry("ide/amd7409",0);
-#endif /* CONFIG_BLK_DEV_AMD7409 */
+#ifdef CONFIG_BLK_DEV_AMD74XX
+	if ((amd74xx_display_info) && (amd74xx_proc))
+		remove_proc_entry("ide/amd74xx",0);
+#endif /* CONFIG_BLK_DEV_AMD74XX */
 #ifdef CONFIG_BLK_DEV_CMD64X
 	if ((cmd64x_display_info) && (cmd64x_proc))
 		remove_proc_entry("ide/cmd64x",0);
@@ -897,10 +897,6 @@
 	if ((hpt366_display_info) && (hpt366_proc))
 		remove_proc_entry("ide/hpt366",0);
 #endif /* CONFIG_BLK_DEV_HPT366 */
-#ifdef CONFIG_BLK_DEV_OSB4
-	if ((osb4_display_info) && (osb4_proc))
-		remove_proc_entry("ide/osb4",0);
-#endif /* CONFIG_BLK_DEV_OSB4 */
 #ifdef CONFIG_BLK_DEV_PDC202XX
 	if ((pdc202xx_display_info) && (pdc202xx_proc))
 		remove_proc_entry("ide/pdc202xx",0);
@@ -909,6 +905,10 @@
 	if ((piix_display_info) && (piix_proc))
 		remove_proc_entry("ide/piix",0);
 #endif /* CONFIG_BLK_DEV_PIIX */
+#ifdef CONFIG_BLK_DEV_SVWKS
+	if ((svwks_display_info) && (svwks_proc))
+		remove_proc_entry("ide/svwks",0);
+#endif /* CONFIG_BLK_DEV_SVWKS */
 #ifdef CONFIG_BLK_DEV_SIS5513
 	if ((sis_display_info) && (sis_proc))
 		remove_proc_entry("ide/sis", 0);
diff -urN linux-2.4.9-pre2/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c
--- linux-2.4.9-pre2/drivers/ide/ide-tape.c	Fri Jul 20 12:41:02 2001
+++ linux/drivers/ide/ide-tape.c	Mon Dec  3 23:02:45 2001
@@ -4099,9 +4099,14 @@
 	}
 	if (rq_ptr->errors == IDETAPE_ERROR_EOD)
 		return 0;
-	else if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+	if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) {
+		idetape_switch_buffers (tape, tape->first_stage);
 		set_bit (IDETAPE_FILEMARK, &tape->flags);
-	else {
+#if USE_IOTRACE
+		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+#endif
+		calculate_speeds(drive);
+	} else {
 		idetape_switch_buffers (tape, tape->first_stage);
 		if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) {
 #if ONSTREAM_DEBUG
@@ -6127,24 +6132,33 @@
 
 #endif
 
+static int idetape_reinit (ide_drive_t *drive)
+{
+	return 0;
+}
+
 /*
  *	IDE subdriver functions, registered with ide.c
  */
 static ide_driver_t idetape_driver = {
-	name:		"ide-tape",
-	version:	IDETAPE_VERSION,
-	media:		ide_tape,
-	busy:		1,
-	supports_dma:	1,
-	supports_dsc_overlap: 1,
-	cleanup:	idetape_cleanup,
-	do_request:	idetape_do_request,
-	end_request:	idetape_end_request,
-	ioctl:		idetape_blkdev_ioctl,
-	open:		idetape_blkdev_open,
-	release:	idetape_blkdev_release,
-	pre_reset:	idetape_pre_reset,
-	proc:		idetape_proc,
+	name:			"ide-tape",
+	version:		IDETAPE_VERSION,
+	media:			ide_tape,
+	busy:			1,
+	supports_dma:		1,
+	supports_dsc_overlap: 	1,
+	cleanup:		idetape_cleanup,
+	do_request:		idetape_do_request,
+	end_request:		idetape_end_request,
+	ioctl:			idetape_blkdev_ioctl,
+	open:			idetape_blkdev_open,
+	release:		idetape_blkdev_release,
+	media_change:		NULL,
+	revalidate:		NULL,
+	pre_reset:		idetape_pre_reset,
+	capacity:		NULL,
+	proc:			idetape_proc,
+	driver_reinit:		idetape_reinit,
 };
 
 int idetape_init (void);
@@ -6167,6 +6181,21 @@
 	release:	idetape_chrdev_release,
 };
 
+MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
+
+static void __exit idetape_exit (void)
+{
+	ide_drive_t *drive;
+	int minor;
+
+	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);
+	}
+	ide_unregister_module(&idetape_module);
+}
+
 /*
  *	idetape_init will register the driver for each tape.
  */
@@ -6252,22 +6281,5 @@
 	return 0;
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-	return idetape_init ();
-}
-
-void cleanup_module (void)
-{
-	ide_drive_t *drive;
-	int minor;
-
-	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);
-	}
-	ide_unregister_module(&idetape_module);
-}
-#endif /* MODULE */
+module_init(idetape_init);
+module_exit(idetape_exit);
diff -urN linux-2.4.9-pre2/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.4.9-pre2/drivers/ide/ide.c	Thu Jul 19 21:02:28 2001
+++ linux/drivers/ide/ide.c	Mon Dec  3 23:02:45 2001
@@ -162,6 +162,9 @@
 #include <linux/kmod.h>
 #endif /* CONFIG_KMOD */
 
+/* default maximum number of failures */
+#define IDE_DEFAULT_MAX_FAILURES 	1
+
 static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR };
 
 static int	idebus_parameter; /* holds the "idebus=" parameter */
@@ -249,6 +252,7 @@
 	hwif->name[1]	= 'd';
 	hwif->name[2]	= 'e';
 	hwif->name[3]	= '0' + index;
+	hwif->bus_state = BUSSTATE_ON;
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t *drive = &hwif->drives[unit];
 
@@ -263,6 +267,7 @@
 		drive->name[0]			= 'h';
 		drive->name[1]			= 'd';
 		drive->name[2]			= 'a' + (index * MAX_DRIVES) + unit;
+		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;
 		init_waitqueue_head(&drive->wqueue);
 	}
 }
@@ -377,7 +382,19 @@
  */
 void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
-	byte io_32bit = drive->io_32bit;
+	byte io_32bit;
+
+	/* first check if this controller has defined a special function
+	 * for handling polled ide transfers
+	 */
+
+	if(HWIF(drive)->ideproc) {
+		HWIF(drive)->ideproc(ideproc_ide_input_data,
+				     drive, buffer, wcount);
+		return;
+	}
+
+	io_32bit = drive->io_32bit;
 
 	if (io_32bit) {
 #if SUPPORT_VLB_SYNC
@@ -410,7 +427,15 @@
  */
 void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
-	byte io_32bit = drive->io_32bit;
+	byte io_32bit;
+
+	if(HWIF(drive)->ideproc) {
+		HWIF(drive)->ideproc(ideproc_ide_output_data,
+				     drive, buffer, wcount);
+		return;
+	}
+
+	io_32bit = drive->io_32bit;
 
 	if (io_32bit) {
 #if SUPPORT_VLB_SYNC
@@ -447,6 +472,12 @@
  */
 void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
+	if(HWIF(drive)->ideproc) {
+		HWIF(drive)->ideproc(ideproc_atapi_input_bytes,
+				     drive, buffer, bytecount);
+		return;
+	}
+
 	++bytecount;
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
 	if (MACH_IS_ATARI || MACH_IS_Q40) {
@@ -462,6 +493,12 @@
 
 void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
+	if(HWIF(drive)->ideproc) {
+		HWIF(drive)->ideproc(ideproc_atapi_output_bytes,
+				     drive, buffer, bytecount);
+		return;
+	}
+
 	++bytecount;
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
 	if (MACH_IS_ATARI || MACH_IS_Q40) {
@@ -512,10 +549,20 @@
 {
 	struct request *rq;
 	unsigned long flags;
+	ide_drive_t *drive = hwgroup->drive;
 
 	spin_lock_irqsave(&io_request_lock, flags);
 	rq = hwgroup->rq;
 
+	/*
+	 * decide whether to reenable DMA -- 3 is a random magic for now,
+	 * if we DMA timeout more than 3 times, just stay in PIO
+	 */
+	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+		drive->state = 0;
+		hwgroup->hwif->dmaproc(ide_dma_on, drive);
+	}
+
 	if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) {
 		add_blkdev_randomness(MAJOR(rq->rq_dev));
 		blkdev_dequeue_request(rq);
@@ -637,11 +684,14 @@
 			return ide_started;	/* continue polling */
 		}
 		printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
+		drive->failures++;
 	} else  {
 		printk("%s: reset: ", hwif->name);
-		if ((tmp = GET_ERR()) == 1)
+		if ((tmp = GET_ERR()) == 1) {
 			printk("success\n");
-		else {
+			drive->failures = 0;
+		} else {
+			drive->failures++;
 #if FANCY_STATUS_DUMPS
 			printk("master: ");
 			switch (tmp & 0x7f) {
@@ -1049,6 +1099,12 @@
 	int i;
 	unsigned long flags;
  
+	/* bail early if we've exceeded max_failures */
+	if (drive->max_failures && (drive->failures > drive->max_failures)) {
+		*startstop = ide_stopped;
+		return 1;
+	}
+
 	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
 	if ((stat = GET_STAT()) & BUSY_STAT) {
 		__save_flags(flags);	/* local CPU only */
@@ -1145,6 +1201,11 @@
 #ifdef DEBUG
 	printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
 #endif
+	/* bail early if we've exceeded max_failures */
+	if (drive->max_failures && (drive->failures > drive->max_failures)) {
+		goto kill_rq;
+	}
+
 	if (unit >= MAX_DRIVES) {
 		printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
 		goto kill_rq;
@@ -1200,6 +1261,19 @@
 	return ide_stopped;
 }
 
+ide_startstop_t restart_request (ide_drive_t *drive)
+{
+	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	hwgroup->handler = NULL;
+	del_timer(&hwgroup->timer);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	return start_request(drive);
+}
+
 /*
  * ide_stall_queue() can be used by a drive to give excess bandwidth back
  * to the hwgroup by sleeping for timeout jiffies.
@@ -1388,6 +1462,49 @@
 }
 
 /*
+ * un-busy the hwgroup etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+void ide_dma_timeout_retry(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct request *rq;
+
+	/*
+	 * end current dma transaction
+	 */
+	(void) hwif->dmaproc(ide_dma_end, drive);
+
+	/*
+	 * complain a little, later we might remove some of this verbosity
+	 */
+	printk("%s: timeout waiting for DMA\n", drive->name);
+	(void) hwif->dmaproc(ide_dma_timeout, drive);
+
+	/*
+	 * disable dma for now, but remember that we did so because of
+	 * a timeout -- we'll reenable after we finish this next request
+	 * (or rather the first chunk of it) in pio.
+	 */
+	drive->retry_pio++;
+	drive->state = DMA_PIO_RETRY;
+	(void) hwif->dmaproc(ide_dma_off_quietly, drive);
+
+	/*
+	 * un-busy drive etc (hwgroup->busy is cleared on return) and
+	 * make sure request is sane
+	 */
+	rq = HWGROUP(drive)->rq;
+	HWGROUP(drive)->rq = NULL;
+
+	rq->errors = 0;
+	rq->sector = rq->bh->b_rsector;
+	rq->current_nr_sectors = rq->bh->b_size >> 9;
+	rq->buffer = rq->bh->b_data;
+}
+
+/*
  * ide_timer_expiry() is our timeout function for all drive operations.
  * But note that it can also be invoked as a result of a "sleep" operation
  * triggered by the mod_timer() call in ide_do_request.
@@ -1460,11 +1577,10 @@
 				startstop = handler(drive);
 			} else {
 				if (drive->waiting_for_dma) {
-					(void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
-					printk("%s: timeout waiting for DMA\n", drive->name);
-					(void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive);
-				}
-				startstop = ide_error(drive, "irq timeout", GET_STAT());
+					startstop = ide_stopped;
+					ide_dma_timeout_retry(drive);
+				} else
+					startstop = ide_error(drive, "irq timeout", GET_STAT());
 			}
 			set_recovery_timer(hwif);
 			drive->service_time = jiffies - drive->service_start;
@@ -2089,7 +2205,10 @@
 	hwif->maskproc		= old_hwif.maskproc;
 	hwif->quirkproc		= old_hwif.quirkproc;
 	hwif->rwproc		= old_hwif.rwproc;
+	hwif->ideproc		= old_hwif.ideproc;
 	hwif->dmaproc		= old_hwif.dmaproc;
+	hwif->busproc		= old_hwif.busproc;
+	hwif->bus_state		= old_hwif.bus_state;
 	hwif->dma_base		= old_hwif.dma_base;
 	hwif->dma_extra		= old_hwif.dma_extra;
 	hwif->config_data	= old_hwif.config_data;
@@ -2671,6 +2790,20 @@
 		case BLKELVSET:
 			return blk_ioctl(inode->i_rdev, cmd, arg);
 
+		case HDIO_GET_BUSSTATE:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if (put_user(HWIF(drive)->bus_state, (long *)arg))
+				return -EFAULT;
+			return 0;
+
+		case HDIO_SET_BUSSTATE:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if (HWIF(drive)->busproc)
+				HWIF(drive)->busproc(HWIF(drive), arg);
+			return 0;
+
 		default:
 			if (drive->driver != NULL)
 				return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg);
@@ -3196,6 +3329,12 @@
 	}
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_ETRAX_IDE
+	{
+		extern void init_e100_ide(void);
+		init_e100_ide();
+	}
+#endif /* CONFIG_ETRAX_IDE */
 #ifdef CONFIG_BLK_DEV_CMD640
 	{
 		extern void ide_probe_for_cmd640x(void);
@@ -3373,6 +3512,13 @@
 	return ide_stopped;
 }
 
+static int default_driver_reinit (ide_drive_t *drive)
+{
+	printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name);
+
+	return 0;
+}
+
 static void setup_driver_defaults (ide_drive_t *drive)
 {
 	ide_driver_t *d = drive->driver;
@@ -3387,6 +3533,7 @@
 	if (d->pre_reset == NULL)	d->pre_reset = default_pre_reset;
 	if (d->capacity == NULL)	d->capacity = default_capacity;
 	if (d->special == NULL)		d->special = default_special;
+	if (d->driver_reinit == NULL)	d->driver_reinit = default_driver_reinit;
 }
 
 ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n)
@@ -3536,6 +3683,7 @@
 EXPORT_SYMBOL(ide_fixstring);
 EXPORT_SYMBOL(ide_wait_stat);
 EXPORT_SYMBOL(ide_do_reset);
+EXPORT_SYMBOL(restart_request);
 EXPORT_SYMBOL(ide_init_drive_cmd);
 EXPORT_SYMBOL(ide_do_drive_cmd);
 EXPORT_SYMBOL(ide_end_drive_cmd);
diff -urN linux-2.4.9-pre2/drivers/ide/it8172.c linux/drivers/ide/it8172.c
--- linux-2.4.9-pre2/drivers/ide/it8172.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ide/it8172.c	Mon Dec  3 23:02:45 2001
@@ -0,0 +1,283 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *      IT8172 IDE controller support
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              stevel@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#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 <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/it8172/it8172_int.h>
+
+#include "ide_modes.h"
+
+/*
+ * Prototypes
+ */
+static void it8172_tune_drive (ide_drive_t *drive, byte pio);
+#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
+static byte it8172_dma_2_pio (byte xfer_rate);
+static int it8172_tune_chipset (ide_drive_t *drive, byte speed);
+static int it8172_config_drive_for_dma (ide_drive_t *drive);
+static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
+#endif
+unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name);
+void __init ide_init_it8172 (ide_hwif_t *hwif);
+
+
+/*
+ *  Based on settings done by AMI BIOS
+ *  (might be usefull if drive is not registered in CMOS for any reason).
+ */
+static void it8172_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);
+}
+
+#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
+/*
+ *
+ */
+static byte it8172_dma_2_pio (byte xfer_rate)
+{
+    switch(xfer_rate) {
+    case XFER_UDMA_5:
+    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;
+    }
+}
+
+static int it8172_tune_chipset (ide_drive_t *drive, byte speed)
+{
+    ide_hwif_t *hwif	= HWIF(drive);
+    struct pci_dev *dev	= hwif->pci_dev;
+    int a_speed		= 3 << (drive->dn * 4);
+    int u_flag		= 1 << drive->dn;
+    int u_speed		= 0;
+    int err		= 0;
+    byte reg48, reg4a;
+
+    pci_read_config_byte(dev, 0x48, &reg48);
+    pci_read_config_byte(dev, 0x4a, &reg4a);
+
+    switch(speed) {
+    case XFER_UDMA_4:
+    case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
+    case XFER_UDMA_5:
+    case XFER_UDMA_3:
+    case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
+    case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
+    case XFER_MW_DMA_2:
+    case XFER_MW_DMA_1:
+    case XFER_SW_DMA_2:	break;
+    default:		return -1;
+    }
+
+    if (speed >= XFER_UDMA_0) {
+	if (!(reg48 & u_flag))
+	    pci_write_config_byte(dev, 0x48, reg48|u_flag);
+	if (!(reg4a & u_speed)) {
+	    pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed);
+	    pci_write_config_byte(dev, 0x4a, reg4a|u_speed);
+	}
+    }
+    if (speed < XFER_UDMA_0) {
+	if (reg48 & u_flag)
+	    pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+	if (reg4a & a_speed)
+	    pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed);
+    }
+
+    it8172_tune_drive(drive, it8172_dma_2_pio(speed));
+
+#if IT8172_DEBUG
+    printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
+#endif
+    if (!drive->init_speed)
+	drive->init_speed = speed;
+    err = ide_config_drive_speed(drive, speed);
+    drive->current_speed = speed;
+    return err;
+}
+
+static int it8172_config_drive_for_dma (ide_drive_t *drive)
+{
+    struct hd_driveid *id = drive->id;
+    byte speed;
+
+    if (id->dma_ultra & 0x0010) {
+	speed = XFER_UDMA_2;
+    } else if (id->dma_ultra & 0x0008) {
+	speed = XFER_UDMA_1;
+    } else if (id->dma_ultra & 0x0004) {
+	speed = XFER_UDMA_2;
+    } else if (id->dma_ultra & 0x0002) {
+	speed = XFER_UDMA_1;
+    } else if (id->dma_ultra & 0x0001) {
+	speed = XFER_UDMA_0;
+    } else if (id->dma_mword & 0x0004) {
+	speed = XFER_MW_DMA_2;
+    } else if (id->dma_mword & 0x0002) {
+	speed = XFER_MW_DMA_1;
+    } else if (id->dma_1word & 0x0004) {
+	speed = XFER_SW_DMA_2;
+    } else {
+	speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+    }
+
+    (void) it8172_tune_chipset(drive, speed);
+
+    return ((int)((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+	    ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+	    ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+	    ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+	    ide_dma_off_quietly);
+}
+
+static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+    switch (func) {
+    case ide_dma_check:
+	return ide_dmaproc((ide_dma_action_t)it8172_config_drive_for_dma(drive),
+			   drive);
+    default :
+	break;
+    }
+    /* Other cases are done by generic IDE-DMA code. */
+    return ide_dmaproc(func, drive);
+}
+#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */
+
+unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name)
+{
+    unsigned char progif;
+    
+    /*
+     * Place both IDE interfaces into PCI "native" mode
+     */
+    (void)pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+    (void)pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05);    
+
+    return IT8172_IDE_IRQ;
+}
+
+
+void __init ide_init_it8172 (ide_hwif_t *hwif)
+{
+    struct pci_dev* dev = hwif->pci_dev;
+    unsigned long cmdBase, ctrlBase;
+    
+    hwif->tuneproc = &it8172_tune_drive;
+    hwif->drives[0].autotune = 1;
+    hwif->drives[1].autotune = 1;
+
+    if (!hwif->dma_base)
+	return;
+
+#ifndef CONFIG_BLK_DEV_IDEDMA
+    hwif->autodma = 0;
+#else /* CONFIG_BLK_DEV_IDEDMA */
+#ifdef CONFIG_IT8172_TUNING
+    hwif->autodma = 1;
+    hwif->dmaproc = &it8172_dmaproc;
+    hwif->speedproc = &it8172_tune_chipset;
+#endif /* CONFIG_IT8172_TUNING */
+#endif /* !CONFIG_BLK_DEV_IDEDMA */
+
+    cmdBase = dev->resource[0].start;
+    ctrlBase = dev->resource[1].start;
+    
+    ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL);
+    memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+    hwif->noprobe = 0;
+}
diff -urN linux-2.4.9-pre2/drivers/ide/osb4.c linux/drivers/ide/osb4.c
--- linux-2.4.9-pre2/drivers/ide/osb4.c	Tue May  1 16:05:00 2001
+++ linux/drivers/ide/osb4.c	Wed Dec 31 16:00:00 1969
@@ -1,459 +0,0 @@
-/*
- * linux/drivers/block/osb4.c		Version 0.2	17 Oct 2000
- *
- *  Copyright (C) 2000 Cobalt Networks, Inc. <asun@cobalt.com>
- *  May be copied or modified under the terms of the GNU General Public License
- *
- *  interface borrowed from alim15x3.c:
- *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
- *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
- *
- *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *
- *  IDE support for the ServerWorks OSB4 IDE chipset
- *
- * here's the default lspci:
- *
- * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP])
- *	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
- *	Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
- *	Latency: 255
- *	Region 4: I/O ports at c200
- * 00: 66 11 11 02 05 01 00 02 00 8a 01 01 00 ff 80 00
- * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 20: 01 c2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 40: 99 99 99 99 ff ff ff ff 0c 0c 00 00 00 00 00 00
- * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- */
-
-#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 <linux/init.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-
-#include "ide_modes.h"
-
-#define OSB4_DEBUG_DRIVE_INFO		0
-
-#define DISPLAY_OSB4_TIMINGS
-
-#if defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static struct pci_dev *bmide_dev;
-
-static int osb4_get_info(char *, char **, off_t, int);
-extern int (*osb4_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
-
-static int osb4_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	u32 bibma = pci_resource_start(bmide_dev, 4);
-	u16 reg56;
-	u8  c0 = 0, c1 = 0, reg54;
-
-	pci_read_config_byte(bmide_dev, 0x54, &reg54);
-	pci_read_config_word(bmide_dev, 0x56, &reg56);
-
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
-	c0 = inb_p((unsigned short)bibma + 0x02);
-	c1 = inb_p((unsigned short)bibma + 0x0a);
-
-	p += sprintf(p, "\n                                ServerWorks OSB4 Chipset.\n");
-	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
-	p += sprintf(p, "                %sabled                         %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
-			(c0&0x20) ? "yes" : "no ",
-			(c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ",
-			(c1&0x40) ? "yes" : "no " );
-	p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
-			(reg54 & 0x01) ? "yes" : "no ",
-			(reg54 & 0x02) ? "yes" : "no ",
-			(reg54 & 0x04) ? "yes" : "no ",
-			(reg54 & 0x08) ? "yes" : "no " );
-	p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
-		     (reg56 & 0x0002) ? "2" : ((reg56 & 0x0001) ? "1" : 
-					       ((reg56 & 0x000f) ? "X" : "0")),
-		     (reg56 & 0x0020) ? "2" : ((reg56 & 0x0010) ? "1" : 
-					       ((reg56 & 0x00f0) ? "X" : "0")),
-		     (reg56 & 0x0200) ? "2" : ((reg56 & 0x0100) ? "1" : 
-					       ((reg56 & 0x0f00) ? "X" : "0")),
-		     (reg56 & 0x2000) ? "2" : ((reg56 & 0x1000) ? "1" : 
-					       ((reg56 & 0xf000) ? "X" : "0")));
-	return p-buffer;	 /* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-static byte osb4_revision = 0;
-
-byte osb4_proc = 0;
-
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-static struct pci_dev *isa_dev;
-
-static int osb4_tune_chipset (ide_drive_t *drive, byte speed)
-{
-	byte udma_modes[]	= { 0x00, 0x01, 0x02 };
-	byte dma_modes[]	= { 0x77, 0x21, 0x20 };
-	byte pio_modes[]	= { 0x5d, 0x47, 0x34, 0x22, 0x20 };
-
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
-	byte unit		= (drive->select.b.unit & 0x01);
-#ifdef CONFIG_BLK_DEV_IDEDMA
-	unsigned long dma_base	= hwif->dma_base;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-	int err;
-
-	byte drive_pci		= 0x00;
-	byte drive_pci2		= 0x00;
-	byte drive_pci3		= hwif->channel ? 0x57 : 0x56;
-
-	byte ultra_enable	= 0x00;
-	byte ultra_timing	= 0x00;
-	byte dma_timing		= 0x00;
-	byte pio_timing		= 0x00;
-
-	byte pio	= ide_get_best_pio_mode(drive, 255, 5, NULL);
-
-        switch (drive->dn) {
-		case 0: drive_pci = 0x41; drive_pci2 = 0x45; break;
-		case 1: drive_pci = 0x40; drive_pci2 = 0x44; break;
-		case 2: drive_pci = 0x43; drive_pci2 = 0x47; break;
-		case 3: drive_pci = 0x42; drive_pci2 = 0x46; break;
-		default:
-			return -1;
-	}
-
-	pci_read_config_byte(dev, drive_pci, &pio_timing);
-	pci_read_config_byte(dev, drive_pci2, &dma_timing);
-	pci_read_config_byte(dev, drive_pci3, &ultra_timing);
-	pci_read_config_byte(dev, 0x54, &ultra_enable);
-
-#ifdef DEBUG
-	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
-		drive->name, ultra_timing, dma_timing, pio_timing);
-#endif
-
-	pio_timing	&= ~0xFF;
-	dma_timing	&= ~0xFF;
-	ultra_timing	&= ~(0x0F << (4*unit));
-	ultra_enable	&= ~(0x01 << drive->dn);
-
-	switch(speed) {
-		case XFER_PIO_4:
-		case XFER_PIO_3:
-		case XFER_PIO_2:
-		case XFER_PIO_1:
-		case XFER_PIO_0:
-			pio_timing |= pio_modes[speed - XFER_PIO_0];
-			break;
-#ifdef CONFIG_BLK_DEV_IDEDMA
-		case XFER_MW_DMA_2:
-		case XFER_MW_DMA_1:
-		case XFER_MW_DMA_0:
-			pio_timing |= pio_modes[pio];
-			dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
-			break;
-
-//		case XFER_UDMA_5:
-//		case XFER_UDMA_4:
-//		case XFER_UDMA_3:
-		case XFER_UDMA_2:
-		case XFER_UDMA_1:
-		case XFER_UDMA_0:
-			pio_timing |= pio_modes[pio];
-			dma_timing |= dma_modes[2];
-			ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
-			ultra_enable |= (0x01 << drive->dn);
-#endif
-		default:
-			break;
-	}
-
-#ifdef DEBUG
-	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
-		drive->name, ultra_timing, dma_timing, pio_timing);
-#endif
-
-#if OSB4_DEBUG_DRIVE_INFO
-	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
-#endif /* OSB4_DEBUG_DRIVE_INFO */
-
-	if (!drive->init_speed)
-		drive->init_speed = speed;
-
-	pci_write_config_byte(dev, drive_pci, pio_timing);
-#ifdef CONFIG_BLK_DEV_IDEDMA
-	pci_write_config_byte(dev, drive_pci2, dma_timing);
-	pci_write_config_byte(dev, drive_pci3, ultra_timing);
-	pci_write_config_byte(dev, 0x54, ultra_enable);
-	
-	if (speed > XFER_PIO_4) {
-		outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-	} else {
-		outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
-	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-	err = ide_config_drive_speed(drive, speed);
-	drive->current_speed = speed;
-	return err;
-}
-
-static void config_chipset_for_pio (ide_drive_t *drive)
-{
-	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
-	unsigned short xfer_pio = drive->id->eide_pio_modes;
-	byte			timing, speed, pio;
-
-	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
-
-	if (xfer_pio> 4)
-		xfer_pio = 0;
-
-	if (drive->id->eide_pio_iordy > 0) {
-		for (xfer_pio = 5;
-			xfer_pio>0 &&
-			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
-			xfer_pio--);
-	} else {
-		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
-			   (drive->id->eide_pio_modes & 2) ? 0x04 :
-			   (drive->id->eide_pio_modes & 1) ? 0x03 :
-			   (drive->id->tPIO & 2) ? 0x02 :
-			   (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
-	}
-
-	timing = (xfer_pio >= pio) ? xfer_pio : pio;
-
-	switch(timing) {
-		case 4: speed = XFER_PIO_4;break;
-		case 3: speed = XFER_PIO_3;break;
-		case 2: speed = XFER_PIO_2;break;
-		case 1: speed = XFER_PIO_1;break;
-		default:
-			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
-			break;
-	}
-	(void) osb4_tune_chipset(drive, speed);
-	drive->current_speed = speed;
-}
-
-static void osb4_tune_drive (ide_drive_t *drive, byte pio)
-{
-	byte speed;
-	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) osb4_tune_chipset(drive, speed);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
-	struct hd_driveid *id	= drive->id;
-	byte			speed;
-
-#if 0
-	byte udma_66		= eighty_ninty_three(drive);
-	/* need specs to figure out if osb4 is capable of ata/66/100 */
-	int ultra100		= 0;
-	int ultra66		= 0;
-
-	if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) {
-		speed = XFER_UDMA_5;
-	} else if (id->dma_ultra & 0x0010) {
-		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
-	} else if (id->dma_ultra & 0x0008) {
-		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
-	} else if (id->dma_ultra & 0x0004) {
-#else
-	if (id->dma_ultra & 0x0004) {
-#endif
-		speed = XFER_UDMA_2;
-	} else if (id->dma_ultra & 0x0002) {
-		speed = XFER_UDMA_1;
-	} else if (id->dma_ultra & 0x0001) {
-		speed = XFER_UDMA_0;
-	} else if (id->dma_mword & 0x0004) {
-		speed = XFER_MW_DMA_2;
-	} else if (id->dma_mword & 0x0002) {
-		speed = XFER_MW_DMA_1;
-	} else if (id->dma_1word & 0x0004) {
-		speed = XFER_SW_DMA_2;
-	} else {
-		speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
-	}
-
-	(void) osb4_tune_chipset(drive, speed);
-
-	return ((int)	((id->dma_ultra >> 11) & 7) ? ide_dma_on :
-			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
-			((id->dma_mword >> 8) & 7) ? ide_dma_on :
-			((id->dma_1word >> 8) & 7) ? ide_dma_on :
-						     ide_dma_off_quietly);
-}
-
-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 & 0x002F) {
-				/* 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 & 0x007)) {
-				/* 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);
-}
-
-static int osb4_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	switch (func) {
-		case ide_dma_check:
-			return config_drive_xfer_rate(drive);
-		default :
-			break;
-	}
-	/* Other cases are done by generic IDE-DMA code. */
-	return ide_dmaproc(func, drive);
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-unsigned int __init pci_init_osb4 (struct pci_dev *dev, const char *name)
-{
-	unsigned int reg64;
-
-	pci_read_config_byte(dev, PCI_REVISION_ID, &osb4_revision);
-
-	isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
-
-	pci_read_config_dword(isa_dev, 0x64, &reg64);
-#ifdef DEBUG
-	printk("%s: reg64 == 0x%08x\n", name, reg64);
-#endif
-
-//	reg64 &= ~0x0000A000;
-//#ifdef CONFIG_SMP
-//	reg64 |= 0x00008000;
-//#endif
-	/* Assume the APIC was set up properly by the BIOS for now . If it
-	   wasnt we need to do a fix up _way_ earlier. Bits 15,10,3 control
-	   APIC enable, routing and decode */
-	   
-	reg64 &= ~0x00002000;	
-	pci_write_config_dword(isa_dev, 0x64, reg64);
-
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
-
-#if defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!osb4_proc) {
-		osb4_proc = 1;
-		bmide_dev = dev;
-		osb4_display_info = &osb4_get_info;
-	}
-#endif /* DISPLAY_OSB4_TIMINGS && CONFIG_PROC_FS */
-	return 0;
-}
-
-unsigned int __init ata66_osb4 (ide_hwif_t *hwif)
-{
-	return 0;
-}
-
-void __init ide_init_osb4 (ide_hwif_t *hwif)
-{
-	if (!hwif->irq)
-		hwif->irq = hwif->channel ? 15 : 14;
-
-	hwif->tuneproc = &osb4_tune_drive;
-	hwif->speedproc = &osb4_tune_chipset;
-
-#ifndef CONFIG_BLK_DEV_IDEDMA
-	hwif->drives[0].autotune = 1;
-	hwif->drives[1].autotune = 1;
-	hwif->autodma = 0;
-	return;
-#else /* CONFIG_BLK_DEV_IDEDMA */
-
-	if (hwif->dma_base) {
-		if (!noautodma)
-			hwif->autodma = 1;
-		hwif->dmaproc = &osb4_dmaproc;
-	} else {
-		hwif->autodma = 0;
-		hwif->drives[0].autotune = 1;
-		hwif->drives[1].autotune = 1;
-	}
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
-}
diff -urN linux-2.4.9-pre2/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- linux-2.4.9-pre2/drivers/ide/pdc202xx.c	Tue May  1 16:05:00 2001
+++ linux/drivers/ide/pdc202xx.c	Mon Dec  3 23:02:45 2001
@@ -108,7 +108,7 @@
 	u32 bibma  = pci_resource_start(dev, 4);
 	u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
 	u16 reg50h = 0, pmask = (1<<10), smask = (1<<11);
-	u8 hi = 0, lo = 0;
+	u8 hi = 0, lo = 0, invalid_data_set = 0;
 
         /*
          * at that point bibma+0x2 et bibma+0xa are byte registers
@@ -132,6 +132,10 @@
 	pci_read_config_dword(dev, 0x6c, &reg6ch);
 
 	switch(dev->device) {
+		case PCI_DEVICE_ID_PROMISE_20268:
+			p += sprintf(p, "\n                                PDC20268 TX2 Chipset.\n");
+			invalid_data_set = 1;
+			break;
 		case PCI_DEVICE_ID_PROMISE_20267:
 			p += sprintf(p, "\n                                PDC20267 Chipset.\n");
 			break;
@@ -175,31 +179,38 @@
 	p += sprintf(p, "           Mode %s                      Mode %s\n",
 		(sc1a & 0x01) ? "MASTER" : "PCI   ",
 		(sc1b & 0x01) ? "MASTER" : "PCI   ");
-	p += sprintf(p, "                %s                     %s\n",
-		(sc1d & 0x08) ? "Error       " :
-		((sc1d & 0x05) == 0x05) ? "Not My INTR " :
-		(sc1d & 0x04) ? "Interrupting" :
-		(sc1d & 0x02) ? "FIFO Full   " :
-		(sc1d & 0x01) ? "FIFO Empty  " : "????????????",
-		(sc1d & 0x80) ? "Error       " :
-		((sc1d & 0x50) == 0x50) ? "Not My INTR " :
-		(sc1d & 0x40) ? "Interrupting" :
-		(sc1d & 0x20) ? "FIFO Full   " :
-		(sc1d & 0x10) ? "FIFO Empty  " : "????????????");
+	if (!(invalid_data_set))
+		p += sprintf(p, "                %s                     %s\n",
+			(sc1d & 0x08) ? "Error       " :
+			((sc1d & 0x05) == 0x05) ? "Not My INTR " :
+			(sc1d & 0x04) ? "Interrupting" :
+			(sc1d & 0x02) ? "FIFO Full   " :
+			(sc1d & 0x01) ? "FIFO Empty  " : "????????????",
+			(sc1d & 0x80) ? "Error       " :
+			((sc1d & 0x50) == 0x50) ? "Not My INTR " :
+			(sc1d & 0x40) ? "Interrupting" :
+			(sc1d & 0x20) ? "FIFO Full   " :
+			(sc1d & 0x10) ? "FIFO Empty  " : "????????????");
 	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
 	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
 		(c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
-	p += sprintf(p, "DMA Mode:       %s           %s          %s            %s\n",
-		pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
-		pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
-		pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
-		pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
-	p += sprintf(p, "PIO Mode:       %s            %s           %s            %s\n",
-		pdc202xx_pio_verbose(reg60h),pdc202xx_pio_verbose(reg64h),
-		pdc202xx_pio_verbose(reg68h),pdc202xx_pio_verbose(reg6ch));
+	if (!(invalid_data_set))
+		p += sprintf(p, "DMA Mode:       %s           %s          %s            %s\n",
+			pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
+			pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
+			pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
+			pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
+	if (!(invalid_data_set))
+		p += sprintf(p, "PIO Mode:       %s            %s           %s            %s\n",
+			pdc202xx_pio_verbose(reg60h),
+			pdc202xx_pio_verbose(reg64h),
+			pdc202xx_pio_verbose(reg68h),
+			pdc202xx_pio_verbose(reg6ch));
 #if 0
 	p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n");
 #endif
+	if (invalid_data_set)
+		p += sprintf(p, "--------------- Cannot Decode HOST ---------------\n");
 	return (char *)p;
 }
 
@@ -374,6 +385,9 @@
 
 	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))	return -1;
 
+	if (dev->device == PCI_DEVICE_ID_PROMISE_20268)
+		goto skip_register_hell;
+
 	pci_read_config_dword(dev, drive_pci, &drive_conf);
 	pci_read_config_byte(dev, (drive_pci), &AP);
 	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
@@ -461,7 +475,12 @@
 	decode_registers(REG_D, DP);
 #endif /* PDC202XX_DECODE_REGISTER_INFO */
 
+skip_register_hell:
+
+	if (!drive->init_speed)
+		drive->init_speed = speed;
 	err = ide_config_drive_speed(drive, speed);
+	drive->current_speed = speed;
 
 #if PDC202XX_DEBUG_DRIVE_INFO
 	printk("%s: %s drive%d 0x%08x ",
@@ -513,7 +532,7 @@
 	byte CLKSPD		= IN_BYTE(high_16 + 0x11);
 	byte udma_33		= ultra ? (inb(high_16 + 0x001f) & 1) : 0;
 	byte udma_66		= ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0;
-	byte udma_100		= (((dev->device == PCI_DEVICE_ID_PROMISE_20265) || (dev->device == PCI_DEVICE_ID_PROMISE_20267)) && udma_66) ? 1 : 0;
+	byte udma_100		= (((dev->device == PCI_DEVICE_ID_PROMISE_20265) || (dev->device == PCI_DEVICE_ID_PROMISE_20267) || (dev->device == PCI_DEVICE_ID_PROMISE_20268)) && udma_66) ? 1 : 0;
 
 	/*
 	 * Set the control register to use the 66Mhz system
@@ -536,6 +555,9 @@
 				   (id->dma_ultra & 0x0010) ||
 				   (id->dma_ultra & 0x0008)) ? 1 : 0;
 
+	if (dev->device == PCI_DEVICE_ID_PROMISE_20268)
+		goto jump_pci_mucking;
+
 	pci_read_config_word(dev, 0x50, &EP);
 
 	if (((ultra_66) || (ultra_100)) && (EP & c_mask)) {
@@ -616,6 +638,8 @@
 	if (drive->media == ide_disk)	/* PREFETCH_EN */
 		pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
 
+jump_pci_mucking:
+
 	if ((id->dma_ultra & 0x0020) && (udma_100))	speed = XFER_UDMA_5;
 	else if ((id->dma_ultra & 0x0010) && (udma_66))	speed = XFER_UDMA_4;
 	else if ((id->dma_ultra & 0x0008) && (udma_66))	speed = XFER_UDMA_3;
@@ -630,7 +654,8 @@
 	else if (id->dma_1word & 0x0001)		speed = XFER_SW_DMA_0;
 	else {
 		/* restore original pci-config space */
-		pci_write_config_dword(dev, drive_pci, drive_conf);
+		if (dev->device != PCI_DEVICE_ID_PROMISE_20268)
+			pci_write_config_dword(dev, drive_pci, drive_conf);
 		return ide_dma_off_quietly;
 	}
 
@@ -783,7 +808,10 @@
 		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) && (dev->device != PCI_DEVICE_ID_PROMISE_20265) && (dev->device != PCI_DEVICE_ID_PROMISE_20267)) {
+		if ((irq != irq2) &&
+		    (dev->device != PCI_DEVICE_ID_PROMISE_20265) &&
+		    (dev->device != PCI_DEVICE_ID_PROMISE_20267) &&
+		    (dev->device != PCI_DEVICE_ID_PROMISE_20268)) {
 			pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq);	/* 0xbc */
 			printk("%s: pci-config space interrupt mirror fixed.\n", name);
 		}
@@ -851,6 +879,14 @@
 	    (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20267)) {
 		hwif->resetproc	= &pdc202xx_reset;
 	}
+
+#undef CONFIG_PDC202XX_32_UNMASK
+#ifdef CONFIG_PDC202XX_32_UNMASK
+	hwif->drives[0].io_32bit = 1;
+	hwif->drives[1].io_32bit = 1;
+	hwif->drives[0].unmask = 1;
+	hwif->drives[1].unmask = 1;
+#endif /* CONFIG_PDC202XX_32_UNMASK */
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
diff -urN linux-2.4.9-pre2/drivers/ide/piix.c linux/drivers/ide/piix.c
--- linux-2.4.9-pre2/drivers/ide/piix.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/ide/piix.c	Mon Dec  3 23:02:45 2001
@@ -88,6 +88,34 @@
 	u8  c0 = 0, c1 = 0;
 	u8  reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0;
 
+	switch(bmide_dev->device) {
+		case PCI_DEVICE_ID_INTEL_82801BA_8:
+		case PCI_DEVICE_ID_INTEL_82801BA_9:
+			p += sprintf(p, "\n                                Intel PIIX4 Ultra 100 Chipset.\n");
+			break;
+		case PCI_DEVICE_ID_INTEL_82372FB_1:
+		case PCI_DEVICE_ID_INTEL_82801AA_1:
+			p += sprintf(p, "\n                                Intel PIIX4 Ultra 66 Chipset.\n");
+			break;
+		case PCI_DEVICE_ID_INTEL_82451NX:
+		case PCI_DEVICE_ID_INTEL_82801AB_1:
+		case PCI_DEVICE_ID_INTEL_82443MX_1:
+		case PCI_DEVICE_ID_INTEL_82371AB:
+			p += sprintf(p, "\n                                Intel PIIX4 Ultra 33 Chipset.\n");
+			break;
+		case PCI_DEVICE_ID_INTEL_82371SB_1:
+			p += sprintf(p, "\n                                Intel PIIX3 Chipset.\n");
+			break;
+		case PCI_DEVICE_ID_INTEL_82371MX:
+			p += sprintf(p, "\n                                Intel MPIIX Chipset.\n");
+			return p-buffer;	/* => must be less than 4k! */
+		case PCI_DEVICE_ID_INTEL_82371FB_1:
+		case PCI_DEVICE_ID_INTEL_82371FB_0:
+		default:
+			p += sprintf(p, "\n                                Intel PIIX Chipset.\n");
+			break;
+	}
+
 	pci_read_config_word(bmide_dev, 0x40, &reg40);
 	pci_read_config_word(bmide_dev, 0x42, &reg42);
 	pci_read_config_byte(bmide_dev, 0x44, &reg44);
@@ -100,14 +128,13 @@
 	psitre = (reg40 & 0x4000) ? 1 : 0;
 	ssitre = (reg42 & 0x4000) ? 1 : 0;
 
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
 	c0 = inb_p((unsigned short)bibma + 0x02);
 	c1 = inb_p((unsigned short)bibma + 0x0a);
 
-	p += sprintf(p, "\n                    %s Chipset.\n", bmide_dev->name);
 	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
 	p += sprintf(p, "                %sabled                         %sabled\n",
 			(c0&0x80) ? "dis" : " en",
@@ -481,6 +508,11 @@
 	if (!hwif->irq)
 		hwif->irq = hwif->channel ? 15 : 14;
 #endif /* CONFIG_IA64 */
+
+	if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
+		/* This is a painful system best to let it self tune for now */
+		return;
+	}
 
 	hwif->tuneproc = &piix_tune_drive;
 	hwif->drives[0].autotune = 1;
diff -urN linux-2.4.9-pre2/drivers/ide/serverworks.c linux/drivers/ide/serverworks.c
--- linux-2.4.9-pre2/drivers/ide/serverworks.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ide/serverworks.c	Mon Dec  3 23:02:45 2001
@@ -0,0 +1,577 @@
+/*
+ * linux/drivers/ide/serverworks.c		Version 0.2	17 Oct 2000
+ *
+ *  Copyright (C) 2000 Cobalt Networks, Inc. <asun@cobalt.com>
+ *  May be copied or modified under the terms of the GNU General Public License
+ *
+ *  interface borrowed from alim15x3.c:
+ *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
+ *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
+ *
+ *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *
+ *  IDE support for the ServerWorks OSB4 IDE chipset
+ *
+ * here's the default lspci:
+ *
+ * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP])
+ *	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B-
+ *	Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
+ *	Latency: 255
+ *	Region 4: I/O ports at c200
+ * 00: 66 11 11 02 05 01 00 02 00 8a 01 01 00 ff 80 00
+ * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 20: 01 c2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 40: 99 99 99 99 ff ff ff ff 0c 0c 00 00 00 00 00 00
+ * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ *
+ * 00:0f.1 IDE interface: ServerWorks: Unknown device 0212 (rev 92) (prog-if 8a [Master SecP PriP])
+ *         Subsystem: ServerWorks: Unknown device 0212
+ *         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
+ *         Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
+ *         Latency: 64, cache line size 08
+ *         Region 0: I/O ports at 01f0
+ *         Region 1: I/O ports at 03f4
+ *         Region 2: I/O ports at 0170
+ *         Region 3: I/O ports at 0374
+ *         Region 4: I/O ports at 08b0
+ *         Region 5: I/O ports at 1000
+ *
+ * 00:0f.1 IDE interface: ServerWorks: Unknown device 0212 (rev 92)
+ * 00: 66 11 12 02 05 00 00 02 92 8a 01 01 08 40 80 00
+ * 10: f1 01 00 00 f5 03 00 00 71 01 00 00 75 03 00 00
+ * 20: b1 08 00 00 01 10 00 00 00 00 00 00 66 11 12 02
+ * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 40: 4f 4f 4f 4f 20 ff ff ff f0 50 44 44 00 00 00 00
+ * 50: 00 00 00 00 07 00 44 02 0f 04 03 00 00 00 00 00
+ * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ *
+ *
+ */
+
+#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 <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define SVWKS_DEBUG_DRIVE_INFO		0
+
+#define DISPLAY_SVWKS_TIMINGS
+
+#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static struct pci_dev *bmide_dev;
+
+static int svwks_get_info(char *, char **, off_t, int);
+extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+
+static int svwks_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	u32 bibma = pci_resource_start(bmide_dev, 4);
+	u32 reg40, reg44;
+	u16 reg48, reg56;
+	u8  c0 = 0, c1 = 0, reg54;
+
+	pci_read_config_dword(bmide_dev, 0x40, &reg40);
+	pci_read_config_dword(bmide_dev, 0x44, &reg44);
+	pci_read_config_word(bmide_dev, 0x48, &reg48);
+	pci_read_config_byte(bmide_dev, 0x54, &reg54);
+	pci_read_config_word(bmide_dev, 0x56, &reg56);
+
+        /*
+         * at that point bibma+0x2 et bibma+0xa are byte registers
+         * to investigate:
+         */
+	c0 = inb_p((unsigned short)bibma + 0x02);
+	c1 = inb_p((unsigned short)bibma + 0x0a);
+
+	switch(bmide_dev->device) {
+		case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+			p += sprintf(p, "\n                                ServerWorks CSB5 Chipset.\n");
+			break;
+		case PCI_DEVICE_ID_SERVERWORKS_OSB4:
+			p += sprintf(p, "\n                                ServerWorks OSB4 Chipset.\n");
+			break;
+		default:
+			p += sprintf(p, "\n                                ServerWorks 0x%04x Chipset.\n", bmide_dev->device);
+			break;
+	}
+
+	p += sprintf(p, "------------------------------- General Status ---------------------------------\n");
+#if 0
+	p += sprintf(p, "                                     : %s\n", "str");
+#endif
+	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+	p += sprintf(p, "                %sabled                         %sabled\n",
+			(c0&0x80) ? "dis" : " en",
+			(c1&0x80) ? "dis" : " en");
+	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+			(c0&0x20) ? "yes" : "no ",
+			(c0&0x40) ? "yes" : "no ",
+			(c1&0x20) ? "yes" : "no ",
+			(c1&0x40) ? "yes" : "no " );
+	p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
+			(reg54 & 0x01) ? "yes" : "no ",
+			(reg54 & 0x02) ? "yes" : "no ",
+			(reg54 & 0x04) ? "yes" : "no ",
+			(reg54 & 0x08) ? "yes" : "no " );
+	p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
+			((reg56&0x0005)==0x0005)?"5":
+				((reg56&0x0004)==0x0004)?"4":
+				((reg56&0x0003)==0x0003)?"3":
+				((reg56&0x0002)==0x0002)?"2":
+				((reg56&0x0001)==0x0001)?"1":
+				((reg56&0x000F))?"?":"0",
+			((reg56&0x0050)==0x0050)?"5":
+				((reg56&0x0040)==0x0040)?"4":
+				((reg56&0x0030)==0x0030)?"3":
+				((reg56&0x0020)==0x0020)?"2":
+				((reg56&0x0010)==0x0010)?"1":
+				((reg56&0x00F0))?"?":"0",
+			((reg56&0x0500)==0x0500)?"5":
+				((reg56&0x0400)==0x0400)?"4":
+				((reg56&0x0300)==0x0300)?"3":
+				((reg56&0x0200)==0x0200)?"2":
+				((reg56&0x0100)==0x0100)?"1":
+				((reg56&0x0F00))?"?":"0",
+			((reg56&0x5000)==0x5000)?"5":
+				((reg56&0x4000)==0x4000)?"4":
+				((reg56&0x3000)==0x3000)?"3":
+				((reg56&0x2000)==0x2000)?"2":
+				((reg56&0x1000)==0x1000)?"1":
+				((reg56&0xF000))?"?":"0");
+	p += sprintf(p, "DMA enabled:    %s                %s               %s                 %s\n",
+			((reg44&0x00002000)==0x00002000)?"2":
+				((reg44&0x00002100)==0x00002100)?"1":
+				((reg44&0x00007700)==0x00007700)?"0":
+				((reg44&0x0000FF00)==0x0000FF00)?"X":"?",
+			((reg44&0x00000020)==0x00000020)?"2":
+				((reg44&0x00000021)==0x00000021)?"1":
+				((reg44&0x00000077)==0x00000077)?"0":
+				((reg44&0x000000FF)==0x000000FF)?"X":"?",
+			((reg44&0x20000000)==0x20000000)?"2":
+				((reg44&0x21000000)==0x21000000)?"1":
+				((reg44&0x77000000)==0x77000000)?"0":
+				((reg44&0xFF000000)==0xFF000000)?"X":"?",
+			((reg44&0x00200000)==0x00200000)?"2":
+				((reg44&0x00210000)==0x00210000)?"1":
+				((reg44&0x00770000)==0x00770000)?"0":
+				((reg44&0x00FF0000)==0x00FF0000)?"X":"?");
+#if 0
+	if (bmide_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
+		p += sprintf(p, "PIO  enabled:   %s                %s               %s                 %s\n",
+	if (bmide_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4)
+#endif
+		p += sprintf(p, "PIO  enabled:   %s                %s               %s                 %s\n",
+			((reg40&0x00002000)==0x00002000)?"4":
+				((reg40&0x00002200)==0x00002200)?"3":
+				((reg40&0x00003400)==0x00003400)?"2":
+				((reg40&0x00004700)==0x00004700)?"1":
+				((reg40&0x00005D00)==0x00005D00)?"0":"?",
+			((reg40&0x00000020)==0x00000020)?"4":
+				((reg40&0x00000022)==0x00000022)?"3":
+				((reg40&0x00000034)==0x00000034)?"2":
+				((reg40&0x00000047)==0x00000047)?"1":
+				((reg40&0x0000005D)==0x0000005D)?"0":"?",
+			((reg40&0x20000000)==0x20000000)?"4":
+				((reg40&0x22000000)==0x22000000)?"3":
+				((reg40&0x34000000)==0x34000000)?"2":
+				((reg40&0x47000000)==0x47000000)?"1":
+				((reg40&0x5D000000)==0x5D000000)?"0":"?",
+			((reg40&0x00200000)==0x00200000)?"4":
+				((reg40&0x00220000)==0x00220000)?"3":
+				((reg40&0x00340000)==0x00340000)?"2":
+				((reg40&0x00470000)==0x00470000)?"1":
+				((reg40&0x005D0000)==0x005D0000)?"0":"?");
+	return p-buffer;	 /* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+static byte svwks_revision = 0;
+
+byte svwks_proc = 0;
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static struct pci_dev *isa_dev;
+
+static int svwks_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	byte udma_modes[]	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+	byte dma_modes[]	= { 0x77, 0x21, 0x20 };
+	byte pio_modes[]	= { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	byte unit		= (drive->select.b.unit & 0x01);
+	byte csb5		= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	unsigned long dma_base	= hwif->dma_base;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+	int err;
+
+	byte drive_pci		= 0x00;
+	byte drive_pci2		= 0x00;
+	byte drive_pci3		= hwif->channel ? 0x57 : 0x56;
+
+	byte ultra_enable	= 0x00;
+	byte ultra_timing	= 0x00;
+	byte dma_timing		= 0x00;
+	byte pio_timing		= 0x00;
+	unsigned short csb5_pio	= 0x00;
+
+	byte pio	= ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+        switch (drive->dn) {
+		case 0: drive_pci = 0x41; drive_pci2 = 0x45; break;
+		case 1: drive_pci = 0x40; drive_pci2 = 0x44; break;
+		case 2: drive_pci = 0x43; drive_pci2 = 0x47; break;
+		case 3: drive_pci = 0x42; drive_pci2 = 0x46; break;
+		default:
+			return -1;
+	}
+
+	pci_read_config_byte(dev, drive_pci, &pio_timing);
+	pci_read_config_byte(dev, drive_pci2, &dma_timing);
+	pci_read_config_byte(dev, drive_pci3, &ultra_timing);
+	pci_read_config_word(dev, 0x4A, &csb5_pio);
+	pci_read_config_byte(dev, 0x54, &ultra_enable);
+
+#ifdef DEBUG
+	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+		drive->name, ultra_timing, dma_timing, pio_timing);
+#endif
+
+	pio_timing	&= ~0xFF;
+	dma_timing	&= ~0xFF;
+	ultra_timing	&= ~(0x0F << (4*unit));
+	ultra_enable	&= ~(0x01 << drive->dn);
+	csb5_pio	&= ~(0x0F << (4*drive->dn));
+
+	switch(speed) {
+		case XFER_PIO_4:
+		case XFER_PIO_3:
+		case XFER_PIO_2:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+			pio_timing |= pio_modes[speed - XFER_PIO_0];
+			csb5_pio   |= ((speed - XFER_PIO_0) << (4*drive->dn));
+			break;
+#ifdef CONFIG_BLK_DEV_IDEDMA
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:
+		case XFER_MW_DMA_0:
+			pio_timing |= pio_modes[pio];
+			csb5_pio   |= (pio << (4*drive->dn));
+			dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
+			break;
+
+		case XFER_UDMA_5:
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+			pio_timing |= pio_modes[pio];
+			csb5_pio   |= (pio << (4*drive->dn));
+			dma_timing |= dma_modes[2];
+			ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
+			ultra_enable |= (0x01 << drive->dn);
+#endif
+		default:
+			break;
+	}
+
+#ifdef DEBUG
+	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
+		drive->name, ultra_timing, dma_timing, pio_timing);
+#endif
+
+#if OSB4_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
+#endif /* OSB4_DEBUG_DRIVE_INFO */
+
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
+	pci_write_config_byte(dev, drive_pci, pio_timing);
+	if (csb5)
+		pci_write_config_word(dev, 0x4A, csb5_pio);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	pci_write_config_byte(dev, drive_pci2, dma_timing);
+	pci_write_config_byte(dev, drive_pci3, ultra_timing);
+	pci_write_config_byte(dev, 0x54, ultra_enable);
+	
+	if (speed > XFER_PIO_4) {
+		outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+	} else {
+		outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+	}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+	err = ide_config_drive_speed(drive, speed);
+	drive->current_speed = speed;
+	return err;
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+	unsigned short xfer_pio = drive->id->eide_pio_modes;
+	byte			timing, speed, pio;
+
+	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+	if (xfer_pio> 4)
+		xfer_pio = 0;
+
+	if (drive->id->eide_pio_iordy > 0) {
+		for (xfer_pio = 5;
+			xfer_pio>0 &&
+			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+			xfer_pio--);
+	} else {
+		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+			   (drive->id->eide_pio_modes & 2) ? 0x04 :
+			   (drive->id->eide_pio_modes & 1) ? 0x03 :
+			   (drive->id->tPIO & 2) ? 0x02 :
+			   (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+	}
+
+	timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+	switch(timing) {
+		case 4: speed = XFER_PIO_4;break;
+		case 3: speed = XFER_PIO_3;break;
+		case 2: speed = XFER_PIO_2;break;
+		case 1: speed = XFER_PIO_1;break;
+		default:
+			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+			break;
+	}
+	(void) svwks_tune_chipset(drive, speed);
+	drive->current_speed = speed;
+}
+
+static void svwks_tune_drive (ide_drive_t *drive, byte pio)
+{
+	byte speed;
+	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) svwks_tune_chipset(drive, speed);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	byte udma_66		= eighty_ninty_three(drive);
+	byte			speed;
+
+	int ultra66		= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
+	/* need specs to figure out if osb4 is capable of ata/66/100 */
+	int ultra100		= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
+
+	if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) {
+		speed = XFER_UDMA_5;
+	} else if (id->dma_ultra & 0x0010) {
+		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
+	} else if (id->dma_ultra & 0x0008) {
+		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
+	} else if (id->dma_ultra & 0x0004) {
+		speed = XFER_UDMA_2;
+	} else if (id->dma_ultra & 0x0002) {
+		speed = XFER_UDMA_1;
+	} else if (id->dma_ultra & 0x0001) {
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_1word & 0x0004) {
+		speed = XFER_SW_DMA_2;
+	} else {
+		speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+	}
+
+	(void) svwks_tune_chipset(drive, speed);
+
+	return ((int)	((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+}
+
+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 & 0x002F) {
+				/* 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 & 0x007)) {
+				/* 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);
+}
+
+static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		default :
+			break;
+	}
+	/* Other cases are done by generic IDE-DMA code. */
+	return ide_dmaproc(func, drive);
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+unsigned int __init pci_init_svwks (struct pci_dev *dev, const char *name)
+{
+	unsigned int reg64;
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
+
+	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+		isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
+
+		pci_read_config_dword(isa_dev, 0x64, &reg64);
+#ifdef DEBUG
+		printk("%s: reg64 == 0x%08x\n", name, reg64);
+#endif
+
+//		reg64 &= ~0x0000A000;
+//#ifdef CONFIG_SMP
+//		reg64 |= 0x00008000;
+//#endif
+	/* Assume the APIC was set up properly by the BIOS for now . If it
+	   wasnt we need to do a fix up _way_ earlier. Bits 15,10,3 control
+	   APIC enable, routing and decode */
+	   
+		reg64 &= ~0x00002000;	
+		pci_write_config_dword(isa_dev, 0x64, reg64);
+	}
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
+
+#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!svwks_proc) {
+		svwks_proc = 1;
+		bmide_dev = dev;
+		svwks_display_info = &svwks_get_info;
+	}
+#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */
+	return 0;
+}
+
+unsigned int __init ata66_svwks (ide_hwif_t *hwif)
+{
+	return 0;
+}
+
+void __init ide_init_svwks (ide_hwif_t *hwif)
+{
+	if (!hwif->irq)
+		hwif->irq = hwif->channel ? 15 : 14;
+
+	hwif->tuneproc = &svwks_tune_drive;
+	hwif->speedproc = &svwks_tune_chipset;
+
+#ifndef CONFIG_BLK_DEV_IDEDMA
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+	hwif->autodma = 0;
+	return;
+#else /* CONFIG_BLK_DEV_IDEDMA */
+
+	if (hwif->dma_base) {
+		if (!noautodma)
+			hwif->autodma = 1;
+		hwif->dmaproc = &svwks_dmaproc;
+	} else {
+		hwif->autodma = 0;
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+#endif /* !CONFIG_BLK_DEV_IDEDMA */
+}
diff -urN linux-2.4.9-pre2/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- linux-2.4.9-pre2/drivers/isdn/Config.in	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/Config.in	Mon Dec  3 23:02:45 2001
@@ -69,8 +69,8 @@
    bool '  Gazel cards' CONFIG_HISAX_GAZEL
    bool '  HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
    bool '  Winbond W6692 based cards' CONFIG_HISAX_W6692
+   bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-      bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
 #      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
       if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
 	 bool '  Am7930' CONFIG_HISAX_AMD7930
diff -urN linux-2.4.9-pre2/drivers/isdn/act2000/act2000_isa.c linux/drivers/isdn/act2000/act2000_isa.c
--- linux-2.4.9-pre2/drivers/isdn/act2000/act2000_isa.c	Fri Nov 17 11:16:20 2000
+++ linux/drivers/isdn/act2000/act2000_isa.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: act2000_isa.c,v 1.11 2000/11/12 16:32:06 kai Exp $
+/* $Id: act2000_isa.c,v 1.11.6.2 2001/07/18 16:25:12 kai Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
  *
@@ -26,16 +26,7 @@
 #include "act2000_isa.h"
 #include "capi.h"
 
-static act2000_card *irq2card_map[16] =
-{
-	0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int act2000_isa_irqs[] =
-{
-        3, 5, 7, 10, 11, 12, 15
-};
-#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int))
+static act2000_card *irq2card_map[16];
 
 static void
 act2000_isa_delay(long t)
@@ -82,13 +73,9 @@
 act2000_isa_detect(unsigned short portbase)
 {
         int ret = 0;
-        unsigned long flags;
 
-        save_flags(flags);
-        cli();
         if (!check_region(portbase, ISA_REGION))
                 ret = act2000_isa_reset(portbase);
-        restore_flags(flags);
         return ret;
 }
 
@@ -167,9 +154,6 @@
 int
 act2000_isa_config_irq(act2000_card * card, short irq)
 {
-        int i;
-        unsigned long flags;
-
         if (card->flags & ACT2000_FLAGS_IVALID) {
                 free_irq(card->irq, NULL);
                 irq2card_map[card->irq] = NULL;
@@ -178,30 +162,13 @@
         outb(ISA_COR_IRQOFF, ISA_PORT_COR);
         if (!irq)
                 return 0;
-        save_flags(flags);
-        cli();
-        if (irq == -1) {
-                /* Auto select */
-                for (i = 0; i < ISA_NRIRQS; i++) {
-                        if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) {
-                                card->irq = act2000_isa_irqs[i];
-                                irq2card_map[card->irq] = card;
-                                card->flags |= ACT2000_FLAGS_IVALID;
-                                break;
-                        }
-                }
-        } else {
-                /* Fixed irq */
-                if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
-                        card->irq = irq;
-                        irq2card_map[card->irq] = card;
-			card->flags |= ACT2000_FLAGS_IVALID;
-                }
-        }
-        restore_flags(flags);
-        if (!card->flags & ACT2000_FLAGS_IVALID) {
+
+	if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
+		card->irq = irq;
+		irq2card_map[card->irq] = card;
+		card->flags |= ACT2000_FLAGS_IVALID;
                 printk(KERN_WARNING
-                       "act2000: Could not request irq\n");
+                       "act2000: Could not request irq %d\n",irq);
                 return -EBUSY;
         } else {
 		act2000_isa_select_irq(card);
diff -urN linux-2.4.9-pre2/drivers/isdn/act2000/module.c linux/drivers/isdn/act2000/module.c
--- linux-2.4.9-pre2/drivers/isdn/act2000/module.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/isdn/act2000/module.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: module.c,v 1.14.6.2 2000/12/18 22:14:10 kai Exp $
+/* $Id: module.c,v 1.14.6.3 2001/07/13 09:20:11 kai Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *
@@ -38,7 +38,7 @@
 /* Parameters to be set by insmod */
 static int   act_bus  =  0;
 static int   act_port = -1;  /* -1 = Autoprobe  */
-static int   act_irq  = -1;  /* -1 = Autoselect */
+static int   act_irq  = -1;
 static char *act_id   = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 
 MODULE_DESCRIPTION(       "Driver for IBM Active 2000 ISDN card");
@@ -46,7 +46,7 @@
 MODULE_SUPPORTED_DEVICE(  "ISDN subsystem");
 MODULE_PARM_DESC(act_bus, "BusType of first card, 1=ISA, 2=MCA, 3=PCMCIA, currently only ISA");
 MODULE_PARM_DESC(membase, "Base port address of first card");
-MODULE_PARM_DESC(act_irq, "IRQ of first card (-1 = grab next free IRQ)");
+MODULE_PARM_DESC(act_irq, "IRQ of first card");
 MODULE_PARM_DESC(act_id,  "ID-String of first card");
 MODULE_PARM(act_bus,  "i");
 MODULE_PARM(act_port, "i");
diff -urN linux-2.4.9-pre2/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- linux-2.4.9-pre2/drivers/isdn/avmb1/capi.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/isdn/avmb1/capi.c	Mon Dec  3 23:02:45 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: capi.c,v 1.44.6.12 2001/06/09 15:14:15 kai Exp $
+ * $Id: capi.c,v 1.44.6.13 2001/08/13 07:46:15 kai Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
@@ -43,7 +43,7 @@
 #include "capifs.h"
 #endif
 
-static char *revision = "$Revision: 1.44.6.12 $";
+static char *revision = "$Revision: 1.44.6.13 $";
 
 MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");
 
diff -urN linux-2.4.9-pre2/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- linux-2.4.9-pre2/drivers/isdn/divert/divert_procfs.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/isdn/divert/divert_procfs.c	Mon Dec  3 23:02:45 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: divert_procfs.c,v 1.11 2000/11/25 17:01:00 kai Exp $
+ * $Id: divert_procfs.c,v 1.11.6.1 2001/08/13 07:46:15 kai Exp $
  *
  * Filesystem handling for the diversion supplementary services.
  *
diff -urN linux-2.4.9-pre2/drivers/isdn/eicon/lincfg.c linux/drivers/isdn/eicon/lincfg.c
--- linux-2.4.9-pre2/drivers/isdn/eicon/lincfg.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/eicon/lincfg.c	Mon Dec  3 23:02:45 2001
@@ -43,12 +43,6 @@
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 
-#define HW_ID_EICON_PCI			0x1133
-#define HW_ID_DIVA_SERVER_P		0xE014
-#define HW_ID_DIVA_SERVER_B_ST	0xE010
-#define HW_ID_DIVA_SERVER_B_U	0xE013
-#define HW_ID_DIVA_SERVER_Q   	0xE012
-
 struct file_operations Divas_fops;
 int Divas_major;
 
@@ -73,8 +67,8 @@
 	
 	while (wDeviceIndex < 10)
 	{
-		wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
-				HW_ID_DIVA_SERVER_Q, 
+		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
+				PCI_DEVICE_ID_EICON_MAESTRAQ, 
 				wDeviceIndex, 
 				&byBus, &byFunc);
 
@@ -174,8 +168,8 @@
 
 	while (wDeviceIndex < 10)
 	{
-		wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
-				HW_ID_DIVA_SERVER_B_ST, 
+		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
+				PCI_DEVICE_ID_EICON_MAESTRA, 
 				wDeviceIndex, 
 				&byBus, &byFunc);
 
@@ -232,8 +226,8 @@
 			wNumCards++;
 		}
 
-		wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
-				HW_ID_DIVA_SERVER_B_U, 
+		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
+				PCI_DEVICE_ID_EICON_MAESTRAQ_U, 
 				wDeviceIndex, 
 				&byBus, &byFunc);
 
@@ -298,8 +292,8 @@
 
 	while (wDeviceIndex < 10)
 	{
-		wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
-				HW_ID_DIVA_SERVER_P, 
+		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
+				PCI_DEVICE_ID_EICON_MAESTRAP, 
 				wDeviceIndex, 
 				&byBus, &byFunc);
 
diff -urN linux-2.4.9-pre2/drivers/isdn/hisax/sedlbauer_cs.c linux/drivers/isdn/hisax/sedlbauer_cs.c
--- linux-2.4.9-pre2/drivers/isdn/hisax/sedlbauer_cs.c	Sat Jul 28 12:12:37 2001
+++ linux/drivers/isdn/hisax/sedlbauer_cs.c	Mon Dec  3 23:02:45 2001
@@ -25,8 +25,8 @@
     <maniemann@users.sourceforge.net>. All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
-    case the provisions of the GPL are applicable instead of the
+    terms of the GNU General Public License version 2 (the "GPL"), in
+    which case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
     your version of this file under the MPL, indicate your decision
diff -urN linux-2.4.9-pre2/drivers/isdn/hysdn/hysdn_procconf.c linux/drivers/isdn/hysdn/hysdn_procconf.c
--- linux-2.4.9-pre2/drivers/isdn/hysdn/hysdn_procconf.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/isdn/hysdn/hysdn_procconf.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_procconf.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $
+/* $Id: hysdn_procconf.c,v 1.8.6.3 2001/08/13 07:46:15 kai Exp $
 
  * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
@@ -31,7 +31,7 @@
 
 #include "hysdn_defs.h"
 
-static char *hysdn_procconf_revision = "$Revision: 1.8.6.2 $";
+static char *hysdn_procconf_revision = "$Revision: 1.8.6.3 $";
 
 #define INFO_OUT_LEN 80		/* length of info line including lf */
 
diff -urN linux-2.4.9-pre2/drivers/isdn/hysdn/hysdn_proclog.c linux/drivers/isdn/hysdn/hysdn_proclog.c
--- linux-2.4.9-pre2/drivers/isdn/hysdn/hysdn_proclog.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/isdn/hysdn/hysdn_proclog.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_proclog.c,v 1.9.6.1 2001/05/26 15:19:58 kai Exp $
+/* $Id: hysdn_proclog.c,v 1.9.6.2 2001/08/13 07:46:15 kai Exp $
 
  * Linux driver for HYSDN cards, /proc/net filesystem log functions.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
diff -urN linux-2.4.9-pre2/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- linux-2.4.9-pre2/drivers/isdn/icn/icn.c	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/icn/icn.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.65.6.5 2001/06/09 15:14:19 kai Exp $
+/* $Id: icn.c,v 1.65.6.6 2001/07/13 09:20:12 kai Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -34,7 +34,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.65.6.5 $";
+*revision = "$Revision: 1.65.6.6 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -804,8 +804,8 @@
 icn_loadboot(u_char * buffer, icn_card * card)
 {
 	int ret;
-	ulong flags;
 	u_char *codebuf;
+	unsigned long flags;
 
 #ifdef BOOT_DEBUG
 	printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
@@ -818,8 +818,6 @@
 		kfree(codebuf);
 		return ret;
 	}
-	save_flags(flags);
-	cli();
 	if (!card->rvalid) {
 		if (check_region(card->port, ICN_PORTLEN)) {
 			printk(KERN_WARNING
@@ -827,7 +825,6 @@
 			       CID,
 			       card->port,
 			       card->port + ICN_PORTLEN);
-			restore_flags(flags);
 			kfree(codebuf);
 			return -EBUSY;
 		}
@@ -840,14 +837,12 @@
 		if (check_mem_region(dev.memaddr, 0x4000)) {
 			printk(KERN_WARNING
 			       "icn: memory at 0x%08lx in use.\n", dev.memaddr);
-			restore_flags(flags);
 			return -EBUSY;
 		}
 		request_mem_region(dev.memaddr, 0x4000, "icn-isdn (all cards)");
 		dev.shmem = ioremap(dev.memaddr, 0x4000);
 		dev.mvalid = 1;
 	}
-	restore_flags(flags);
 	OUTB_P(0, ICN_RUN);     /* Reset Controller */
 	OUTB_P(0, ICN_MAPRAM);  /* Disable RAM      */
 	icn_shiftout(ICN_CFG, 0x0f, 3, 4);	/* Windowsize= 16k  */
@@ -1051,18 +1046,19 @@
 	ocount = 1;
 	xcount = loop = 0;
 	while (len) {
-		save_flags(flags);
-		cli();
-		lastmap_card = dev.mcard;
-		lastmap_channel = dev.channel;
-		icn_map_channel(card, mch);
-
 		avail = cmd_free;
 		count = MIN(avail, len);
 		if (user)
 			copy_from_user(msg, buf, count);
 		else
 			memcpy(msg, buf, count);
+
+		save_flags(flags);
+		cli();
+		lastmap_card = dev.mcard;
+		lastmap_channel = dev.channel;
+		icn_map_channel(card, mch);
+
 		icn_putmsg(card, '>');
 		for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp
 		     ++) {
@@ -1140,10 +1136,7 @@
 icn_disable_cards(void)
 {
 	icn_card *card = cards;
-	unsigned long flags;
 
-	save_flags(flags);
-	cli();
 	while (card) {
 		if (check_region(card->port, ICN_PORTLEN)) {
 			printk(KERN_WARNING
@@ -1151,14 +1144,12 @@
 			       CID,
 			       card->port,
 			       card->port + ICN_PORTLEN);
-			cli();
 		} else {
 			OUTB_P(0, ICN_RUN);	/* Reset Controller     */
 			OUTB_P(0, ICN_MAPRAM);	/* Disable RAM          */
 		}
 		card = card->next;
 	}
-	restore_flags(flags);
 }
 
 static int
@@ -1603,25 +1594,19 @@
 static int
 icn_addcard(int port, char *id1, char *id2)
 {
-	ulong flags;
 	icn_card *card;
 	icn_card *card2;
 
-	save_flags(flags);
-	cli();
 	if (!(card = icn_initcard(port, id1))) {
-		restore_flags(flags);
 		return -EIO;
 	}
 	if (!strlen(id2)) {
-		restore_flags(flags);
 		printk(KERN_INFO
 		       "icn: (%s) ICN-2B, port 0x%x added\n",
 		       card->interface.id, port);
 		return 0;
 	}
 	if (!(card2 = icn_initcard(port, id2))) {
-		restore_flags(flags);
 		printk(KERN_INFO
 		       "icn: (%s) half ICN-4B, port 0x%x added\n",
 		       card2->interface.id, port);
@@ -1633,7 +1618,6 @@
 	card2->doubleS0 = 1;
 	card2->secondhalf = 1;
 	card2->other = card;
-	restore_flags(flags);
 	printk(KERN_INFO
 	       "icn: (%s and %s) ICN-4B, port 0x%x added\n",
 	       card->interface.id, card2->interface.id, port);
diff -urN linux-2.4.9-pre2/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.4.9-pre2/drivers/isdn/isdn_common.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/isdn/isdn_common.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.114.6.12 2001/06/09 15:14:15 kai Exp $
+/* $Id: isdn_common.c,v 1.114.6.13 2001/08/13 07:46:15 kai Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -51,7 +51,7 @@
 
 isdn_dev *dev;
 
-static char *isdn_revision = "$Revision: 1.114.6.12 $";
+static char *isdn_revision = "$Revision: 1.114.6.13 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
diff -urN linux-2.4.9-pre2/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c
--- linux-2.4.9-pre2/drivers/isdn/isdnloop/isdnloop.c	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/isdnloop/isdnloop.c	Mon Dec  3 23:02:45 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.11.6.3 2001/06/09 15:14:19 kai Exp $
+/* $Id: isdnloop.c,v 1.11.6.4 2001/07/13 09:20:12 kai Exp $
 
  * ISDN low-level module implementing a dummy loop driver.
  *
@@ -26,7 +26,7 @@
 #include "isdnloop.h"
 
 static char
-*revision = "$Revision: 1.11.6.3 $";
+*revision = "$Revision: 1.11.6.4 $";
 
 static int isdnloop_addcard(char *);
 
@@ -1518,16 +1518,11 @@
 static int
 isdnloop_addcard(char *id1)
 {
-	ulong flags;
 	isdnloop_card *card;
 
-	save_flags(flags);
-	cli();
 	if (!(card = isdnloop_initcard(id1))) {
-		restore_flags(flags);
 		return -EIO;
 	}
-	restore_flags(flags);
 	printk(KERN_INFO
 	       "isdnloop: (%s) virtual card added\n",
 	       card->interface.id);
diff -urN linux-2.4.9-pre2/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- linux-2.4.9-pre2/drivers/parport/ChangeLog	Mon Dec  3 23:02:36 2001
+++ linux/drivers/parport/ChangeLog	Mon Dec  3 23:02:45 2001
@@ -1,3 +1,7 @@
+2001-08-11  Tim Waugh  <twaugh@redhat.com>
+
+	* parport_pc.c: Support for Titan Electronics cards.
+
 2001-08-08  Tim Waugh  <twaugh@redhat.com>
 
 	* share.c (parport_unregister_device): Remove device from wait list
diff -urN linux-2.4.9-pre2/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- linux-2.4.9-pre2/drivers/parport/parport_pc.c	Tue Jul 10 16:07:46 2001
+++ linux/drivers/parport/parport_pc.c	Mon Dec  3 23:02:45 2001
@@ -2545,6 +2545,8 @@
 	timedia_9018a,
 	syba_2p_epp,
 	syba_1p_ecp,
+	titan_010l,
+	titan_1284p2,
 };
 
 
@@ -2611,6 +2613,8 @@
                                            a 1K io window */
 	/* syba_2p_epp AP138B */	{ 2, { { 0, 0x078 }, { 0, 0x178 }, } },
 	/* syba_1p_ecp W83787 */	{ 1, { { 0, 0x078 }, } },
+	/* titan_010l */		{ 1, { { 3, -1 }, } },
+	/* titan_1284p2 */		{ 2, { { 0, 1 }, { 2, 3 }, } },
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
@@ -2696,6 +2700,9 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp },
 	{ PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
+	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
+	{ 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff -urN linux-2.4.9-pre2/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux-2.4.9-pre2/drivers/pci/pci.c	Mon Dec  3 23:02:36 2001
+++ linux/drivers/pci/pci.c	Mon Dec  3 23:02:45 2001
@@ -22,6 +22,7 @@
 #include <linux/pm.h>
 #include <linux/kmod.h>		/* for hotplug_path */
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
@@ -942,8 +943,7 @@
 {
 	struct pci_dev *dev = child->self;
 	u8 io_base_lo, io_limit_lo;
-	u16 mem_base_lo, mem_limit_lo, io_base_hi, io_limit_hi;
-	u32 mem_base_hi, mem_limit_hi;
+	u16 mem_base_lo, mem_limit_lo;
 	unsigned long base, limit;
 	struct resource *res;
 	int i;
@@ -957,10 +957,17 @@
 	res = child->resource[0];
 	pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
 	pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
-	pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
-	pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
-	base = ((io_base_lo & PCI_IO_RANGE_MASK) << 8) | (io_base_hi << 16);
-	limit = ((io_limit_lo & PCI_IO_RANGE_MASK) << 8) | (io_limit_hi << 16);
+	base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
+	limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+
+	if ((base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+		u16 io_base_hi, io_limit_hi;
+		pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+		pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+		base |= (io_base_hi << 16);
+		limit |= (io_limit_hi << 16);
+	}
+
 	if (base && base <= limit) {
 		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
 		res->start = base;
@@ -994,19 +1001,23 @@
 	res = child->resource[2];
 	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
 	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
-	pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
-	pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
-	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
-	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+	base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+	limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+
+	if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+		u32 mem_base_hi, mem_limit_hi;
+		pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+		pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
 #if BITS_PER_LONG == 64
-	base |= ((long) mem_base_hi) << 32;
-	limit |= ((long) mem_limit_hi) << 32;
+		base |= ((long) mem_base_hi) << 32;
+		limit |= ((long) mem_limit_hi) << 32;
 #else
-	if (mem_base_hi || mem_limit_hi) {
-		printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
-		return;
-	}
+		if (mem_base_hi || mem_limit_hi) {
+			printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
+			return;
+		}
 #endif
+	}
 	if (base && base <= limit) {
 		res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
 		res->start = base;
diff -urN linux-2.4.9-pre2/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c
--- linux-2.4.9-pre2/drivers/scsi/scsi_scan.c	Thu Jul  5 11:28:17 2001
+++ linux/drivers/scsi/scsi_scan.c	Mon Dec  3 23:02:45 2001
@@ -153,6 +153,10 @@
 	{"DELL", "PSEUDO DEVICE .",   "*", BLIST_SPARSELUN}, // Dell PV 530F
 	{"DELL", "PV530F",    "*", BLIST_SPARSELUN}, // Dell PV 530F
 	{"EMC", "SYMMETRIX", "*", BLIST_SPARSELUN},
+	{"CMD", "CRA-7280", "*", BLIST_SPARSELUN},   // CMD RAID Controller
+	{"CNSI", "G7324", "*", BLIST_SPARSELUN},     // Chaparral G7324 RAID
+	{"Zzyzx", "RocketStor 500S", "*", BLIST_SPARSELUN},
+	{"Zzyzx", "RocketStor 2000", "*", BLIST_SPARSELUN},
 	{"SONY", "TSL",       "*", BLIST_FORCELUN},  // DDS3 & DDS4 autoloaders
 	{"DELL", "PERCRAID", "*", BLIST_FORCELUN},
 	{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
@@ -565,20 +569,26 @@
 	}
 
 	/*
-	 * Check the peripheral qualifier field - this tells us whether LUNS
-	 * are supported here or not.
+	 * Check for SPARSELUN before checking the peripheral qualifier,
+	 * so sparse lun devices are completely scanned.
 	 */
-	if ((scsi_result[0] >> 5) == 3) {
-		scsi_release_request(SRpnt);
-		return 0;	/* assume no peripheral if any sort of error */
-	}
 
 	/*
 	 * Get any flags for this device.  
 	 */
 	bflags = get_device_flags (scsi_result);
 
-
+	if (bflags & BLIST_SPARSELUN) {
+	  *sparse_lun = 1;
+	}
+	/*
+	 * Check the peripheral qualifier field - this tells us whether LUNS
+	 * are supported here or not.
+	 */
+	if ((scsi_result[0] >> 5) == 3) {
+		scsi_release_request(SRpnt);
+		return 0;	/* assume no peripheral if any sort of error */
+	}
 	 /*   The Toshiba ROM was "gender-changed" here as an inline hack.
 	      This is now much more generic.
 	      This is a mess: What we really want is to leave the scsi_result
diff -urN linux-2.4.9-pre2/fs/Makefile linux/fs/Makefile
--- linux-2.4.9-pre2/fs/Makefile	Tue May 22 09:35:42 2001
+++ linux/fs/Makefile	Mon Dec  3 23:02:45 2001
@@ -7,7 +7,7 @@
 
 O_TARGET := fs.o
 
-export-objs :=	filesystems.o dcache.o
+export-objs :=	filesystems.o open.o dcache.o
 mod-subdirs :=	nls
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
diff -urN linux-2.4.9-pre2/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.9-pre2/fs/buffer.c	Fri Aug 10 16:35:26 2001
+++ linux/fs/buffer.c	Mon Dec  3 23:02:45 2001
@@ -2399,7 +2399,6 @@
 {
 	struct buffer_head * tmp, * bh = page->buffers;
 	int index = BUFSIZE_INDEX(bh->b_size);
-	int loop = 0;
 
 cleaned_buffers_try_again:
 	spin_lock(&lru_list_lock);
@@ -2449,8 +2448,8 @@
 	if (gfp_mask & __GFP_IO) {
 		sync_page_buffers(bh, gfp_mask);
 		/* We waited synchronously, so we can free the buffers. */
-		if ((gfp_mask & __GFP_WAIT) && !loop) {
-			loop = 1;
+		if (gfp_mask & __GFP_WAIT) {
+			gfp_mask = 0;	/* no IO or waiting this time around */
 			goto cleaned_buffers_try_again;
 		}
 		wakeup_bdflush();
diff -urN linux-2.4.9-pre2/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
--- linux-2.4.9-pre2/fs/nfsd/nfs3xdr.c	Mon Dec  3 23:02:36 2001
+++ linux/fs/nfsd/nfs3xdr.c	Mon Dec  3 23:02:45 2001
@@ -730,14 +730,14 @@
 
 int
 nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
-		     int namlen, off_t offset, ino_t ino, unsigned int d_type)
+		     int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
 	return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
 }
 
 int
 nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
-			  int namlen, off_t offset, ino_t ino, unsigned int d_type)
+			  int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
 	return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
 }
diff -urN linux-2.4.9-pre2/fs/nfsd/nfsxdr.c linux/fs/nfsd/nfsxdr.c
--- linux-2.4.9-pre2/fs/nfsd/nfsxdr.c	Mon Dec  3 23:02:36 2001
+++ linux/fs/nfsd/nfsxdr.c	Mon Dec  3 23:02:45 2001
@@ -391,7 +391,7 @@
 
 int
 nfssvc_encode_entry(struct readdir_cd *cd, const char *name,
-		    int namlen, off_t offset, ino_t ino, unsigned int d_type)
+		    int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
 	u32	*p = cd->buffer;
 	int	buflen, slen;
diff -urN linux-2.4.9-pre2/fs/ntfs/Makefile linux/fs/ntfs/Makefile
--- linux-2.4.9-pre2/fs/ntfs/Makefile	Mon Jul 16 15:14:10 2001
+++ linux/fs/ntfs/Makefile	Mon Dec  3 23:02:45 2001
@@ -5,7 +5,7 @@
 obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o
 obj-m   := $(O_TARGET)
 # New version format started 3 February 2001.
-EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.15\" #-DDEBUG
+EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.16\" #-DDEBUG
 
 include $(TOPDIR)/Rules.make
 
diff -urN linux-2.4.9-pre2/fs/ntfs/dir.c linux/fs/ntfs/dir.c
--- linux-2.4.9-pre2/fs/ntfs/dir.c	Mon Jul 23 16:23:58 2001
+++ linux/fs/ntfs/dir.c	Mon Dec  3 23:02:45 2001
@@ -789,7 +789,7 @@
 	int block;
 	int start;
 	ntfs_attribute *attr;
-	ntfs_volume *vol = ino->vol;
+	ntfs_volume *vol;
 	int byte, bit;
 	int error = 0;
 
@@ -797,6 +797,7 @@
 		ntfs_error("No inode passed to getdir_unsorted\n");
 		return -EINVAL;
 	}
+	vol = ino->vol;
 	if (!vol) {
 		ntfs_error("Inode %d has no volume\n", ino->i_number);
 		return -EINVAL;
diff -urN linux-2.4.9-pre2/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- linux-2.4.9-pre2/fs/ntfs/fs.c	Mon Jul 16 15:14:10 2001
+++ linux/fs/ntfs/fs.c	Mon Dec  3 23:02:45 2001
@@ -1,8 +1,8 @@
 /*
  * fs.c - NTFS driver for Linux 2.4.x
  *
- * Development has as of recently (since June '01) been sponsored
- * by Legato Systems, Inc. (http://www.legato.com)
+ * Legato Systems, Inc. (http://www.legato.com) have sponsored Anton
+ * Altaparmakov to develop NTFS on Linux since June 2001.
  *
  * Copyright (C) 1995-1997, 1999 Martin von Löwis
  * Copyright (C) 1996 Richard Russon
@@ -286,25 +286,25 @@
 }
 
 /* Parse the (re)mount options. */
-static int parse_options(ntfs_volume* vol, char *opt)
+static int parse_options(ntfs_volume *vol, char *opt, int remount)
 {
-	char *value;
-
-	vol->uid = vol->gid = 0;
-	vol->umask = 0077;
-	vol->ngt = ngt_nt;
-	vol->nls_map = 0;
-	vol->nct = 0;
+	char *value;		/* Defaults if not specified and !remount. */
+	ntfs_uid_t uid = -1;	/* 0, root user only */
+	ntfs_gid_t gid = -1;	/* 0, root user only */
+	int umask = -1;		/* 0077, owner access only */
+	unsigned int ngt = -1;	/* ngt_nt */
+	void *nls_map = NULL;	/* Try to load the default NLS. */
+	int use_utf8 = -1;	/* If no NLS specified and loading the default
+				   NLS failed use utf8. */
 	if (!opt)
 		goto done;
-	for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ","))
-	{
+	for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {
 		if ((value = strchr(opt, '=')) != NULL)
 			*value ++= '\0';
 		if (strcmp(opt, "uid") == 0) {
 			if (!value || !*value)
 				goto needs_arg;
-			vol->uid = simple_strtoul(value, &value, 0);
+			uid = simple_strtoul(value, &value, 0);
 			if (*value) {
 				printk(KERN_ERR "NTFS: uid invalid argument\n");
 				return 0;
@@ -312,7 +312,7 @@
 		} else if (strcmp(opt, "gid") == 0) {
 			if (!value || !*value)
 				goto needs_arg;
-			vol->gid = simple_strtoul(value, &value, 0);
+			gid = simple_strtoul(value, &value, 0);
 			if (*value) {
 				printk(KERN_ERR "NTFS: gid invalid argument\n");
 				return 0;
@@ -320,79 +320,86 @@
 		} else if (strcmp(opt, "umask") == 0) {
 			if (!value || !*value)
 				goto needs_arg;
-			vol->umask = simple_strtoul(value, &value, 0);
+			umask = simple_strtoul(value, &value, 0);
 			if (*value) {
 				printk(KERN_ERR "NTFS: umask invalid "
 						"argument\n");
 				return 0;
 			}
-		} else if (strcmp(opt, "iocharset") == 0) {
-			if (!value || !*value)
-				goto needs_arg;
-			vol->nls_map = load_nls(value);
-			vol->nct |= nct_map;
-			if (!vol->nls_map) {
-				printk(KERN_ERR "NTFS: charset not found");
-				return 0;
-			}
 		} else if (strcmp(opt, "posix") == 0) {
 			int val;
 			if (!value || !*value)
 				goto needs_arg;
 			if (!simple_getbool(value, &val))
 				goto needs_bool;
-			vol->ngt = val ? ngt_posix : ngt_nt;
+			ngt = val ? ngt_posix : ngt_nt;
 		} else if (strcmp(opt, "show_sys_files") == 0) {
 			int val = 0;
 			if (!value || !*value)
 				val = 1;
 			else if (!simple_getbool(value, &val))
 				goto needs_bool;
-			vol->ngt = val ? ngt_full : ngt_nt;
-		} else if (strcmp(opt, "utf8") == 0) {
-			int val = 0;
+			ngt = val ? ngt_full : ngt_nt;
+		} else if (strcmp(opt, "iocharset") == 0) {
 			if (!value || !*value)
-				val = 1;
-			else if (!simple_getbool(value, &val))
-				goto needs_bool;
-			if (val)
-				vol->nct |= nct_utf8;
-		} else if (strcmp(opt, "uni_xlate") == 0) {
+				goto needs_arg;
+			nls_map = load_nls(value);
+			if (!nls_map) {
+				printk(KERN_ERR "NTFS: charset not found");
+				return 0;
+			}
+		} else if (strcmp(opt, "utf8") == 0) {
 			int val = 0;
-			/* No argument: uni_vfat. boolean argument: uni_vfat.
-			 * "2": uni. */
 			if (!value || !*value)
 				val = 1;
-			else if (strcmp(value, "2") == 0)
-				vol->nct |= nct_uni_xlate;
 			else if (!simple_getbool(value, &val))
 				goto needs_bool;
-			if (val)
-				vol->nct |= nct_uni_xlate_vfat | nct_uni_xlate;
+			use_utf8 = val;
 		} else {
 			printk(KERN_ERR "NTFS: unkown option '%s'\n", opt);
 			return 0;
 		}
 	}
-	if (vol->nct & nct_utf8 & (nct_map | nct_uni_xlate)) {
-		printk(KERN_ERR "utf8 cannot be combined with iocharset or "
-				"uni_xlate\n");
-		return 0;
-	}
- done:
-	if ((vol->nct & (nct_uni_xlate | nct_map | nct_utf8)) == 0)
-		/* default to UTF-8 */
-		vol->nct = nct_utf8;
-	if (!vol->nls_map) {
-		vol->nls_map = load_nls_default();
-		if (vol->nls_map)
-			vol->nct = nct_map | (vol->nct&nct_uni_xlate);
-	}
+done:
+	if (use_utf8 != -1 && use_utf8) {
+		if (nls_map) {
+			unload_nls(nls_map);
+			printk(KERN_ERR "NTFS: utf8 cannot be combined with "
+					"iocharset.\n");
+			return 0;
+		}
+		if (remount && vol->nls_map)
+			unload_nls(vol->nls_map);
+		vol->nls_map = NULL;
+	} else {
+		if (nls_map) {
+			if (remount && vol->nls_map)
+				unload_nls(vol->nls_map);
+			vol->nls_map = nls_map;
+		} else if (!remount || (remount && !use_utf8 && !vol->nls_map))
+			vol->nls_map = load_nls_default();
+	}
+	if (uid != -1)
+		vol->uid = uid;
+	else if (!remount)
+		vol->uid = 0;
+	if (gid != -1)
+		vol->gid = gid;
+	else if (!remount)
+		vol->gid = 0;
+	if (umask != -1)
+		vol->umask = (ntmode_t)umask;
+	else if (!remount)
+		vol->umask = 0077;
+	if (ngt != -1)
+		vol->ngt = ngt;
+	else if (!remount)
+		vol->ngt = ngt_nt;
 	return 1;
- needs_arg:
+needs_arg:
 	printk(KERN_ERR "NTFS: %s needs an argument", opt);
 	return 0;
- needs_bool:
+needs_bool:
 	printk(KERN_ERR "NTFS: %s needs boolean argument", opt);
 	return 0;
 }
@@ -898,7 +905,7 @@
 /* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */
 static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options)
 {
-	if (!parse_options(NTFS_SB2VOL(sb), options))
+	if (!parse_options(NTFS_SB2VOL(sb), options, 1))
 		return -EINVAL;
 	return 0;
 }
@@ -1003,7 +1010,7 @@
 
 	ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
 	vol = NTFS_SB2VOL(sb);
-	if (!parse_options(vol, (char*)options))
+	if (!parse_options(vol, (char*)options, 0))
 		goto ntfs_read_super_vol;
 	/* Assume a 512 bytes block device for now. */
 	set_blocksize(sb->s_dev, 512);
diff -urN linux-2.4.9-pre2/fs/ntfs/support.c linux/fs/ntfs/support.c
--- linux-2.4.9-pre2/fs/ntfs/support.c	Mon Jul 16 15:14:10 2001
+++ linux/fs/ntfs/support.c	Mon Dec  3 23:02:45 2001
@@ -225,147 +225,81 @@
 	return ntfs_unixutc2ntutc(CURRENT_TIME);
 }
 
-/* When printing unicode characters base64, use this table. It is not strictly
- * base64, but the Linux vfat encoding. base64 has the disadvantage of using
- * the slash. */
-static char uni2esc[64] = 
-	    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-";
-
-static unsigned char esc2uni(char c)
-{
-	if (c <  '0') return 255;
-	if (c <= '9') return c - '0';
-	if (c <  'A') return 255;
-	if (c <= 'Z') return c - 'A' + 10;
-	if (c <  'a') return 255;
-	if (c <= 'z') return c - 'a' + 36;
-	if (c == '+') return 62;
-	if (c == '-') return 63;
-	return 255;
-}
-
 int ntfs_dupuni2map(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
-		    int *out_len)
+		int *out_len)
 {
-	int i, o, val, chl, chi;
+	int i, o, chl, chi;
 	char *result, *buf, charbuf[NLS_MAX_CHARSET_SIZE];
-	struct nls_table* nls = vol->nls_map;
+	struct nls_table *nls = vol->nls_map;
 
 	result = ntfs_malloc(in_len + 1);
 	if (!result)
 		return -ENOMEM;
 	*out_len = in_len;
-	result[in_len] = '\0';
 	for (i = o = 0; i < in_len; i++) {
-		int cl, ch;
-		/* FIXME: byte order? */
-		cl = in[i] & 0xFF;
-		ch = (in[i] >> 8) & 0xFF;
-		if (!nls) {
-			if (!ch) {
-				result[o++] = cl;
-				continue;
-			}
-		} else {
-			/* FIXME: byte order? */
-			wchar_t uni = in[i];
-			if ((chl = nls->uni2char(uni, charbuf,
-						NLS_MAX_CHARSET_SIZE)) > 0) {
-				/* adjust result buffer */
-				if (chl > 1) {
-					buf = ntfs_malloc(*out_len + chl - 1);
-					if (!buf) {
-						ntfs_free(result);
-						return -ENOMEM;
-					}
-					memcpy(buf, result, o);
+		/* FIXME: Byte order? */
+		wchar_t uni = in[i];
+		if ((chl = nls->uni2char(uni, charbuf,
+				NLS_MAX_CHARSET_SIZE)) > 0) {
+			/* Adjust result buffer. */
+			if (chl > 1) {
+				buf = ntfs_malloc(*out_len + chl - 1);
+				if (!buf) {
 					ntfs_free(result);
-					result = buf;
-					*out_len += (chl - 1);
+					return -ENOMEM;
 				}
-				for (chi = 0; chi < chl; chi++)
-					result[o++] = charbuf[chi];
-			} else
-				result[o++] = '?';
-			continue;
-		}
-		if (!(vol->nct & nct_uni_xlate))
-			goto inval;
-		/* realloc */
-		buf = ntfs_malloc(*out_len + 3);
-		if (!buf) {
-			ntfs_free(result);
-			return -ENOMEM;
-		}
-		memcpy(buf, result, o);
-		ntfs_free(result);
-		result = buf;
-		*out_len += 3;
-		result[o++] = ':';
-		if (vol->nct & nct_uni_xlate_vfat) {
-			val = (cl << 8) + ch;
-			result[o+2] = uni2esc[val & 0x3f];
-			val >>= 6;
-			result[o+1] = uni2esc[val & 0x3f];
-			val >>= 6;
-			result[o] = uni2esc[val & 0x3f];
-			o += 3;
+				memcpy(buf, result, o);
+				ntfs_free(result);
+				result = buf;
+				*out_len += (chl - 1);
+			}
+			for (chi = 0; chi < chl; chi++)
+				result[o++] = charbuf[chi];
 		} else {
-			val = (ch << 8) + cl;
-			result[o++] = uni2esc[val & 0x3f];
-			val >>= 6;
-			result[o++] = uni2esc[val & 0x3f];
-			val >>= 6;
-			result[o++] = uni2esc[val & 0x3f];
+			/* Invalid character. */
+			printk(KERN_ERR "NTFS: Unicode name contains a "
+					"character that cannot be converted "
+					"to chosen character set. Remount "
+					"with utf8 encoding and this should "
+					"work.\n");
+			ntfs_free(result);
+			return -EILSEQ;
 		}
 	}
+	result[*out_len] = '\0';
 	*out = result;
 	return 0;
- inval:
-	ntfs_free(result);
-	*out = 0;
-	return -EILSEQ;
 }
 
 int ntfs_dupmap2uni(ntfs_volume *vol, char* in, int in_len, ntfs_u16 **out,
-		    int *out_len)
+		int *out_len)
 {
 	int i, o;
-	ntfs_u16* result;
-	struct nls_table* nls = vol->nls_map;
+	ntfs_u16 *result;
+	struct nls_table *nls = vol->nls_map;
 
-	*out=result = ntfs_malloc(2 * in_len);
+	*out = result = ntfs_malloc(2 * in_len);
 	if (!result)
 		return -ENOMEM;
 	*out_len = in_len;
-	for (i = o = 0; i < in_len; i++, o++){
+	for (i = o = 0; i < in_len; i++, o++) {
 		wchar_t uni;
-		if (in[i] != ':' || (vol->nct & nct_uni_xlate) == 0){
-			int charlen;
-			charlen = nls->char2uni(&in[i], in_len-i, &uni);
-			if (charlen < 0)
-				return charlen;
-			*out_len -= (charlen - 1);
-			i += (charlen - 1);
-		} else {
-			unsigned char c1, c2, c3;
-			*out_len -= 3;
-			c1 = esc2uni(in[++i]);
-			c2 = esc2uni(in[++i]);
-			c3 = esc2uni(in[++i]);
-			if (c1 == 255 || c2 == 255 || c3 == 255)
-				uni = 0;
-			else if (vol->nct & nct_uni_xlate_vfat) {
-				uni = (((c2 & 0x3) << 6) + c3) << 8 |
-				      ((c1 << 4) + (c2 >> 2));
-			} else {
-				uni = ((c3 << 4) + (c2 >> 2)) << 8 |
-				      (((c2 & 0x3) << 6) + c1);
-			}
+		int charlen;
+
+		charlen = nls->char2uni(&in[i], in_len - i, &uni);
+		if (charlen < 0) {
+			printk(KERN_ERR "NTFS: Name contains a character that "
+					"cannot be converted to Unicode.\n");
+			ntfs_free(result);
+			return charlen;
 		}
-		/* FIXME: byte order? */
+		*out_len -= charlen - 1;
+		i += charlen - 1;
+		/* FIXME: Byte order? */
 		result[o] = uni;
 		if (!result[o]) {
+			printk(KERN_ERR "NTFS: Name contains a character that "
+					"cannot be converted to Unicode.\n");
 			ntfs_free(result);
 			return -EILSEQ;
 		}
diff -urN linux-2.4.9-pre2/fs/ntfs/util.c linux/fs/ntfs/util.c
--- linux-2.4.9-pre2/fs/ntfs/util.c	Mon Jul 16 15:14:10 2001
+++ linux/fs/ntfs/util.c	Mon Dec  3 23:02:45 2001
@@ -13,12 +13,15 @@
 #include "util.h"
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <asm/div64.h>		/* For do_div(). */
 #include "support.h"
 
-/* Converts a single wide character to a sequence of utf8 bytes.
+/*
+ * Converts a single wide character to a sequence of utf8 bytes.
  * The character is represented in host byte order.
- * Returns the number of bytes, or 0 on error. */
-static int to_utf8(ntfs_u16 c, unsigned char* buf)
+ * Returns the number of bytes, or 0 on error.
+ */
+static int to_utf8(ntfs_u16 c, unsigned char *buf)
 {
 	if (c == 0)
 		return 0; /* No support for embedded 0 runes. */
@@ -34,22 +37,21 @@
 		}
 		return 2;
 	}
-	if (c < 0x10000) {
-		if (buf) {
-			buf[0] = 0xe0 | (c >> 12);
-			buf[1] = 0x80 | ((c >> 6) & 0x3f);
-			buf[2] = 0x80 | (c & 0x3f);
-		}
-		return 3;
+	/* c < 0x10000 */
+	if (buf) {
+		buf[0] = 0xe0 | (c >> 12);
+		buf[1] = 0x80 | ((c >> 6) & 0x3f);
+		buf[2] = 0x80 | (c & 0x3f);
 	}
-	/* We don't support characters above 0xFFFF in NTFS. */
-	return 0;
+	return 3;
 }
 
-/* Decodes a sequence of utf8 bytes into a single wide character.
+/*
+ * Decodes a sequence of utf8 bytes into a single wide character.
  * The character is returned in host byte order.
- * Returns the number of bytes consumed, or 0 on error. */
-static int from_utf8(const unsigned char* str, ntfs_u16 *c)
+ * Returns the number of bytes consumed, or 0 on error.
+ */
+static int from_utf8(const unsigned char *str, ntfs_u16 *c)
 {
 	int l = 0, i;
 
@@ -80,11 +82,12 @@
 	return l;
 }
 
-/* Converts wide string to UTF-8. Expects two in- and two out-parameters.
+/*
+ * Converts wide string to UTF-8. Expects two in- and two out-parameters.
  * Returns 0 on success, or error code. 
  * The caller has to free the result string.
- * There is no support for UTF-16, yet. */
-static int ntfs_dupuni2utf8(ntfs_u16* in, int in_len, char **out, int *out_len)
+ */
+static int ntfs_dupuni2utf8(ntfs_u16 *in, int in_len, char **out, int *out_len)
 {
 	int i, tmp;
 	int len8;
@@ -92,15 +95,14 @@
 
 	ntfs_debug(DEBUG_NAME1, "converting l = %d\n", in_len);
 	/* Count the length of the resulting UTF-8. */
-	for (i = len8 = 0; i < in_len; i++){
+	for (i = len8 = 0; i < in_len; i++) {
 		tmp = to_utf8(NTFS_GETU16(in + i), 0);
 		if (!tmp)
-			/* invalid character */
+			/* Invalid character. */
 			return -EILSEQ;
 		len8 += tmp;
 	}
 	*out = result = ntfs_malloc(len8 + 1); /* allow for zero-termination */
-
 	if (!result)
 		return -ENOMEM;
 	result[len8] = '\0';
@@ -111,10 +113,12 @@
 	return 0;
 }
 
-/* Converts an UTF-8 sequence to a wide string. Same conventions as the
- * previous function. */
+/*
+ * Converts an UTF-8 sequence to a wide string. Same conventions as the
+ * previous function.
+ */
 static int ntfs_duputf82uni(unsigned char* in, int in_len, ntfs_u16** out,
-			    int *out_len)
+		int *out_len)
 {
 	int i, tmp;
 	int len16;
@@ -131,76 +135,30 @@
 		return -ENOMEM;
 	result[len16] = 0;
 	*out_len = len16;
-	for (i = len16 = 0; i < in_len; i += tmp, len16++)
-	{
+	for (i = len16 = 0; i < in_len; i += tmp, len16++) {
 		tmp = from_utf8(in + i, &wtmp);
 		NTFS_PUTU16(result + len16, wtmp);
 	}
 	return 0;
 }
 
-/* See above. Produces ISO-8859-1 from wide strings. */
-static int ntfs_dupuni288591(ntfs_u16* in, int in_len, char** out, int *out_len)
-{
-	int i;
-	char *result;
-
-	/* Check for characters out of range. */
-	for (i = 0; i < in_len; i++)
-		if (NTFS_GETU16(in + i) >= 256)
-			return -EILSEQ;
-	*out = result = ntfs_malloc(in_len + 1);
-	if (!result)
-		return -ENOMEM;
-	result[in_len] = '\0';
-	*out_len = in_len;
-	for (i = 0; i < in_len; i++)
-		result[i] = (unsigned char)NTFS_GETU16(in + i);
-	return 0;
-}
-
-/* See above. */
-static int ntfs_dup885912uni(unsigned char* in, int in_len, ntfs_u16 **out,
-			     int *out_len)
-{
-	int i;
-
-	ntfs_u16* result;
-	*out = result = ntfs_malloc(2 * in_len);
-	if (!result)
-		return -ENOMEM;
-	*out_len = in_len;
-	for (i = 0; i < in_len; i++)
-		NTFS_PUTU16(result + i, in[i]);
-	return 0;
-}
-
-/* Encodings dispatcher */
+/* Encodings dispatchers. */
 int ntfs_encodeuni(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
-		   int *out_len)
+		int *out_len)
 {
-	if (vol->nct & nct_utf8)
-		return ntfs_dupuni2utf8(in, in_len, out, out_len);
-	else if (vol->nct & nct_iso8859_1)
-		return ntfs_dupuni288591(in, in_len, out, out_len);
-	else if(vol->nct & (nct_map | nct_uni_xlate))
-		/* uni_xlate is handled inside map. */
+	if (vol->nls_map)
 		return ntfs_dupuni2map(vol, in, in_len, out, out_len);
 	else
-		return -EINVAL; /* unknown encoding */
+		return ntfs_dupuni2utf8(in, in_len, out, out_len);
 }
 
 int ntfs_decodeuni(ntfs_volume *vol, char *in, int in_len, ntfs_u16 **out,
-		   int *out_len)
+		int *out_len)
 {
-	if (vol->nct & nct_utf8)
-		return ntfs_duputf82uni(in, in_len, out, out_len);
-	else if (vol->nct & nct_iso8859_1)
-		return ntfs_dup885912uni(in, in_len, out, out_len);
-	else if (vol->nct & (nct_map | nct_uni_xlate))
+	if (vol->nls_map)
 		return ntfs_dupmap2uni(vol, in, in_len, out, out_len);
 	else
-		return -EINVAL;
+		return ntfs_duputf82uni(in, in_len, out, out_len);
 }
 
 /* Same address space copies. */
@@ -224,18 +182,6 @@
 	return result;
 }
 
-#if 0
-/* Copy len unicode characters from from to to. :) */
-void ntfs_uni2ascii(char *to, short int *from, int len)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		to[i] = NTFS_GETU16(from + i);
-	to[i] = '\0';
-}
-#endif
-
 /* Copy len ascii characters from from to to. :) */
 void ntfs_ascii2uni(short int *to, char *from, int len)
 {
@@ -279,57 +225,26 @@
 	return 0;
 }
 
+#define NTFS_TIME_OFFSET ((ntfs_time64_t)(369*365 + 89) * 24 * 3600 * 10000000)
+
 /* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units)
  * into Unix UTC (based 1.1.1970, in seconds). */
 ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc)
 {
-/* This is very gross because:
- * 1: We must do 64-bit division on a 32-bit machine.
- * 2: We can't use libgcc for long long operations in the kernel.
- * 3: Floating point math in the kernel would corrupt user data. */
-	const unsigned int D = 10000000;
-	unsigned int H = (unsigned int)(ntutc >> 32);
-	unsigned int L = (unsigned int)ntutc;
-	unsigned int numerator2;
-	unsigned int lowseconds;
-	unsigned int result;
-
-	/* It is best to subtract 0x019db1ded53e8000 first. */
-	/* Then the 1601-based date becomes a 1970-based date. */
-	if (L < (unsigned)0xd53e8000)
-		H--;
-	L -= (unsigned)0xd53e8000;
-	H -= (unsigned)0x019db1de;
-
-	/* Now divide 64-bit numbers on a 32-bit machine. :-)
-	 * With the subtraction already done, the result fits in 32 bits.
-	 * The numerator fits in 56 bits and the denominator fits
-	 * in 24 bits, so we can shift by 8 bits to make this work. */
-
-	numerator2  = (H << 8) | (L >> 24);
-	result      = (numerator2 / D);   /* shifted 24 right!! */
-	lowseconds  = result << 24;
-
-	numerator2  = ((numerator2 - result * D) << 8) | ((L >> 16) & 0xff);
-	result      = (numerator2 / D);   /* shifted 16 right!! */
-	lowseconds |= result << 16;
-
-	numerator2  = ((numerator2 - result * D) << 8) | ((L >> 8) & 0xff);
-	result      = (numerator2 / D);   /* shifted 8 right!! */
-	lowseconds |= result << 8;
-
-	numerator2  = ((numerator2 - result * D) << 8) | (L & 0xff);
-	result      = (numerator2 / D);   /* not shifted */
-	lowseconds |= result;
-
-	return lowseconds;
+	/* Subtract the NTFS time offset, then convert to 1s intervals. */
+	ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET;
+	do_div(t, 10000000);
+	return (ntfs_time_t)t;
 }
 
 /* Convert the Unix UTC into NT UTC. */
 ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t)
 {
-	return ((t + (ntfs_time64_t)(369 * 365 + 89) * 24 * 3600) * 10000000);
+	/* Convert to 100ns intervals and then add the NTFS time offset. */
+	return (ntfs_time64_t)t * 10000000 + NTFS_TIME_OFFSET;
 }
+
+#undef NTFS_TIME_OFFSET
 
 /* Fill index name. */
 void ntfs_indexname(char *buf, int type)
diff -urN linux-2.4.9-pre2/fs/ntfs/util.h linux/fs/ntfs/util.h
--- linux-2.4.9-pre2/fs/ntfs/util.h	Mon Jul 16 15:14:10 2001
+++ linux/fs/ntfs/util.h	Mon Dec  3 23:02:45 2001
@@ -5,18 +5,6 @@
  * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
 
-/* Which character set is used for file names. */
-/*  Translate everything to UTF-8. */
-#define nct_utf8             1
-/*  Translate to 8859-1. */
-#define nct_iso8859_1        2
-/*  Quote unprintables with ":". */
-#define nct_uni_xlate        4
-/*  Do that in the vfat way instead of the documented way. */
-#define nct_uni_xlate_vfat   8
-/*  Use a mapping table to determine printables. */
-#define nct_map              16
-
 /* The first 16 inodes correspond to NTFS special files. */
 typedef enum {
 	FILE_$Mft	= 0,
@@ -42,9 +30,6 @@
 
 /* String operations */
 /*  Copy Unicode <-> ASCII */
-#if 0
-void ntfs_uni2ascii(char *to, char *from, int len);
-#endif
 void ntfs_ascii2uni(short int *to, char *from, int len);
 
 /*  Comparison */
diff -urN linux-2.4.9-pre2/fs/open.c linux/fs/open.c
--- linux-2.4.9-pre2/fs/open.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/open.c	Mon Dec  3 23:02:45 2001
@@ -847,3 +847,18 @@
 	}
 	return -EPERM;
 }
+
+/*
+ * Called when an inode is about to be open.
+ * We use this to disallow opening RW large files on 32bit systems if
+ * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
+ * on this flag in sys_open.
+ */
+int generic_file_open(struct inode * inode, struct file * filp)
+{
+	if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
+		return -EFBIG;
+	return 0;
+}
+
+EXPORT_SYMBOL(generic_file_open);
diff -urN linux-2.4.9-pre2/include/linux/apm_bios.h linux/include/linux/apm_bios.h
--- linux-2.4.9-pre2/include/linux/apm_bios.h	Wed Jul  4 11:50:39 2001
+++ linux/include/linux/apm_bios.h	Mon Dec  3 23:02:45 2001
@@ -52,6 +52,7 @@
 	struct apm_bios_info	bios;
 	unsigned short		connection_version;
 	int			get_power_status_broken;
+	int			get_power_status_swabinminutes;
 	int			allow_ints;
 	int			realmode_power_off;
 	int			disabled;
diff -urN linux-2.4.9-pre2/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.9-pre2/include/linux/fs.h	Mon Dec  3 23:02:36 2001
+++ linux/include/linux/fs.h	Mon Dec  3 23:02:45 2001
@@ -1347,6 +1347,7 @@
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
+extern int generic_file_open(struct inode * inode, struct file * filp);
 
 extern struct file_operations generic_ro_fops;
 
diff -urN linux-2.4.9-pre2/include/linux/i2o.h linux/include/linux/i2o.h
--- linux-2.4.9-pre2/include/linux/i2o.h	Mon Dec  3 23:02:36 2001
+++ linux/include/linux/i2o.h	Mon Dec  3 23:02:45 2001
@@ -30,6 +30,7 @@
 #include <asm/semaphore.h> /* Needed for MUTEX init macros */
 #include <linux/config.h>
 #include <linux/notifier.h>
+#include <linux/ioport.h>
 #include <asm/atomic.h>
 
 /*
diff -urN linux-2.4.9-pre2/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.4.9-pre2/include/linux/ide.h	Fri Aug 10 18:15:44 2001
+++ linux/include/linux/ide.h	Mon Dec  3 23:02:45 2001
@@ -87,6 +87,11 @@
 #define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
 
 /*
+ * state flags
+ */
+#define DMA_PIO_RETRY	1	/* retrying in PIO */
+
+/*
  * Ensure that various configuration flags have compatible settings
  */
 #ifdef REALLY_SLOW_IO
@@ -133,14 +138,6 @@
 #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 GET_ALTSTAT()		IN_BYTE(IDE_CONTROL_REG)
@@ -255,6 +252,27 @@
 #include <asm/ide.h>
 
 /*
+ * If the arch-dependant ide.h did not declare/define any OUT_BYTE
+ * or IN_BYTE functions, we make some defaults here.
+ */
+
+#ifndef HAVE_ARCH_OUT_BYTE
+#ifdef REALLY_FAST_IO
+#define OUT_BYTE(b,p)          outb((b),(p))
+#else
+#define OUT_BYTE(b,p)          outb_p((b),(p))
+#endif
+#endif
+
+#ifndef HAVE_ARCH_IN_BYTE
+#ifdef REALLY_FAST_IO
+#define IN_BYTE(p)             (byte)inb_p(p)
+#else
+#define IN_BYTE(p)             (byte)inb(p)
+#endif
+#endif
+
+/*
  * Now for the data we need to maintain per-drive:  ide_drive_t
  */
 
@@ -286,6 +304,8 @@
 	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	 retry_pio;		/* retrying dma capable host in pio */
+	byte	 state;			/* retry state */
 	byte     waiting_for_dma;	/* dma currently in progress */
 	byte     unmask;		/* flag: okay to unmask other irqs */
 	byte     slow;			/* flag: slow data port */
@@ -349,6 +369,8 @@
 	byte		init_speed;	/* transfer rate set at boot */
 	byte		current_speed;	/* current transfer rate set */
 	byte		dn;		/* now wide spread use */
+	unsigned int	failures;	/* current failure count */
+	unsigned int	max_failures;	/* maximum allowed failure count */
 } ide_drive_t;
 
 /*
@@ -373,6 +395,23 @@
 typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
 
 /*
+ * An ide_ideproc_t() performs CPU-polled transfers to/from a drive.
+ * Arguments are: the drive, the buffer pointer, and the length (in bytes or
+ * words depending on if it's an IDE or ATAPI call).
+ *
+ * If it is not defined for a controller, standard-code is used from ide.c.
+ *
+ * Controllers which are not memory-mapped in the standard way need to 
+ * override that mechanism using this function to work.
+ *
+ */
+typedef enum { ideproc_ide_input_data,    ideproc_ide_output_data,
+	       ideproc_atapi_input_bytes, ideproc_atapi_output_bytes
+} ide_ide_action_t;
+
+typedef void (ide_ideproc_t)(ide_ide_action_t, ide_drive_t *, void *, unsigned int);
+
+/*
  * 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
@@ -397,6 +436,11 @@
 typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t);
 
 /*
+ * ide soft-power support
+ */
+typedef int (ide_busproc_t) (struct hwif_s *, int);
+
+/*
  * hwif_chipset_t is used to keep track of the specific hardware
  * chipset used by each IDE interface, if known.
  */
@@ -405,9 +449,13 @@
 		ide_qd6580,	ide_umc8672,	ide_ht6560b,
 		ide_pdc4030,	ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
-		ide_pmac
+		ide_pmac,       ide_etrax100
 } hwif_chipset_t;
 
+#define IDE_CHIPSET_PCI_MASK	\
+    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
+#define IDE_CHIPSET_IS_PCI(c)	((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
+
 #ifdef CONFIG_BLK_DEV_IDEPCI
 typedef struct ide_pci_devid_s {
 	unsigned short	vid;
@@ -433,12 +481,14 @@
 	ide_maskproc_t	*maskproc;	/* special host masking for drive selection */
 	ide_quirkproc_t	*quirkproc;	/* check host's drive quirk list */
 	ide_rw_proc_t	*rwproc;	/* adjust timing based upon rq->cmd direction */
+	ide_ideproc_t   *ideproc;       /* CPU-polled transfer routine */
 	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
 	unsigned int	*dmatable_cpu;	/* dma physical region descriptor table (cpu view) */
 	dma_addr_t	dmatable_dma;	/* dma physical region descriptor table (dma view) */
 	struct scatterlist *sg_table;	/* Scatter-gather list used to build the above */
 	int sg_nents;			/* Current number of entries in it */
 	int sg_dma_direction;		/* dma transfer direction */
+	int sg_dma_active;		/* is it in use */
 	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 */
@@ -467,6 +517,8 @@
 #endif
 	byte		straight8;	/* Alan's straight 8 check */
 	void		*hwif_data;	/* extra hwif data */
+	ide_busproc_t	*busproc;	/* driver soft-power interface */
+	byte		bus_state;	/* power state of the IDE bus */
 } ide_hwif_t;
 
 
@@ -595,6 +647,7 @@
 typedef unsigned long	(ide_capacity_proc)(ide_drive_t *);
 typedef ide_startstop_t	(ide_special_proc)(ide_drive_t *);
 typedef void		(ide_setting_proc)(ide_drive_t *);
+typedef int		(ide_driver_reinit_proc)(ide_drive_t *);
 
 typedef struct ide_driver_s {
 	const char			*name;
@@ -615,6 +668,7 @@
 	ide_capacity_proc		*capacity;
 	ide_special_proc		*special;
 	ide_proc_entry_t		*proc;
+	ide_driver_reinit_proc		*driver_reinit;
 } ide_driver_t;
 
 #define DRIVER(drive)		((ide_driver_t *)((drive)->driver))
@@ -737,6 +791,12 @@
  * The caller should return immediately after invoking this.
  */
 ide_startstop_t ide_do_reset (ide_drive_t *);
+
+/*
+ * Re-Start an operation for an IDE interface.
+ * The caller should return immediately after invoking this.
+ */
+ide_startstop_t restart_request (ide_drive_t *);
 
 /*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
diff -urN linux-2.4.9-pre2/include/linux/nfsd/nfsd.h linux/include/linux/nfsd/nfsd.h
--- linux-2.4.9-pre2/include/linux/nfsd/nfsd.h	Fri Aug 10 18:14:31 2001
+++ linux/include/linux/nfsd/nfsd.h	Mon Dec  3 23:02:45 2001
@@ -57,7 +57,7 @@
 	char			dotonly;
 };
 typedef int		(*encode_dent_fn)(struct readdir_cd *, const char *,
-						int, off_t, ino_t, unsigned int);
+						int, loff_t, ino_t, unsigned int);
 typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
 
 /*
diff -urN linux-2.4.9-pre2/include/linux/nfsd/xdr.h linux/include/linux/nfsd/xdr.h
--- linux-2.4.9-pre2/include/linux/nfsd/xdr.h	Fri Aug 10 18:15:05 2001
+++ linux/include/linux/nfsd/xdr.h	Mon Dec  3 23:02:45 2001
@@ -151,7 +151,7 @@
 int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *);
 
 int nfssvc_encode_entry(struct readdir_cd *, const char *name,
-				int namlen, off_t offset, ino_t ino, unsigned int);
+				int namlen, loff_t offset, ino_t ino, unsigned int);
 
 int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
 
diff -urN linux-2.4.9-pre2/include/linux/nfsd/xdr3.h linux/include/linux/nfsd/xdr3.h
--- linux-2.4.9-pre2/include/linux/nfsd/xdr3.h	Fri Aug 10 18:15:17 2001
+++ linux/include/linux/nfsd/xdr3.h	Mon Dec  3 23:02:45 2001
@@ -292,10 +292,10 @@
 int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
 				struct nfsd3_fhandle_pair *);
 int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
-				int namlen, off_t offset, ino_t ino,
+				int namlen, loff_t offset, ino_t ino,
 				unsigned int);
 int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
-				int namlen, off_t offset, ino_t ino,
+				int namlen, loff_t offset, ino_t ino,
 				unsigned int);
 
 
diff -urN linux-2.4.9-pre2/include/linux/ntfs_fs_sb.h linux/include/linux/ntfs_fs_sb.h
--- linux-2.4.9-pre2/include/linux/ntfs_fs_sb.h	Mon Jul 16 15:14:10 2001
+++ linux/include/linux/ntfs_fs_sb.h	Mon Dec  3 23:02:45 2001
@@ -8,7 +8,6 @@
 	ntfs_uid_t uid;
 	ntfs_gid_t gid;
 	ntmode_t umask;
-        unsigned int nct;
 	void *nls_map;
 	unsigned int ngt;
 	/* Configuration provided by user with the ntfstools.
diff -urN linux-2.4.9-pre2/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- linux-2.4.9-pre2/include/linux/pci_ids.h	Mon Dec  3 23:02:36 2001
+++ linux/include/linux/pci_ids.h	Mon Dec  3 23:02:45 2001
@@ -1417,8 +1417,13 @@
 #define PCI_DEVICE_ID_AIRONET_4500	0x4800 // drivers/net/aironet4500_card.c
 
 #define PCI_VENDOR_ID_TITAN		0x14D2
+#define PCI_DEVICE_ID_TITAN_010L	0x8001
+#define PCI_DEVICE_ID_TITAN_100L	0x8010
 #define PCI_DEVICE_ID_TITAN_110L	0x8011
+#define PCI_DEVICE_ID_TITAN_200L	0x8020
 #define PCI_DEVICE_ID_TITAN_210L	0x8021
+#define PCI_DEVICE_ID_TITAN_400L	0x8040
+#define PCI_DEVICE_ID_TITAN_800L	0x8080
 #define PCI_DEVICE_ID_TITAN_100		0xA001
 #define PCI_DEVICE_ID_TITAN_200		0xA005
 #define PCI_DEVICE_ID_TITAN_400		0xA003
diff -urN linux-2.4.9-pre2/mm/memory.c linux/mm/memory.c
--- linux-2.4.9-pre2/mm/memory.c	Fri Aug 10 17:45:55 2001
+++ linux/mm/memory.c	Mon Dec  3 23:02:46 2001
@@ -460,7 +460,7 @@
 	if (err)
 		return err;
 
-	down_write(&mm->mmap_sem);
+	down_read(&mm->mmap_sem);
 
 	err = -EFAULT;
 	iobuf->locked = 0;
@@ -518,12 +518,12 @@
 		ptr += PAGE_SIZE;
 	}
 
-	up_write(&mm->mmap_sem);
+	up_read(&mm->mmap_sem);
 	dprintk ("map_user_kiobuf: end OK\n");
 	return 0;
 
  out_unlock:
-	up_write(&mm->mmap_sem);
+	up_read(&mm->mmap_sem);
 	unmap_kiobuf(iobuf);
 	dprintk ("map_user_kiobuf: end %d\n", err);
 	return err;
diff -urN linux-2.4.9-pre2/mm/oom_kill.c linux/mm/oom_kill.c
--- linux-2.4.9-pre2/mm/oom_kill.c	Fri Jul  6 17:02:23 2001
+++ linux/mm/oom_kill.c	Mon Dec  3 23:02:46 2001
@@ -136,26 +136,12 @@
 }
 
 /**
- * oom_kill - kill the "best" process when we run out of memory
- *
- * If we run out of memory, we have the choice between either
- * killing a random task (bad), letting the system crash (worse)
- * OR try to be smart about which process to kill. Note that we
- * don't have to be perfect here, we just have to be good.
- *
  * We must be careful though to never send SIGKILL a process with
  * CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that
  * we select a process with CAP_SYS_RAW_IO set).
  */
-void oom_kill(void)
+void oom_kill_task(struct task_struct *p)
 {
-
-	struct task_struct *p = select_bad_process();
-
-	/* Found nothing?!?! Either we hang forever, or we panic. */
-	if (p == NULL)
-		panic("Out of memory and no killable processes...\n");
-
 	printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
 
 	/*
@@ -172,6 +158,30 @@
 	} else {
 		force_sig(SIGKILL, p);
 	}
+}
+
+/**
+ * oom_kill - kill the "best" process when we run out of memory
+ *
+ * If we run out of memory, we have the choice between either
+ * killing a random task (bad), letting the system crash (worse)
+ * OR try to be smart about which process to kill. Note that we
+ * don't have to be perfect here, we just have to be good.
+ */
+void oom_kill(void)
+{
+	struct task_struct *p = select_bad_process(), *q;
+
+	/* Found nothing?!?! Either we hang forever, or we panic. */
+	if (p == NULL)
+		panic("Out of memory and no killable processes...\n");
+
+	/* kill all processes that share the ->mm (i.e. all threads) */
+	read_lock(&tasklist_lock);
+	for_each_task(q) {
+		if(q->mm == p->mm) oom_kill_task(q);
+	}
+	read_unlock(&tasklist_lock);
 
 	/*
 	 * Make kswapd go out of the way, so "p" has a good chance of
diff -urN linux-2.4.9-pre2/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.9-pre2/mm/vmscan.c	Mon Dec  3 23:02:36 2001
+++ linux/mm/vmscan.c	Mon Dec  3 23:02:46 2001
@@ -477,20 +477,19 @@
  * This code used to be heavily inspired by the FreeBSD source code. 
  * Thanks go out to Matthew Dillon.
  */
-#define MAX_LAUNDER 		(4 * (1 << page_cluster))
 #define CAN_DO_FS		(gfp_mask & __GFP_FS)
-#define CAN_DO_IO		(gfp_mask & __GFP_IO)
 int page_launder(int gfp_mask, int sync)
 {
-	int launder_loop, maxscan, cleaned_pages, maxlaunder;
+	int maxscan, cleaned_pages;
 	struct list_head * page_lru;
 	struct page * page;
 
-	launder_loop = 0;
-	maxlaunder = 0;
 	cleaned_pages = 0;
 
-dirty_page_rescan:
+	/* Will we wait on IO? */
+	if (!sync)
+		gfp_mask &= ~__GFP_WAIT;
+
 	spin_lock(&pagemap_lru_lock);
 	maxscan = nr_inactive_dirty_pages >> DEF_PRIORITY;
 	while ((page_lru = inactive_dirty_list.prev) != &inactive_dirty_list &&
@@ -545,8 +544,8 @@
 			if (!writepage)
 				goto page_active;
 
-			/* First time through? Move it to the back of the list */
-			if (!launder_loop || !CAN_DO_FS) {
+			/* Can't do it? Move it to the back of the list */
+			if (!CAN_DO_FS) {
 				list_del(page_lru);
 				list_add(page_lru, &inactive_dirty_list);
 				UnlockPage(page);
@@ -576,9 +575,9 @@
 		 * buffer pages
 		 */
 		if (page->buffers) {
-			unsigned int buffer_mask;
 			int clearedbuf;
 			int freed_page = 0;
+
 			/*
 			 * Since we might be doing disk IO, we have to
 			 * drop the spinlock and take an extra reference
@@ -588,16 +587,8 @@
 			page_cache_get(page);
 			spin_unlock(&pagemap_lru_lock);
 
-			/* Will we do (asynchronous) IO? */
-			if (launder_loop && maxlaunder == 0 && sync)
-				buffer_mask = gfp_mask;				/* Do as much as we can */
-			else if (launder_loop && maxlaunder-- > 0)
-				buffer_mask = gfp_mask & ~__GFP_WAIT;			/* Don't wait, async write-out */
-			else
-				buffer_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO);	/* Don't even start IO */
-
 			/* Try to free the page buffers. */
-			clearedbuf = try_to_free_buffers(page, buffer_mask);
+			clearedbuf = try_to_free_buffers(page, gfp_mask);
 
 			/*
 			 * Re-take the spinlock. Note that we cannot
@@ -660,29 +651,6 @@
 	}
 	spin_unlock(&pagemap_lru_lock);
 
-	/*
-	 * If we don't have enough free pages, we loop back once
-	 * to queue the dirty pages for writeout. When we were called
-	 * by a user process (that /needs/ a free page) and we didn't
-	 * free anything yet, we wait synchronously on the writeout of
-	 * MAX_SYNC_LAUNDER pages.
-	 *
-	 * We also wake up bdflush, since bdflush should, under most
-	 * loads, flush out the dirty pages before we have to wait on
-	 * IO.
-	 */
-	if (CAN_DO_IO && !launder_loop && free_shortage()) {
-		launder_loop = 1;
-		/* If we cleaned pages, never do synchronous IO. */
-		if (cleaned_pages)
-			sync = 0;
-		/* We only do a few "out of order" flushes. */
-		maxlaunder = MAX_LAUNDER;
-		/* Kflushd takes care of the rest. */
-		wakeup_bdflush();
-		goto dirty_page_rescan;
-	}
-
 	/* Return the number of pages moved to the inactive_clean list. */
 	return cleaned_pages;
 }
@@ -886,6 +854,13 @@
 	int ret = 0;
 
 	/*
+	 * If needed, we move pages from the active list
+	 * to the inactive list.
+	 */
+	if (inactive_shortage()) 
+		ret += refill_inactive(gfp_mask);
+
+	/*
 	 * If we're low on free pages, move pages from the
 	 * inactive_dirty list to the inactive_clean list.
 	 *
@@ -893,19 +868,11 @@
 	 * before we get around to moving them to the other
 	 * list, so this is a relatively cheap operation.
 	 */
-
 	ret += page_launder(gfp_mask, user);
 
 	ret += shrink_dcache_memory(DEF_PRIORITY, gfp_mask);
 	ret += shrink_icache_memory(DEF_PRIORITY, gfp_mask);
 
-	/*
-	 * If needed, we move pages from the active list
-	 * to the inactive list.
-	 */
-	if (inactive_shortage()) 
-		ret += refill_inactive(gfp_mask);
-
 	/* 	
 	 * Reclaim unused slab cache if memory is low.
 	 */
@@ -973,8 +940,6 @@
 			refill_inactive_scan(DEF_PRIORITY);
 		}
 
-		run_task_queue(&tq_disk);
-
 		/* 
 		 * We go to sleep if either the free page shortage
 		 * or the inactive page shortage is gone. We do this
@@ -987,6 +952,7 @@
 		 * we'll be woken up earlier...
 		 */
 		if (!free_shortage() || !inactive_shortage()) {
+			run_task_queue(&tq_disk);
 			interruptible_sleep_on_timeout(&kswapd_wait, HZ);
 		/*
 		 * If we couldn't free enough memory, we see if it was
