diff -u --recursive --new-file v2.1.92/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.92/linux/Documentation/Configure.help	Wed Apr  1 20:11:46 1998
+++ linux/Documentation/Configure.help	Sat Apr  4 09:45:13 1998
@@ -974,8 +974,7 @@
   that implements the TGA interface (much like the VGA standard, but
   older TGA adapters are *not* VGA compatible).  On such systems, you
   should say Y here so that the TGA driver rather than the standard
-  VGA driver is used.  Note that, at this time, there is no X server
-  for these systems. If unsure, try N.
+  VGA driver is used.
 
 PCI support
 CONFIG_PCI
@@ -1019,9 +1018,13 @@
 
 Backward-compatible /proc/pci
 CONFIG_PCI_OLD_PROC
-  If you say Y here and to the "/proc filesystem support" below, you
-  will get a directory /proc/pci with information about your PCI
-  hardware. If unsure, say Y.
+  Older kernels supported a /proc/pci file containing brief textual
+  description of all PCI devices in the system. Several programs tried
+  to parse this file, so it became almost impossible to add new
+  fields without breaking compatibility. So a new /proc interface to
+  PCI (/proc/bus/pci) has been implemented and the old one is supported
+  for compatibility reasons only (you can disable it here, gaining
+  some memory).  If unsure, say Y.
 
 MCA support
 CONFIG_MCA
@@ -5343,7 +5346,7 @@
   M here and read Documentation/modules.txt. If you don't know whether
   you need it, then you don't need it: say N.
 
-Kernel automounter support (experimental)
+Kernel automounter support
 CONFIG_AUTOFS_FS
   The automounter is a tool to automatically mount remote filesystems
   on demand.  This implementation is partially kernel-based to reduce
@@ -5421,6 +5424,13 @@
   inserted in and removed from the running kernel whenever you want).
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt.
+
+/dev/pts filesystem
+CONFIG_DEVPTS_FS
+  A filesystem which when mounted on /dev/pts and used in conjunction
+  with the /dev/ptmx multiplexing pty device, should allow full
+  support for Unix98 pty's without requiring setuid or daemons.  glibc
+  2.1 contains the requisite support for this mode of operation.
 
 Macintosh partition map support
 CONFIG_MAC_PARTITION
diff -u --recursive --new-file v2.1.92/linux/Documentation/networking/ip_dynaddr.txt linux/Documentation/networking/ip_dynaddr.txt
--- v2.1.92/linux/Documentation/networking/ip_dynaddr.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/ip_dynaddr.txt	Fri Apr  3 17:48:11 1998
@@ -0,0 +1,29 @@
+IP dynamic address hack-port v0.03
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This stuff allows diald ONESHOT connections to get established by
+dynamically changing packet source address (and socket's if local procs).
+It is implemented for TCP diald-box connections(1) and IP_MASQuerading(2).
+
+If enabled[*] and forwarding interface has changed:
+  1)  Socket (and packet) source address is rewritten ON RETRANSMISSIONS
+      while in SYN_SENT state (diald-box processes).
+  2)  Out-bounded MASQueraded source address changes ON OUTPUT (when
+      internal host does retransmission) until a packet from outside is
+      received by the tunnel.
+
+This is specially helpful for auto dialup links (diald), where the
+``actual'' outgoing address is unknown at the moment the link is
+going up. So, the *same* (local AND masqueraded) connections requests that
+bring the link up will be able to get established.
+
+[*] At boot, by default no address rewriting is attempted. 
+  To enable:
+     # echo 1 > /proc/sys/net/ipv4/ip_dynaddr
+  To enable verbose mode:
+     # echo 2 > /proc/sys/net/ipv4/ip_dynaddr
+  To disable (default)
+     # echo 0 > /proc/sys/net/ipv4/ip_dynaddr
+
+Enjoy!
+
+-- Juanjo  <jjciarla@raiz.uncu.edu.ar>
diff -u --recursive --new-file v2.1.92/linux/Documentation/networking/ppp.txt linux/Documentation/networking/ppp.txt
--- v2.1.92/linux/Documentation/networking/ppp.txt	Sun Nov 30 12:23:16 1997
+++ linux/Documentation/networking/ppp.txt	Fri Apr  3 17:48:11 1998
@@ -1,11 +1,7 @@
 *NEWSFLASH*
 This kernel release needs a minor bug fix for pppd to run properly with
 the new routing code.  When your pppd doesn't work apply the following 
-patch to pppd-2.2.0f or install updated RPMs.
-
-Updated RPMs for libc5 machines (build on RedHat 4.0):
-ftp://ftp.firstfloor.org/pub/ak/ppp-2.2.0f-4.src.rpm
-ftp://ftp.firstfloor.org/pub/ak/ppp-2.2.0f-4.i386.rpm
+patch to pppd-2.2.0f or update to the newest pppd version.
 
 Patch:
 
diff -u --recursive --new-file v2.1.92/linux/Documentation/networking/routing.txt linux/Documentation/networking/routing.txt
--- v2.1.92/linux/Documentation/networking/routing.txt	Thu Dec 19 00:31:52 1996
+++ linux/Documentation/networking/routing.txt	Mon Apr  6 11:38:56 1998
@@ -35,10 +35,10 @@
 
 NEWS for hacker.
 
-- New destination cache. Flexible, robust and just beatiful.
+- New destination cache. Flexible, robust and just beautiful.
 - Network stack is reordered, simplified, optimized, a lot of bugs fixed.
-  (well, and new bugs are intoduced, but I've yet not seen them 8))
-  It is difficult to descibe all the changes, look into source.
+  (well, and new bugs are introduced, but I haven't seen them yet 8))
+  It is difficult to describe all the changes, look into source.
 
 If you see this file, then this patch works 8)
 
diff -u --recursive --new-file v2.1.92/linux/Documentation/pci.txt linux/Documentation/pci.txt
--- v2.1.92/linux/Documentation/pci.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/pci.txt	Thu Apr  2 09:12:22 1998
@@ -0,0 +1,60 @@
+		       Few Notes About The PCI Subsystem
+
+				       or
+
+		"What should you avoid when writing PCI drivers"
+
+	  by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on 13-Feb-1998
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. How to find PCI devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+   In case your driver wants to search for all devices with given vendor/device
+ID, it should use:
+
+		struct pci_dev *dev = NULL;
+		while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
+			configure_device(dev);
+
+   For class-based search, use pci_find_class(CLASS_ID, dev).
+
+   In case you want to do some complex matching, look at pci_devices -- it's
+a linked list of pci_dev structures for all PCI devices in the system.
+
+   All these methods return pointer to a pci_dev structure which is used as a
+parameter for many other PCI functions. The rest of them accept bus and
+device/function numbers which can be found in pci_dev->bus->number and
+pci_dev->devfn. Feel free to use all other fields of the pci_dev structure, but
+don't modify them.
+
+   The pci_present() function can be used to test presence of PCI in the
+machine.
+
+2. How to access PCI config space
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   You can use pci_(read|write)_config_(byte|word|dword) to access the config
+space of device represented by pci_dev. All these functions return 0 when
+successfull or an error code (PCIBIOS_...) which can be translated to text
+string by pcibios_strerror. Most drivers expect that accesses to valid PCI
+devices don't fail.
+
+   In case you want to address the devices by bus/device/function numbers,
+use pcibios_(read_write)_config_(byte|word|dword).
+
+   If you access fields in the standard portion of the config header, please
+use symbolic names of locations and bits declared in <linux/pci.h>.
+
+3. Addresses and interrupts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   Memory and port addresses and interrupt numbers should NOT be read from the
+config space. You should use the values in the pci_dev structure as they might
+have been remapped by the kernel.
+
+4. Obsolete functions
+~~~~~~~~~~~~~~~~~~~~~
+
+<linux/bios32.h> is obsolete and should not be included in new code.
+
+pcibios_find_(device|class) are also obsolete and should be replaced by
+pci_find_(device|class).
diff -u --recursive --new-file v2.1.92/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt
--- v2.1.92/linux/Documentation/sysrq.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sysrq.txt	Fri Apr  3 17:50:32 1998
@@ -0,0 +1,89 @@
+                      MAGIC SYSRQ KEY DOCUMENTATION v1.0
+                     ------------------------------------
+                        [Fri Apr  3 08:27:12 EST 1998]
+
+1. What is the magic SysRQ key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+It is a 'magical' key combo you can hit, and the kernel will respond to
+regardless of anything else, unless it is hard-locked.
+
+2. How do I enable the magic SysRQ key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
+configuring the kernel. This option is only available it 2.1.x or later
+kernels.
+
+3. How do I use the magic SysRQ key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You press the key combo 'ALT-SysRQ-<command key>'.
+
+4. What are the 'command' keys?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+'r'     - Turns off keyboard raw mode and sets it to XLATE.
+
+'k'     - Kills all programs on the current virtual console.
+
+'b'     - Will immediately reboot the system without syncing or unmounting
+          your disks.
+
+'o'     - Will shut your system off via APM (if configured and supported).
+
+'s'     - Will attempt to sync all mounted filesystems.
+
+'u'     - Will attempt to remount all mounted file systems readonly.
+
+'p'     - Will dump the current registers and flags to your console.
+
+'t'     - Will dump a list of current tasks and their information to your
+          console.
+
+'m'     - Will dump current memory info to your console.
+
+'0'-'8' - Sets the console log level, controlling which kernel messages
+          will be printed to your console. ('0', for example would make
+          it so that only emergency messages like PANICs or OOPSes would
+          make it to your console.)
+
+'e'     - Send a SIGTERM to all processes, except for init.
+
+'i'     - Send a SIGKILL to all processes, except for init.
+
+'l'     - Send a SIGKILL to all processes, INCLUDING init. (Your system
+          will be non-functional after this.)
+
+5. Okay, so what can I use them for?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Well, un'R'aw is very handy when your X server or a svgalib program crashes.
+
+sa'K' (system attention key) is useful when you want to exit a program
+that will not let you switch consoles. (For example, X or a svgalib program.)
+
+re'B'oot is good when you're unable to shut down. But you should also 'S'ync
+and 'U'mount first.
+
+'S'ync is great when your system is locked up, it allows you to sync your
+disks and will certainly lessen the chance of data loss and fscking.
+
+'U'mount is basically useful in the same ways as 'S'ync. I generally 'S'ync,
+'U'mount, then re'B'oot when my system locks. It's saved me many a fsck.
+
+The loglevel'0'-'8' is useful when your console is being flooded with
+kernel messages you do not want to see. Setting '0' will prevent all but
+the most urgent kernel messages from reaching your console. (They will
+still be logged if syslogd/klogd are alive, though.)
+
+t'E'rm and k'I'll are useful if you have some sort of runaway process you
+are unable to kill any other way, especially if it's spawning other
+processes.
+
+6. Sometimes SysRQ seems to get 'stuck' after using it, what can I do?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+That happens to me, also. I've found that tapping shift, alt, and control
+on both sides of the keyboard, and hitting an invalid sysrq sequence again
+will fix the problem. (ie, something like alt-sysrq-z).
+
+7. I have more questions, who can I ask?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You may feel free to send email to myrdraal@deathsdoor.com, and I will
+respond as soon as possible.
+ -Myrdraal
diff -u --recursive --new-file v2.1.92/linux/Makefile linux/Makefile
--- v2.1.92/linux/Makefile	Wed Apr  1 20:11:47 1998
+++ linux/Makefile	Thu Apr  2 21:23:00 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 92
+SUBLEVEL = 93
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.1.92/linux/arch/alpha/kernel/bios32.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/bios32.c	Thu Apr  2 09:12:22 1998
@@ -56,7 +56,6 @@
 
 #else /* CONFIG_PCI */
 
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
@@ -555,55 +554,6 @@
 #endif /* !PCI_MODIFY */
 
 
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.  
- */
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-			 unsigned short index, unsigned char *bus,
-			 unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if (dev->vendor == vendor && dev->device == device_id) {
-			if (curr == index) {
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-			unsigned char *bus, unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if (dev->class == class_code) {
-			if (curr == index) {
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-
 int pcibios_present(void)
 {
 	return 1;
@@ -2247,6 +2197,11 @@
 	return 0;
 }
 #endif /* CONFIG_ALPHA_MIATA */
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	return str;
+}
 
 #ifdef CONFIG_ALPHA_SRM_SETUP
 void reset_for_srm(void)
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/cia.c linux/arch/alpha/kernel/cia.c
--- v2.1.92/linux/arch/alpha/kernel/cia.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/cia.c	Thu Apr  2 09:12:22 1998
@@ -8,7 +8,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c
--- v2.1.92/linux/arch/alpha/kernel/lca.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/lca.c	Thu Apr  2 09:12:22 1998
@@ -8,7 +8,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 
 #include <asm/ptrace.h>
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/mcpcia.c linux/arch/alpha/kernel/mcpcia.c
--- v2.1.92/linux/arch/alpha/kernel/mcpcia.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/mcpcia.c	Thu Apr  2 09:12:22 1998
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/pyxis.c linux/arch/alpha/kernel/pyxis.c
--- v2.1.92/linux/arch/alpha/kernel/pyxis.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/pyxis.c	Thu Apr  2 09:12:22 1998
@@ -7,7 +7,6 @@
 #include <linux/config.h> /* CONFIG_ALPHA_RUFFIAN. */
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/smc37c669.c linux/arch/alpha/kernel/smc37c669.c
--- v2.1.92/linux/arch/alpha/kernel/smc37c669.c	Tue Mar 10 10:03:30 1998
+++ linux/arch/alpha/kernel/smc37c669.c	Thu Apr  2 09:12:22 1998
@@ -3,8 +3,6 @@
  */
 #include <linux/kernel.h>
 
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/smc37c93x.c linux/arch/alpha/kernel/smc37c93x.c
--- v2.1.92/linux/arch/alpha/kernel/smc37c93x.c	Tue Mar 10 10:03:30 1998
+++ linux/arch/alpha/kernel/smc37c93x.c	Thu Apr  2 09:12:22 1998
@@ -5,8 +5,6 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/t2.c linux/arch/alpha/kernel/t2.c
--- v2.1.92/linux/arch/alpha/kernel/t2.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/t2.c	Thu Apr  2 09:12:22 1998
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
diff -u --recursive --new-file v2.1.92/linux/arch/alpha/kernel/tsunami.c linux/arch/alpha/kernel/tsunami.c
--- v2.1.92/linux/arch/alpha/kernel/tsunami.c	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/kernel/tsunami.c	Thu Apr  2 09:12:22 1998
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 
diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.1.92/linux/arch/i386/kernel/bios32.c	Wed Feb  4 11:36:00 1998
+++ linux/arch/i386/kernel/bios32.c	Mon Apr  6 13:58:39 1998
@@ -1,7 +1,7 @@
 /*
- * bios32.c - BIOS32, PCI BIOS functions.
+ * bios32.c - Low-Level PCI Access
  *
- * $Id: bios32.c,v 1.17 1997/11/16 11:03:41 mj Exp $
+ * $Id: bios32.c,v 1.26 1998/02/18 15:21:09 mj Exp $
  *
  * Sponsored by
  *	iX Multiuser Multitasking Magazine
@@ -64,12 +64,13 @@
  *
  * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
  *	and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * Feb 6,  1998 : No longer using BIOS to find devices and device classes. [mj]
  */
 
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 
@@ -91,8 +92,6 @@
 
 struct pci_access {
     int pci_present;
-    int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
-    int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
     int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
     int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
     int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
@@ -108,8 +107,6 @@
 
 static struct pci_access pci_access_none = {
 	0,		   		/* No PCI present */
-	(void *) pci_stub,	        /* No functions implemented */
-	(void *) pci_stub,
 	(void *) pci_stub,
 	(void *) pci_stub,
 	(void *) pci_stub,
@@ -125,18 +122,6 @@
 	return access_pci->pci_present;
 }
 
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-	unsigned char *bus, unsigned char *device_fn)
-{
-	return access_pci->find_class(class_code, index, bus, device_fn);
-}
-
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-	unsigned short index, unsigned char *bus, unsigned char *device_fn)
-{
-	return access_pci->find_device(vendor, device_id, index, bus, device_fn);
-}
-
 int pcibios_read_config_byte (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned char *value)
 {
@@ -147,6 +132,9 @@
 #ifdef __SMP__
 /*
  * IOAPICs can take PCI IRQs directly, lets first check the mptable:
+ *
+ * This can go away once nobody probes the irq this way,
+ * but uses the PCI tables instead.
  */
 	if (where == PCI_INTERRUPT_LINE) {
 		int irq;
@@ -205,60 +193,17 @@
 	return access_pci->write_config_dword(bus, device_fn, where, value);
 }
 
-/*
- * Direct access to PCI hardware...
- */
+static unsigned int pci_probe = ~0;
 
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.  
- */
-
-#ifdef CONFIG_PCI_DIRECT
-
-static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
-			   unsigned short index, unsigned char *bus,
-			   unsigned char *devfn)
-{
-    unsigned int curr = 0;
-    struct pci_dev *dev;
-
-    for (dev = pci_devices; dev; dev = dev->next) {
-	if (dev->vendor == vendor && dev->device == device_id) {
-	    if (curr == index) {
-		*devfn = dev->devfn;
-		*bus = dev->bus->number;
-		return PCIBIOS_SUCCESSFUL;
-	    }
-	    ++curr;
-	}
-    }
-    return PCIBIOS_DEVICE_NOT_FOUND;
-}
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
 
 /*
- * Given the class, find the n'th instance of that device
- * in the system.
+ * Direct access to PCI hardware...
  */
 
-static int pci_direct_find_class (unsigned int class_code, unsigned short index,
-			  unsigned char *bus, unsigned char *devfn)
-{
-    unsigned int curr = 0;
-    struct pci_dev *dev;
-
-    for (dev = pci_devices; dev; dev = dev->next) {
-	if (dev->class == class_code) {
-	    if (curr == index) {
-		*devfn = dev->devfn;
-		*bus = dev->bus->number;
-		return PCIBIOS_SUCCESSFUL;
-	    }
-	    ++curr;
-	}
-    }
-    return PCIBIOS_DEVICE_NOT_FOUND;
-}
+#ifdef CONFIG_PCI_DIRECT
 
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
@@ -346,8 +291,6 @@
 
 static struct pci_access pci_direct_conf1 = {
       1,
-      pci_direct_find_device,
-      pci_direct_find_class,
       pci_conf1_read_config_byte,
       pci_conf1_read_config_word,
       pci_conf1_read_config_dword,
@@ -458,8 +401,6 @@
 
 static struct pci_access pci_direct_conf2 = {
       1,
-      pci_direct_find_device,
-      pci_direct_find_class,
       pci_conf2_read_config_byte,
       pci_conf2_read_config_word,
       pci_conf2_read_config_dword,
@@ -470,39 +411,43 @@
 
 __initfunc(static struct pci_access *pci_check_direct(void))
 {
-    unsigned int tmp;
-    unsigned long flags;
+	unsigned int tmp;
+	unsigned long flags;
 
-    save_flags(flags); cli();
+	save_flags(flags); cli();
+
+	/*
+	 * Check if configuration type 1 works.
+	 */
+	if (pci_probe & PCI_PROBE_CONF1) {
+		outb (0x01, 0xCFB);
+		tmp = inl (0xCF8);
+		outl (0x80000000, 0xCF8);
+		if (inl (0xCF8) == 0x80000000) {
+			outl (tmp, 0xCF8);
+			restore_flags(flags);
+			printk("PCI: Using configuration type 1\n");
+			return &pci_direct_conf1;
+		}
+		outl (tmp, 0xCF8);
+	}
+
+	/*
+	 * Check if configuration type 2 works.
+	 */
+	if (pci_probe & PCI_PROBE_CONF2) {
+		outb (0x00, 0xCFB);
+		outb (0x00, 0xCF8);
+		outb (0x00, 0xCFA);
+		if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
+			restore_flags(flags);
+			printk("PCI: Using configuration type 2\n");
+			return &pci_direct_conf2;
+		}
+	}
 
-    /*
-     * Check if configuration type 1 works.
-     */
-    outb (0x01, 0xCFB);
-    tmp = inl (0xCF8);
-    outl (0x80000000, 0xCF8);
-    if (inl (0xCF8) == 0x80000000) {
-	outl (tmp, 0xCF8);
-	restore_flags(flags);
-	printk("PCI: Using configuration type 1\n");
-	return &pci_direct_conf1;
-    }
-    outl (tmp, 0xCF8);
-
-    /*
-     * Check if configuration type 2 works.
-     */
-    outb (0x00, 0xCFB);
-    outb (0x00, 0xCF8);
-    outb (0x00, 0xCFA);
-    if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
 	restore_flags(flags);
-	printk("PCI: Using configuration type 2\n");
-	return &pci_direct_conf2;
-    }
-    restore_flags(flags);
-    printk("PCI: PCI hardware not found (i.e., not present or not supported).\n");
-    return NULL;
+	return NULL;
 }
 
 #endif
@@ -599,7 +544,7 @@
 			printk("bios32_service(0x%lx): not present\n", service);
 			return 0;
 		default: /* Shouldn't happen */
-			printk("bios32_service(0x%lx): returned 0x%x, mail drew@colorado.edu\n",
+			printk("bios32_service(0x%lx): returned 0x%x, report to <mj@ucw.cz>.\n",
 				service, return_code);
 			return 0;
 	}
@@ -642,7 +587,7 @@
 		if (present_status || (signature != PCI_SIGNATURE)) {
 			printk ("PCI: %s: BIOS32 Service Directory says PCI BIOS is present,\n"
 				"	but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
-				"	and signature of 0x%08lx (%c%c%c%c).  Mail drew@Colorado.EDU\n",
+				"	and signature of 0x%08lx (%c%c%c%c).  Report to <mj@ucw.cz>.\n",
 				(signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
 				present_status, signature,
 				(char) (signature >>  0), (char) (signature >>  8),
@@ -660,6 +605,8 @@
 	return 0;
 }
 
+#if 0	/* Not used */
+
 static int pci_bios_find_class (unsigned int class_code, unsigned short index,
 	unsigned char *bus, unsigned char *device_fn)
 {
@@ -709,6 +656,8 @@
 	return (int) (ret & 0xff00) >> 8;
 }
 
+#endif
+
 static int pci_bios_read_config_byte(unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned char *value)
 {
@@ -847,8 +796,6 @@
 
 static struct pci_access pci_bios_access = {
       1,
-      pci_bios_find_device,
-      pci_bios_find_class,
       pci_bios_read_config_byte,
       pci_bios_read_config_word,
       pci_bios_read_config_dword,
@@ -887,18 +834,14 @@
 		if (sum != 0)
 			continue;
 		if (check->fields.revision != 0) {
-			printk("PCI: unsupported BIOS32 revision %d at 0x%p, mail drew@colorado.edu\n",
+			printk("PCI: unsupported BIOS32 revision %d at 0x%p, report to <mj@ucw.cz>\n",
 				check->fields.revision, check);
 			continue;
 		}
 		printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
 		if (check->fields.entry >= 0x100000) {
-#ifdef CONFIG_PCI_DIRECT
-			printk("PCI: BIOS32 entry in high memory, trying direct PCI access.\n");
-			return pci_check_direct();
-#else
 			printk("PCI: BIOS32 entry in high memory, cannot use.\n");
-#endif
+			return NULL;
 		} else {
 			bios32_entry = check->fields.entry;
 			printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
@@ -909,39 +852,128 @@
 		break;	/* Hopefully more than one BIOS32 cannot happen... */
 	}
 
+	/*
+	 * If we were told to use the PCI BIOS and it's not present, avoid
+	 * touching the hardware.
+	 */
+	pci_probe = 0;
 	return NULL;
 }
 
 #endif
 
 /*
- * No fixup function used.
+ * Arch-dependent fixups.
  */
 
-__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
+__initfunc(void pcibios_fixup(void))
 {
-    return mem_start;
+	struct pci_dev *dev;
+	int i, has_io;
+
+	for(dev = pci_devices; dev; dev=dev->next) {
+		/*
+		 * There are probably some buggy BIOSes that forget to assign I/O port
+		 * addresses to several devices. We probably should assign new addresses
+		 * to such devices, but we need to gather some information first. [mj]
+		 */
+		has_io = 0;
+		for(i=0; i<6; i++) {
+			unsigned long a = dev->base_address[i];
+			if (a & PCI_BASE_ADDRESS_SPACE_IO) {
+				has_io = 1;
+				a &= PCI_BASE_ADDRESS_IO_MASK;
+				if (!a || a == PCI_BASE_ADDRESS_IO_MASK)
+					printk(KERN_WARNING "PCI: BIOS forgot to assign address #%d to device %02x:%02x,"
+						" please report to <mj@ucw.cz>\n", i, dev->bus->number, dev->devfn);
+			}
+		}
+		/*
+		 * Check if the I/O space access is allowed. If not, moan loudly. [mj]
+		 */
+		if (has_io) {
+			unsigned short cmd;
+			pci_read_config_word(dev, PCI_COMMAND, &cmd);
+			if (!(cmd & PCI_COMMAND_IO))
+				printk(KERN_WARNING "PCI: BIOS forgot to enable I/O for device %02x:%02x,"
+					" please report to <mj@ucw.cz>\n", dev->bus->number, dev->devfn);
+		}
+#ifdef __SMP__
+		/*
+		 * Recalculate IRQ numbers if we use the I/O APIC
+		 */
+		{
+		unsigned char pin;
+		int irq;
+
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (pin) {
+			pin--;		/* interrupt pins are numbered starting from 1 */
+			irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin);
+			if (irq >= 0) {
+				printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
+					dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+				dev->irq = irq;
+				}
+		}
+		}
+#endif
+		/*
+		 * Fix out-of-range IRQ numbers.
+		 */
+		if (dev->irq >= NR_IRQS)
+			dev->irq = 0;
+	}
 }
 
 /*
  * Initialization. Try all known PCI access methods.
  */
 
-__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void pcibios_init(void))
 {
 	struct pci_access *a = NULL;
 
 #ifdef CONFIG_PCI_BIOS
-	a = pci_find_bios();
-#else
-#ifdef CONFIG_PCI_DIRECT
-	a = pci_check_direct();
-#else
-#error "You need to set CONFIG_PCI_BIOS or CONFIG_PCI_DIRECT if you want PCI support."
+	if (pci_probe & PCI_PROBE_BIOS)
+		a = pci_find_bios();
 #endif
+#ifdef CONFIG_PCI_DIRECT
+	if (!a && (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)))
+		a = pci_check_direct();
 #endif
 	if (a)
 		access_pci = a;
+}
 
-	return memory_start;
+#if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT)
+#error PCI configured with neither PCI BIOS or PCI direct access support.
+#endif
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	if (!strncmp(str, "off", 3)) {
+		pci_probe = 0;
+		return str+3;
+	}
+#ifdef CONFIG_PCI_BIOS
+	else if (!strncmp(str, "bios", 4)) {
+		pci_probe = PCI_PROBE_BIOS;
+		return str+4;
+	} else if (!strncmp(str, "nobios", 6)) {
+		pci_probe &= ~PCI_PROBE_BIOS;
+		return str+6;
+	}
+#endif
+#ifdef CONFIG_PCI_DIRECT
+	else if (!strncmp(str, "conf1", 5)) {
+		pci_probe = PCI_PROBE_CONF1;
+		return str+5;
+	}
+	else if (!strncmp(str, "conf2", 5)) {
+		pci_probe = PCI_PROBE_CONF2;
+		return str+5;
+	}
+#endif
+	return str;
 }
diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.1.92/linux/arch/i386/kernel/i386_ksyms.c	Tue Mar 17 22:18:13 1998
+++ linux/arch/i386/kernel/i386_ksyms.c	Sun Apr  5 12:08:41 1998
@@ -8,7 +8,6 @@
 #include <linux/in6.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
-#include <linux/pci.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -64,13 +63,14 @@
 EXPORT_SYMBOL(strlen_user);
 
 #ifdef __SMP__
-EXPORT_SYMBOL(apic_reg);	/* Needed internally for the I386 inlines */
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL_NOVERS(kernel_flag);
 EXPORT_SYMBOL_NOVERS(active_kernel_processor);
 EXPORT_SYMBOL(smp_invalidate_needed);
 EXPORT_SYMBOL_NOVERS(__lock_kernel);
 EXPORT_SYMBOL(lk_lockmsg);
+EXPORT_SYMBOL(__cpu_logical_map);
+EXPORT_SYMBOL(smp_num_cpus);
 
 /* Global SMP irq stuff */
 EXPORT_SYMBOL(synchronize_irq);
@@ -96,8 +96,4 @@
 EXPORT_SYMBOL(mca_set_adapter_procfn);
 EXPORT_SYMBOL(mca_isenabled);
 EXPORT_SYMBOL(mca_isadapter);
-#endif
-
-#if CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
 #endif
diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.1.92/linux/arch/i386/kernel/io_apic.c	Tue Mar 17 22:18:13 1998
+++ linux/arch/i386/kernel/io_apic.c	Mon Apr  6 14:03:45 1998
@@ -28,13 +28,11 @@
 
 #include "irq.h"
 
-#define IO_APIC_BASE 0xfec00000
-
 /*
  * volatile is justified in this case, it might change
  * spontaneously, GCC should not cache it
  */
-volatile unsigned int * io_apic_reg = NULL;
+#define IO_APIC_BASE ((volatile int *)0xfec00000)
 
 /*
  * The structure of the IO-APIC:
@@ -96,17 +94,19 @@
 int mp_irq_entries = 0;				/* # of MP IRQ source entries */
 struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
 						/* MP IRQ source entries */
+int mpc_default_type = 0;			/* non-0 if default (table-less)
+						   MP configuration */
 
 unsigned int io_apic_read (unsigned int reg)
 {
-	*io_apic_reg = reg;
-	return *(io_apic_reg+4);
+	*IO_APIC_BASE = reg;
+	return *(IO_APIC_BASE+4);
 }
 
 void io_apic_write (unsigned int reg, unsigned int value)
 {
-	*io_apic_reg = reg;
-	*(io_apic_reg+4) = value;
+	*IO_APIC_BASE = reg;
+	*(IO_APIC_BASE+4) = value;
 }
 
 void enable_IO_APIC_irq (unsigned int irq)
@@ -256,7 +256,7 @@
 		/*
 		 * PCI IRQ redirection. Yes, limits are hardcoded.
 		 */
-		if ((i>=16) && (i<=19)) {
+		if ((i>=16) && (i<=23)) {
 			if (pirq_entries[i-16] != -1) {
 				if (!pirq_entries[i-16]) {
 					printk("disabling PIRQ%d\n", i-16);
@@ -516,16 +516,16 @@
 static void init_sym_mode (void)
 {
 	printk("enabling Symmetric IO mode ... ");
-		outb (0x70, 0x22);
-		outb (0x01, 0x23);
+		outb_p (0x70, 0x22);
+		outb_p (0x01, 0x23);
 	printk("...done.\n");
 }
 
 void init_pic_mode (void)
 {
 	printk("disabling Symmetric IO mode ... ");
-		outb (0x70, 0x22);
-		outb (0x00, 0x23);
+		outb_p (0x70, 0x22);
+		outb_p (0x00, 0x23);
 	printk("...done.\n");
 }
 
@@ -579,17 +579,85 @@
 	return in_ioapic_list(ioapic_blacklist);
 }
 
+static void setup_ioapic_id (void)
+{
+	struct IO_APIC_reg_00 reg_00;
 
-void setup_IO_APIC (void)
+	/*
+	 * 'default' mptable configurations mean a hardwired setup,
+	 * 2 CPUs, 16 APIC registers. IO-APIC ID is usually set to 0,
+	 * setting it to ID 2 should be fine.
+	 */
+
+	/*
+	 * Sanity check, is ID 2 really free? Every APIC in the
+	 * system must have a unique ID or we get lots of nice
+	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+	 */
+	if (cpu_present_map & (1<<0x2))
+		panic("APIC ID 2 already used");
+
+	/*
+	 * set the ID
+	 */
+	*(int *)&reg_00 = io_apic_read(0);
+	printk("... changing IO-APIC physical APIC ID to 2 ...\n");
+	reg_00.ID = 0x2;
+	io_apic_write(0, *(int *)&reg_00);
+
+	/*
+	 * Sanity check
+	 */
+	*(int *)&reg_00 = io_apic_read(0);
+	if (reg_00.ID != 0x2)
+		panic("could not set ID");
+}
+
+static void construct_default_ISA_mptable (void)
 {
-	int i;
+	int i, pos=0;
+
+	for (i=0; i<16; i++) {
+		if (!IO_APIC_IRQ(i))
+			continue;
+
+		mp_irqs[pos].mpc_irqtype = 0;
+		mp_irqs[pos].mpc_irqflag = 0;
+		mp_irqs[pos].mpc_srcbus = 0;
+		mp_irqs[pos].mpc_srcbusirq = i;
+		mp_irqs[pos].mpc_dstapic = 0;
+		mp_irqs[pos].mpc_dstirq = i;
+		pos++;
+	}
+	mp_irq_entries = pos;
+	mp_bus_id_to_type[0] = MP_BUS_ISA;
+
 	/*
-	 *      Map the IO APIC into kernel space
+	 * MP specification 1.4 defines some extra rules for default
+	 * configurations, fix them up here:
 	 */
+	
+	switch (mpc_default_type)
+	{
+		case 2:
+			break;
+		default:
+		/*
+		 * pin 2 is IRQ0:
+		 */
+			mp_irqs[0].mpc_dstirq = 2;
+	}
 
-	printk("mapping IO APIC from standard address.\n");
-	io_apic_reg = ioremap_nocache(IO_APIC_BASE,4096);
-	printk("new virtual address: %p.\n",io_apic_reg);
+	setup_ioapic_id();
+}
+			
+void setup_IO_APIC (void)
+{
+	int i;
+
+	if (!pirqs_enabled)
+		for (i=0; i<MAX_PIRQS; i++)
+			pirq_entries[i]=-1;
 
 	init_sym_mode();
 	{
@@ -605,12 +673,6 @@
 	for (i=0; i<nr_ioapic_registers; i++)
 		clear_IO_APIC_irq (i);
 
-#if DEBUG_1
-	for (i=0; i<16; i++)
-		if (IO_APIC_IRQ(i))
-			setup_IO_APIC_irq_ISA_default (i);
-#endif
-
 	/*
 	 * the following IO-APIC's can be enabled:
 	 *
@@ -634,7 +696,18 @@
 		io_apic_irqs = 0;
 	}
 
+	/*
+	 * If there are no explicit mp irq entries: it's either one of the
+	 * default configuration types or we are broken. In both cases it's
+	 * fine to set up most of the low 16 IOAPIC pins to ISA defaults.
+	 */
+	if (!mp_irq_entries) {
+		printk("no explicit IRQ entries, using default mptable\n");
+		construct_default_ISA_mptable();
+	}
+
 	init_IO_APIC_traps();
+
 	setup_IO_APIC_irqs ();
 
 	if (!timer_irq_works ()) {
@@ -644,9 +717,9 @@
 		printk("..MP-BIOS bug: i8254 timer not connected to IO-APIC\n");
 		printk("..falling back to 8259A-based timer interrupt\n");
 	}
-
-	printk("nr of MP irq sources: %d.\n", mp_irq_entries);
-	printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);
+ 
+ 	printk("nr of MP irq sources: %d.\n", mp_irq_entries);
+ 	printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);
 	print_IO_APIC();
 }
 
diff -u --recursive --new-file v2.1.92/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.1.92/linux/arch/i386/kernel/smp.c	Tue Mar 17 22:18:14 1998
+++ linux/arch/i386/kernel/smp.c	Sun Apr  5 12:08:41 1998
@@ -128,9 +128,6 @@
 static int smp_activated = 0;				/* Tripped once we need to start cross invalidating 	*/
 int apic_version[NR_CPUS];				/* APIC version number					*/
 static volatile int smp_commenced=0;			/* Tripped when we start scheduling 		    	*/
-unsigned long apic_addr = 0xFEE00000;			/* Address of APIC (defaults to 0xFEE00000)		*/
-unsigned long nlong = 0;				/* dummy used for apic_reg address + 0x20		*/
-unsigned char *apic_reg=((unsigned char *)(&nlong))-0x20;/* Later set to the ioremap() of the APIC 		*/
 unsigned long apic_retval;				/* Just debugging the assembler.. 			*/
 
 static volatile unsigned char smp_cpu_in_msg[NR_CPUS];	/* True if this processor is sending an IPI		*/
@@ -150,6 +147,7 @@
 int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
 extern int mp_irq_entries;
 extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
+extern int mpc_default_type;
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
 int mp_current_pci_id = 0;
 
@@ -272,8 +270,9 @@
 
 	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
 
-	/* set the local APIC address */
-	apic_addr = (unsigned long)phys_to_virt((unsigned long)mpc->mpc_lapic);
+	/* check the local APIC address */
+	if ((char *)phys_to_virt((unsigned long)mpc->mpc_lapic) != APIC_BASE)
+		panic("unexpected APIC address");
 
 	/*
 	 *	Now process the configuration blocks.
@@ -454,7 +453,7 @@
 					 */
 			
 					cfg=pg0[0];
-					pg0[0] = (apic_addr | 7);
+					pg0[0] = ((unsigned long)APIC_BASE | 7);
 					local_flush_tlb();
 
 					boot_cpu_id = GET_APIC_ID(*((volatile unsigned long *) APIC_ID));
@@ -477,6 +476,14 @@
 					cpu_present_map=3;
 					num_processors=2;
 					printk("I/O APIC at 0xFEC00000.\n");
+
+					/*
+					 * Save the default type number, we
+					 * need it later to set the IO-APIC
+					 * up properly:
+					 */
+					mpc_default_type = mpf->mpf_feature1;
+
 					printk("Bus #0 is ");
 				}
 				switch(mpf->mpf_feature1)
@@ -525,11 +532,6 @@
 				if(mpf->mpf_physptr)
 					smp_read_mpc((void *)mpf->mpf_physptr);
 
-				/*
-				 *	Now that the boot CPU id is known,
-				 *	set some other information about it.
-				 */
-				nlong = boot_cpu_id<<24;	/* Dummy 'self' for bootup */
 				__cpu_logical_map[0] = boot_cpu_id;
 				global_irq_holder = boot_cpu_id;
 				current->processor = boot_cpu_id;
@@ -951,15 +953,6 @@
 		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
 	}
 
-	/*
-	 *	Map the local APIC into kernel space
-	 */
-
-	apic_reg = ioremap(apic_addr,4096);
-
-	if(apic_reg == NULL)
-		panic("Unable to map local apic.");
-
 #ifdef SMP_DEBUG
 	{
 		int reg;
@@ -1497,7 +1490,7 @@
 /*
  * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts
  * per second. We assume that the caller has already set up the local
- * APIC at apic_addr.
+ * APIC.
  *
  * The APIC timer is not exactly sync with the external timer chip, it
  * closely follows bus clocks.
diff -u --recursive --new-file v2.1.92/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.92/linux/arch/i386/mm/init.c	Tue Mar 17 22:18:14 1998
+++ linux/arch/i386/mm/init.c	Sun Apr  5 12:08:41 1998
@@ -174,29 +174,29 @@
  * It may also hold the MP configuration table when we are booting SMP.
  */
 #ifdef __SMP__
-	if (!smp_scan_config(0x0,0x400))	/* Scan the bottom 1K for a signature */
-	{
+	/*
+	 * FIXME: Linux assumes you have 640K of base ram..
+	 * this continues the error...
+	 *
+	 * 1) Scan the bottom 1K for a signature
+	 * 2) Scan the top 1K of base RAM
+	 * 3) Scan the 64K of bios
+	 */
+	if (!smp_scan_config(0x0,0x400) &&
+	    !smp_scan_config(639*0x400,0x400) &&
+	    !smp_scan_config(0xF0000,0x10000)) {
 		/*
-		 *	FIXME: Linux assumes you have 640K of base ram.. this continues
-		 *	the error...
+		 * If it is an SMP machine we should know now, unless the
+		 * configuration is in an EISA/MCA bus machine with an
+		 * extended bios data area. 
+		 *
+		 * there is a real-mode segmented pointer pointing to the
+		 * 4K EBDA area at 0x40E, calculate and scan it here:
 		 */
-		if (!smp_scan_config(639*0x400,0x400))	/* Scan the top 1K of base RAM */
-		{
-			if(!smp_scan_config(0xF0000,0x10000))	/* Scan the 64K of bios */
-			{
-				/*
-				 *	If it is an SMP machine we should know now, unless the configuration
-				 *	is in an EISA/MCA bus machine with an extended bios data area. 
-				 */
-		 
-				address = *(unsigned short *)phys_to_virt(0x40E); /* EBDA */
-				address<<=4;	/* Real mode segments to physical */
-				smp_scan_config(address, 0x1000);	/* Scan the EBDA */
-			}
-		}
+		address = *(unsigned short *)phys_to_virt(0x40E);
+		address<<=4;
+		smp_scan_config(address, 0x1000);
 	}
-			
-/*	smp_alloc_memory(8192); */
 #endif
 	start_mem = PAGE_ALIGN(start_mem);
 	address = PAGE_OFFSET;
@@ -255,7 +255,50 @@
 			address += PAGE_SIZE;
 		}
 	}
+#ifdef __SMP__
+{
+	pte_t pte;
+	unsigned long apic_area = (unsigned long)APIC_BASE;
+
+	pg_dir = swapper_pg_dir + ((apic_area) >> PGDIR_SHIFT);
+	memset((void *)start_mem, 0, PAGE_SIZE);
+	pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
+	start_mem += PAGE_SIZE;
+
+	if (smp_found_config) {
+		/*
+		 * Map the local APIC to FEE00000.
+		 */
+		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
+		pte = mk_pte(__va(apic_area), PAGE_KERNEL);
+		set_pte(pg_table, pte);
+
+		/*
+		 * Map the IO-APIC to FEC00000.
+		 */
+		apic_area = 0xFEC00000; /*(unsigned long)IO_APIC_BASE;*/
+		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
+		pte = mk_pte(__va(apic_area), PAGE_KERNEL);
+		set_pte(pg_table, pte);
+	} else {
+		/*
+		 * No local APIC but we are compiled SMP ... set up a
+		 * fake all zeroes page to simulate the local APIC.
+		 */
+		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
+		pte = mk_pte(start_mem, PAGE_KERNEL);
+		memset((void *)start_mem, 0, PAGE_SIZE);
+		start_mem += PAGE_SIZE;
+		set_pte(pg_table, pte);
+	}
+
+	local_flush_tlb();
+	printk("IO APIC ID: %d\n", *(int *)0xFEC00000);
+	printk("APIC ID: %d\n", *(int *)0xFEE00000);
+}
+#endif
 	local_flush_tlb();
+
 	return free_area_init(start_mem, end_mem);
 }
 
diff -u --recursive --new-file v2.1.92/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c
--- v2.1.92/linux/arch/mips/kernel/pci.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/pci.c	Thu Apr  2 09:12:22 1998
@@ -5,7 +5,6 @@
  *
  * MIPS implementation of PCI BIOS services for PCI support.
  */
-#include <linux/bios32.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -36,53 +35,6 @@
 }
 
 /*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.  
- */
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
-			 unsigned short index, unsigned char *bus,
-			 unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if (dev->vendor == vendor && dev->device == device_id) {
-			if (curr == index) {
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-int pcibios_find_class (unsigned int class_code, unsigned short index,
-			unsigned char *bus, unsigned char *devfn)
-{
-	unsigned int curr = 0;
-	struct pci_dev *dev;
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if (dev->class == class_code) {
-			if (curr == index) {
-				*devfn = dev->devfn;
-				*bus = dev->bus->number;
-				return PCIBIOS_SUCCESSFUL;
-			}
-			++curr;
-		}
-	}
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-/*
  * The functions below are machine specific and must be reimplented for
  * each PCI chipset configuration.  We just run the hook to the machine
  * specific implementation.
@@ -127,6 +79,11 @@
                                 unsigned char where, unsigned int val)
 {
 	return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val);
+}
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	return str;
 }
 
 #endif /* defined(CONFIG_PCI) */
diff -u --recursive --new-file v2.1.92/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c
--- v2.1.92/linux/arch/mips/sni/pci.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sni/pci.c	Thu Apr  2 09:12:22 1998
@@ -6,7 +6,6 @@
  * SNI specific PCI support for RM200/RM300.
  */
 #include <linux/config.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.92/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.1.92/linux/drivers/block/Config.in	Wed Feb  4 11:36:00 1998
+++ linux/drivers/block/Config.in	Thu Apr  2 09:12:22 1998
@@ -34,6 +34,9 @@
           fi
         fi
       fi
+      if [ "$CONFIG_CHRP" = "y" ]; then
+          bool '   WInbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
+      fi
     fi
     bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
     if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
diff -u --recursive --new-file v2.1.92/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.1.92/linux/drivers/block/Makefile	Tue Mar 10 10:03:31 1998
+++ linux/drivers/block/Makefile	Thu Apr  2 09:12:22 1998
@@ -155,6 +155,14 @@
 L_OBJS += ns87415.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_CMD646),y)
+L_OBJS += cmd646.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
+L_OBJS += sl82c105.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDEDISK),y)
 L_OBJS += ide-disk.o
 else
diff -u --recursive --new-file v2.1.92/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c
--- v2.1.92/linux/drivers/block/cmd646.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/cmd646.c	Thu Apr  2 09:12:22 1998
@@ -0,0 +1,20 @@
+/* $Id: cmd646.c,v 1.1 1998/03/15 13:29:10 ecd Exp $
+ * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines
+ *
+ * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#include <linux/pci.h>
+#include "ide.h"
+
+__initfunc(void ide_init_cmd646 (ide_hwif_t *hwif))
+{
+#ifdef __sparc_v9__
+	struct pci_dev *dev = hwif->pci_dev;
+	unsigned char mrdmode;
+
+	(void) pci_read_config_byte(dev, 0x71, &mrdmode);
+	mrdmode &= ~(0x30);
+	(void) pci_write_config_byte(dev, 0x71, mrdmode);
+#endif
+}
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.1.92/linux/drivers/block/ide-dma.c	Thu Jan 15 20:51:04 1998
+++ linux/drivers/block/ide-dma.c	Thu Apr  2 09:12:22 1998
@@ -70,7 +70,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -84,6 +84,7 @@
  */
 const char *good_dma_drives[] = {"Micropolis 2112A",
 				 "CONNER CTMA 4000",
+				 "ST34342A",
 				 NULL};
 
 /*
@@ -140,7 +141,7 @@
 {
 	struct request *rq = HWGROUP(drive)->rq;
 	struct buffer_head *bh = rq->bh;
-	unsigned long size, addr, *table = HWIF(drive)->dmatable;
+	unsigned int size, addr, *table = (unsigned int *)HWIF(drive)->dmatable;
 #ifdef CONFIG_BLK_DEV_TRM290
 	unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
 #else
@@ -183,7 +184,7 @@
 				printk("%s: DMA table too small\n", drive->name);
 				return 0; /* revert to PIO for this request */
 			} else {
-				unsigned long xcount, bcount = 0x10000 - (addr & 0xffff);
+				unsigned int xcount, bcount = 0x10000 - (addr & 0xffff);
 				if (bcount > size)
 					bcount = size;
 				*table++ = cpu_to_le32(addr);
@@ -288,7 +289,7 @@
 	}
 }
 
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) /* __init */
+__initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports))
 {
 	static unsigned long dmatable = 0;
 	static unsigned leftover = 0;
@@ -320,74 +321,39 @@
 		if (hwif->chipset != ide_trm290) {
 			byte dma_stat = inb(dma_base+2);
 			printk(", BIOS settings: %s:%s, %s:%s",
-		 	 hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
-		 	 hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
+			       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
+			       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
 		}
 		printk("\n");
 	}
 }
 
-/* The next two functions were stolen from cmd640.c, with a few modifications  */
-
-__initfunc(static void write_pcicfg_dword (byte fn, unsigned short reg, long val))
-{
-  unsigned long flags;
-
-  save_flags(flags);
-  cli();
-  outl_p((reg & 0xfc) | ((fn * 0x100) + 0x80000000), 0xcf8);
-  outl_p(val, (reg & 3) | 0xcfc);
-  restore_flags(flags);
-}
-
-__initfunc(static long read_pcicfg_dword (byte fn, unsigned short reg))
-{
-  long b;
-  unsigned long flags;
-
-  save_flags(flags);
-  cli();
-  outl_p((reg & 0xfc) | ((fn * 0x100) + 0x80000000), 0xcf8);
-  b = inl_p((reg & 3) | 0xcfc);
-  restore_flags(flags);
-  return b;
-}
-
 /*
  * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
  */
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) /* __init */
+__initfunc(unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name))
 {
 	unsigned long new, dma_base = 0;
-	byte bus = hwif->pci_bus, fn = hwif->pci_fn;
 
 	if (hwif->mate && hwif->mate->dma_base) {
 		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
-	} else if (pcibios_read_config_dword(bus, fn, 0x20, (unsigned int *)&dma_base)) {
-		printk("%s: failed to read dma_base\n", name);
-		dma_base = 0;
-	} else if ((dma_base &= ~0xf) == 0 || dma_base == ~0xf) {
-		printk("%s: dma_base is invalid (0x%04lx, BIOS problem)\n", name, dma_base);
-		new = ide_find_free_region(16 + extra);
-		hwif->no_autodma = 1;	/* default DMA off if we had to configure it here */
-		if (new) {
-			printk("%s: setting dma_base to 0x%04lx\n", name, new);
-			new |= 1;
-			(void) pcibios_write_config_dword(bus, fn, 0x20, new);
-			dma_base = 0;
-			(void) pcibios_read_config_dword(bus, fn, 0x20, (unsigned int *)&dma_base);
-			if (dma_base != new) {
-				if (bus == 0) {
-					printk("%s: operation failed, bypassing BIOS to try again\n", name);
-					write_pcicfg_dword(fn, 0x20, new);
-					dma_base = read_pcicfg_dword(fn, 0x20);
-				}
+	} else {
+		dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+		if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) {
+			printk("%s: dma_base is invalid (0x%04lx, BIOS problem), please report to <mj@ucw.cz>\n", name, dma_base);
+			new = ide_find_free_region(16 + extra);
+			hwif->no_autodma = 1;	/* default DMA off if we had to configure it here */
+			if (new) {
+				printk("%s: setting dma_base to 0x%04lx\n", name, new);
+				new |= PCI_BASE_ADDRESS_SPACE_IO;
+				(void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, new);
+				dma_base = 0;
+				(void) pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, (unsigned int *) &dma_base);
 				if (dma_base != new) {
-					printk("%s: operation failed, DMA disabled\n", name);
+					printk("%s: Operation failed, DMA disabled\n", name);
 					dma_base = 0;
 				}
 			}
-			dma_base &= ~0xf;
 		}
 	}
 	if (dma_base) {
@@ -401,4 +367,3 @@
 	}
 	return dma_base;
 }
-
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.1.92/linux/drivers/block/ide-pci.c	Wed Apr  1 20:11:48 1998
+++ linux/drivers/block/ide-pci.c	Thu Apr  2 09:12:22 1998
@@ -17,7 +17,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -67,6 +67,13 @@
 #define INIT_NS87415	IDE_IGNORE
 #endif
 
+#ifdef CONFIG_BLK_DEV_CMD646
+extern void ide_init_cmd646(ide_hwif_t *);
+#define INIT_CMD646	&ide_init_cmd646
+#else
+#define INIT_CMD646	IDE_IGNORE
+#endif
+
 #ifdef CONFIG_BLK_DEV_RZ1000
 extern void ide_init_rz1000(ide_hwif_t *);
 #define INIT_RZ1000	&ide_init_rz1000
@@ -99,7 +106,7 @@
 	{DEVID_CMD640,	"CMD640",	IDE_IGNORE,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
 	{DEVID_NS87410,	"NS87410",	NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}} },
 	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}} },
-	{DEVID_CMD646,	"CMD646",	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}} },
+	{DEVID_CMD646,	"CMD646",	INIT_CMD646,	{{0x00,0x00,0x00}, {0x51,0x80,0x80}} },
 	{DEVID_HT6565,	"HT6565",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
 	{DEVID_OPTI621,	"OPTI621",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
 	{DEVID_OPTI621X,"OPTI621X",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
@@ -137,7 +144,7 @@
  * Match a PCI IDE port against an entry in ide_hwifs[],
  * based on io_base port if possible.
  */
-__initfunc(static ide_hwif_t *ide_match_hwif (unsigned int io_base, const char *name))
+__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char *name))
 {
 	int h;
 	ide_hwif_t *hwif;
@@ -163,7 +170,7 @@
 		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
 			if (hwif->chipset == ide_unknown)
 				return hwif; /* match */
-			printk("%s: port 0x%04x already claimed by %s\n", name, io_base, hwif->name);
+			printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name);
 			return NULL;	/* already claimed */
 		}
 	}
@@ -188,7 +195,7 @@
 	return NULL;
 }
 
-__initfunc(static int ide_setup_pci_baseregs (byte bus, byte fn, const char *name))
+__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name))
 {
 	unsigned int base, readback;
 	byte reg, progif = 0;
@@ -196,14 +203,14 @@
 	/*
 	 * Place both IDE interfaces into PCI "native" mode:
 	 */
-	if (pcibios_read_config_byte(bus, fn, 0x09, &progif) || (progif & 5) != 5) {
+	if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
 		if ((progif & 0xa) != 0xa) {
 			printk("%s: device not capable of full native PCI mode\n", name);
 			return 1;
 		}
 		printk("%s: placing both ports into native PCI mode\n", name);
-		(void) pcibios_write_config_byte(bus, fn, 0x09, progif|5);
-		if (pcibios_read_config_byte(bus, fn, 0x09, &progif) || (progif & 5) != 5) {
+		(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
+		if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
 			printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif);
 			return 1;
 		}
@@ -213,9 +220,10 @@
 	 */
 	if (!(base = ide_find_free_region(32)))
 		return 1;
-	for (reg = 0x10; reg <= 0x1c; reg += 4, base += 8) {
-		(void) pcibios_write_config_dword(bus, fn, reg, base|1);
-		if (pcibios_read_config_dword(bus, fn, reg, &readback) || (readback &= ~1) != base) {
+	for (reg = 0; reg < 4; reg++, base += 8) {
+		(void) pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, base | PCI_BASE_ADDRESS_SPACE_IO);
+		if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + reg, &readback) ||
+		    readback != (base | PCI_BASE_ADDRESS_SPACE_IO)) {
 			printk("%s: readback failed for basereg 0x%02x: wrote 0x%04x, read 0x%x04\n", name, reg, base, readback);
 			return 1;
 		}
@@ -233,22 +241,19 @@
  * we "know" about, this information is in the ide_pci_device_t struct;
  * for all other chipsets, we just assume both interfaces are enabled.
  */
-__initfunc(static void ide_setup_pci_device (byte bus, byte fn, unsigned int ccode, ide_pci_device_t *d))
+__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d))
 {
-	unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0;
+	unsigned int port, at_least_one_hwif_enabled = 0, no_autodma = 0, pciirq = 0;
 	unsigned short pcicmd = 0, tried_config = 0;
-	byte tmp = 0, progif = 0, pciirq = 0;
+	byte tmp = 0;
 	ide_hwif_t *hwif, *mate = NULL;
 
 check_if_enabled:
-	if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd)
-	 || pcibios_read_config_byte(bus, fn, 0x09, &progif)
-	 || pcibios_read_config_byte(bus, fn, 0x3c, &pciirq))
-	{
+	if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
 		printk("%s: error accessing PCI regs\n", d->name);
 		return;
 	}
-	if (!(pcicmd & 1)) {	/* is device disabled? */
+	if (!(pcicmd & PCI_COMMAND_IO)) {	/* is device disabled? */
 		/*
 		 * PnP BIOS was *supposed* to have set this device up for us,
 		 * but we can do it ourselves, so long as the BIOS has assigned an IRQ
@@ -257,9 +262,8 @@
 		 * but we'll eventually ignore it again if no drives respond.
 		 */
 		if (tried_config++
-		 || ide_setup_pci_baseregs(bus, fn, d->name)
-		 || pcibios_write_config_word(bus, fn, 0x04, pcicmd|1))
-		{
+		 || ide_setup_pci_baseregs(dev, d->name)
+		 || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
 			printk("%s: device disabled (BIOS)\n", d->name);
 			return;
 		}
@@ -271,39 +275,47 @@
 	/*
 	 * Can we trust the reported IRQ?
 	 */
-	if ((ccode >> 16) != PCI_CLASS_STORAGE_IDE || (progif & 5) != 5) {
+	pciirq = dev->irq;
+	if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
 		printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
 		pciirq = 0;
 	} else if (tried_config) {
 		printk("%s: will probe irqs later\n", d->name);
 		pciirq = 0;
-	} else if (!pciirq || pciirq >= NR_IRQS) {
-		printk("%s: bad irq from BIOS (%d): will probe later\n", d->name, pciirq);
+	} else if (!pciirq) {
+		printk("%s: bad irq (%d): will probe later\n", d->name, pciirq);
 		pciirq = 0;
 	} else {
+#ifdef __sparc_v9__
+		printk("%s: 100%% native mode on irq %08x\n", d->name, pciirq);
+#else
 		printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
+#endif
 	}
 	/*
 	 * Set up the IDE ports
 	 */
 	for (port = 0; port <= 1; ++port) {
-		unsigned int base = 0, ctl = 0;
+		unsigned long base = 0, ctl = 0;
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
-		if (e->reg && (pcibios_read_config_byte(bus, fn, e->reg, &tmp) || (tmp & e->mask) != e->val))
+		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
 			continue;	/* port not enabled */
-		if (pcibios_read_config_dword(bus, fn, 0x14+(port*8), &ctl) || (ctl &= ~3) == 0)
+		ctl = dev->base_address[1+2*port] & PCI_BASE_ADDRESS_IO_MASK;
+		if (!ctl)
 			ctl = port ? 0x374 : 0x3f4;	/* use default value */
-		if (pcibios_read_config_dword(bus, fn, 0x10+(port*8), &base) || (base &= ~7) == 0)
+		base = dev->base_address[2*port] & ~7;
+
+		if (!base)
 			base = port ? 0x170 : 0x1f0;	/* use default value */
 		if ((hwif = ide_match_hwif(base, d->name)) == NULL)
 			continue;	/* no room in ide_hwifs[] */
 		if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
 			ide_init_hwif_ports(hwif->io_ports, base, NULL);
 			hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2;
+			hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
 		}
 		hwif->chipset = ide_pci;
-		hwif->pci_bus = bus;
-		hwif->pci_fn = fn;
+		hwif->pci_dev = dev;
 		hwif->pci_devid = d->devid;
 		hwif->channel = port;
 		if (!hwif->irq)
@@ -315,16 +327,18 @@
 		if (no_autodma)
 			hwif->no_autodma = 1;
 #ifdef CONFIG_BLK_DEV_IDEDMA
-		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || ((ccode >> 16) == PCI_CLASS_STORAGE_IDE && (ccode & 0x8000))) {
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
+		    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
 			unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
-			unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name);
-			if (dma_base && !(pcicmd & 4)) {
+			unsigned long dma_base = ide_get_or_set_dma_base(dev, hwif, extra, d->name);
+			if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
 				/*
  	 			 * Set up BM-DMA capability (PnP BIOS should have done this)
  	 			 */
+printk("%s: %s enabling Bus-Master DMA\n", hwif->name, d->name);
 				hwif->no_autodma = 1;	/* default DMA off if we had to configure it here */
-				(void) pcibios_write_config_word(bus, fn, 0x04, (pcicmd|4));
-				if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd) || !(pcicmd & 4)) {
+				(void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
+				if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
 					printk("%s: %s error updating PCICMD\n", hwif->name, d->name);
 					dma_base = 0;
 				}
@@ -332,8 +346,7 @@
 			if (dma_base)
 				ide_setup_dma(hwif, dma_base, 8);
 			else
-				printk("%s: %s Bus-Master DMA disabled (BIOS), pcicmd=0x%04x, ccode=0x%04x, dma_base=0x%04lx\n",
-				 hwif->name, d->name, pcicmd, ccode, dma_base);
+				printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name);
 		}
 #endif	/* CONFIG_BLK_DEV_IDEDMA */
 		if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
@@ -346,66 +359,32 @@
 }
 
 /*
- * ide_scan_pci_device() examines all functions of a PCI device,
- * looking for IDE interfaces and/or devices in ide_pci_chipsets[].
- * We cannot use pcibios_find_class() cuz it doesn't work in all systems.
+ * ide_scan_pcibus() gets invoked at boot time from ide.c.
+ * It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
  */
-static inline void ide_scan_pci_device (unsigned int bus, unsigned int fn)
+__initfunc(void ide_scan_pcibus (void))
 {
-	unsigned int		ccode;
+	struct pci_dev		*dev;
 	ide_pci_devid_t		devid;
 	ide_pci_device_t	*d;
-	byte			hedt;
-
-	if (pcibios_read_config_byte(bus, fn, 0x0e, &hedt))
-		hedt = 0;
-	do {
-		if (pcibios_read_config_word(bus, fn, 0x00, &devid.vid)
-		 || devid.vid == 0xffff
-		 || pcibios_read_config_word(bus, fn, 0x02, &devid.did)
-		 || IDE_PCI_DEVID_EQ(devid, IDE_PCI_DEVID_NULL)
-		 || pcibios_read_config_dword(bus, fn, 0x08, &ccode))
-			return;
-		/* 
-		 * workaround Intel Advanced/ZP with bios <= 1.04;
-		 * these appear in some Dell Dimension XPS's 
-		 */
-		if (!hedt && IDE_PCI_DEVID_EQ(devid, DEVID_PIIXa)) {
-			printk("ide: implementing workaround for PIIX detection\n");
-		        hedt = 0x80;
-		}
 
+	if (!pci_present())
+		return;
+	for(dev = pci_devices; dev; dev=dev->next) {
+		devid.vid = dev->vendor;
+		devid.did = dev->device;
 		for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d);
 		if (d->init_hwif == IDE_IGNORE)
 			printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
-		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(fn & 1))
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
 			continue;	/* OPTI Viper-M uses same devid for functions 0 and 1 */
-		else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (ccode >> 16) == PCI_CLASS_STORAGE_IDE) {
+		else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
 			if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
-				printk("%s: unknown IDE controller on PCI bus %d function %d, VID=%04x, DID=%04x\n",
-					d->name, bus, fn, 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 bus %d function %d\n", d->name, bus, fn);
-			ide_setup_pci_device(bus, fn, ccode, d);
-		}
-	} while ((hedt & 0x80) && (++fn & 7));
-}
-
-/*
- * ide_scan_pcibus() gets invoked at boot time from ide.c
- *
- * Loops over all PCI devices on all PCI buses, invoking ide_scan_pci_device().
- * We cannot use pcibios_find_class() cuz it doesn't work in all systems.
- */
-void ide_scan_pcibus (void) /* __init */
-{
-	unsigned int bus, dev;
-
-	if (!pcibios_present())
-		return;
-	for (bus = 0; bus <= 255; ++bus) {
-		for (dev = 0; dev < 256; dev += 8) {
-			ide_scan_pci_device(bus, dev);
+				printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+			ide_setup_pci_device(dev, d);
 		}
 	}
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- v2.1.92/linux/drivers/block/ide-proc.c	Wed Apr  1 20:11:48 1998
+++ linux/drivers/block/ide-proc.c	Thu Apr  2 09:12:22 1998
@@ -64,7 +64,6 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/ctype.h>
 #include <asm/io.h>
 #include "ide.h"
@@ -211,21 +210,22 @@
 				if (is_pci) {
 #ifdef CONFIG_BLK_DEV_IDEPCI
 					int rc = 0;
+					struct pci_dev *dev = hwif->pci_dev;
 					switch (digits) {
 						case 2:	msg = "byte";
-							rc = pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, reg, val);
+							rc = pci_write_config_byte(dev, reg, val);
 							break;
 						case 4:	msg = "word";
-							rc = pcibios_write_config_word(hwif->pci_bus, hwif->pci_fn, reg, val);
+							rc = pci_write_config_word(dev, reg, val);
 							break;
 						case 8:	msg = "dword";
-							rc = pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, reg, val);
+							rc = pci_write_config_dword(dev, reg, val);
 							break;
 					}
 					if (rc) {
 						restore_flags(flags);
-						printk("proc_ide_write_config: error writing %s at bus %d fn %d reg 0x%x value 0x%x\n",
-							msg, hwif->pci_bus, hwif->pci_fn, reg, val);
+						printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n",
+							msg, dev->bus->number, dev->devfn, reg, val);
 						printk("proc_ide_write_config: %s\n", pcibios_strerror(rc));
 						return -EIO;
 					}
@@ -259,14 +259,16 @@
 	int		len, reg = 0;
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	out += sprintf(out, "pci bus %d device %d vid %04x did %04x channel %d\n",
-		hwif->pci_bus, hwif->pci_fn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
+	struct pci_dev *dev = hwif->pci_dev;
+
+	out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
+		dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
 	do {
 		byte val;
-		int rc = pcibios_read_config_byte(hwif->pci_bus, hwif->pci_fn, reg, &val);
+		int rc = pci_read_config_byte(dev, reg, &val);
 		if (rc) {
-			printk("proc_ide_read_config: error reading bus %d fn %d reg 0x%02x\n",
-				hwif->pci_bus, hwif->pci_fn, reg);
+			printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n",
+				dev->bus->number, dev->devfn, reg);
 			printk("proc_ide_read_config: %s\n", pcibios_strerror(rc));
 			return -EIO;
 			out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.92/linux/drivers/block/ide.c	Wed Apr  1 20:11:48 1998
+++ linux/drivers/block/ide.c	Thu Apr  2 09:12:22 1998
@@ -107,7 +107,6 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/malloc.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 
@@ -263,7 +262,7 @@
 		if (idebus_parameter)
 			system_bus_speed = idebus_parameter;	/* user supplied value */
 #ifdef CONFIG_PCI
-		else if (pcibios_present())
+		else if (pci_present())
 			system_bus_speed = 40;	/* safe default value for PCI */
 #endif /* CONFIG_PCI */
 		else
@@ -1260,6 +1259,12 @@
 	} while ((hwif = hwif->next) != hwgroup->hwif);
 }
 
+#ifdef __sparc_v9__
+#define IDE_IRQ_EQUAL(irq1, irq2)	(1)
+#else
+#define IDE_IRQ_EQUAL(irq1, irq2)	((irq1) == (irq2))
+#endif
+
 /*
  * entry point for all interrupts, caller does __cli() for us
  */
@@ -1270,25 +1275,28 @@
 	ide_hwif_t *hwif = hwgroup->hwif;
 	ide_handler_t *handler;
 
-	if (!ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
+	if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
 		return;
+
 	do {
-		if (hwif->irq != irq) disable_irq(hwif->irq);
+		if (!IDE_IRQ_EQUAL(irq, hwgroup->hwif->irq))
+			disable_irq(hwif->irq);
 	} while ((hwif = hwif->next) != hwgroup->hwif);
-	if (irq == hwif->irq && (handler = hwgroup->handler) != NULL) {
+	if (IDE_IRQ_EQUAL(irq, hwif->irq)
+	    && (handler = hwgroup->handler) != NULL) {
 		ide_drive_t *drive = hwgroup->drive;
-#if 1	/* temporary, remove later -- FIXME */
+#if 1  /* temporary, remove later -- FIXME */
 		{
 			struct request *rq = hwgroup->rq;
 			if (rq != NULL
-			 &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
-			 || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
+			    &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
+			    || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
 			{
 				printk("ide_intr: got IRQ from wrong device: email mlord@pobox.com!!\n");
 				return;
 			}
 		}
-#endif	/* temporary */
+#endif /* temporary */
 		hwgroup->handler = NULL;
 		del_timer(&(hwgroup->timer));
 		/* if (drive->unmask)
@@ -1308,7 +1316,8 @@
 	__cli();
 	hwif = hwgroup->hwif;
 	do {
-		if (hwif->irq != irq) enable_irq(hwif->irq);
+		if (!IDE_IRQ_EQUAL(hwif->irq, irq))
+			enable_irq(hwif->irq);
 	} while ((hwif = hwif->next) != hwgroup->hwif);
 }
 
@@ -2520,7 +2529,7 @@
 __initfunc(static void probe_for_hwifs (void))
 {
 #ifdef CONFIG_PCI
-	if (pcibios_present())
+	if (pci_present())
 	{
 #ifdef CONFIG_BLK_DEV_IDEPCI
 		ide_scan_pcibus();
@@ -2530,23 +2539,29 @@
 			extern void ide_probe_for_rz100x(void);
 			ide_probe_for_rz100x();
 		}
-#endif	/* CONFIG_BLK_DEV_RZ1000 */
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
+#endif /* CONFIG_BLK_DEV_RZ1000 */
+#ifdef CONFIG_BLK_DEV_SL82C105
+		{
+			extern void ide_probe_for_sl82c105(void);
+			ide_probe_for_sl82c105();
+		}
+#endif /* CONFIG_BLK_DEV_SL82C105 */
+#endif /* CONFIG_BLK_DEV_IDEPCI */
 	}
-#endif	/* CONFIG_PCI */
+#endif /* CONFIG_PCI */
 
 #ifdef CONFIG_BLK_DEV_CMD640
 	{
 		extern void ide_probe_for_cmd640x(void);
 		ide_probe_for_cmd640x();
 	}
-#endif	/* CONFIG_BLK_DEV_CMD640 */
+#endif /* CONFIG_BLK_DEV_CMD640 */
 #ifdef CONFIG_BLK_DEV_PDC4030
 	{
 		extern int init_pdc4030(void);
 		(void) init_pdc4030();
 	}
-#endif	/* CONFIG_BLK_DEV_PDC4030 */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
 }
 
 __initfunc(void ide_init_builtin_drivers (void))
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.1.92/linux/drivers/block/ide.h	Wed Apr  1 20:11:48 1998
+++ linux/drivers/block/ide.h	Mon Apr  6 11:50:47 1998
@@ -340,8 +340,7 @@
 	unsigned	reset      : 1;	/* reset after probe */
 	unsigned	no_autodma : 1;	/* don't automatically enable DMA at boot */
 	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
-	byte		pci_bus;	/* for pci chipsets */
-	byte		pci_fn;		/* for pci chipsets */
+	struct		pci_dev *pci_dev; /* for pci chipsets */
 	ide_pci_devid_t	pci_devid;	/* for pci chipsets: {VID,DID} */
 #if (DISK_RECOVERY_TIME > 0)
 	unsigned long	last_time;	/* time when previous rq was done */
@@ -723,7 +722,7 @@
 void ide_dma_intr  (ide_drive_t *drive);
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
 void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
+unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name) __init;
 #endif
 
 #ifdef CONFIG_BLK_DEV_IDE
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.1.92/linux/drivers/block/ll_rw_blk.c	Wed Apr  1 20:11:48 1998
+++ linux/drivers/block/ll_rw_blk.c	Sun Apr  5 14:11:55 1998
@@ -38,6 +38,15 @@
 
 /*
  * Protect the request list against multiple users..
+ *
+ * With this spinlock the Linux block IO subsystem is 100% SMP threaded
+ * from the IRQ event side, and almost 100% SMP threaded from the syscall
+ * side (we still have protect against block device array operations, and
+ * the do_request() side is casually still unsafe. The kernel lock protects
+ * this part currently.).
+ *
+ * there is a fair chance that things will work just OK if these functions
+ * are called with no global kernel lock held ...
  */
 spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED;
 
@@ -106,6 +115,11 @@
 	return max_sectors[MAJOR(dev)][MINOR(dev)];
 }
 
+/*
+ * Is called with the request spinlock aquired.
+ * NOTE: the device-specific queue() functions
+ * have to be atomic!
+ */
 static inline struct request **get_queue(kdev_t dev)
 {
 	int major = MAJOR(dev);
@@ -122,19 +136,27 @@
 void unplug_device(void * data)
 {
 	struct blk_dev_struct * dev = (struct blk_dev_struct *) data;
+	int queue_new_request=0;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&io_request_lock,flags);
 	if (dev->current_request == &dev->plug) {
 		struct request * next = dev->plug.next;
 		dev->current_request = next;
 		if (next || dev->queue) {
 			dev->plug.next = NULL;
-			(dev->request_fn)();
+			queue_new_request = 1;
 		}
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&io_request_lock,flags);
+
+	if (queue_new_request)
+		/*
+		 * request functions are smart enough to notice a change
+		 * in the request queue, calling them without the spinlock
+		 * is OK, i think. <-- FIXME: [is this true? --mingo]
+		 */
+		(dev->request_fn)();
 }
 
 /*
@@ -143,6 +165,7 @@
  * on the list.
  *
  * This is called with interrupts off and no requests on the queue.
+ * (and with the request spinlock aquired)
  */
 static inline void plug_device(struct blk_dev_struct * dev)
 {
@@ -154,8 +177,8 @@
 
 /*
  * look for a free request in the first N entries.
- * NOTE: interrupts must be disabled on the way in, and will still
- *       be disabled on the way out.
+ * NOTE: interrupts must be disabled on the way in (on SMP the request queue
+ * spinlock has to be aquired), and will still be disabled on the way out.
  */
 static inline struct request * get_request(int n, kdev_t dev)
 {
@@ -191,13 +214,14 @@
 {
 	register struct request *req;
 	struct wait_queue wait = { current, NULL };
+	unsigned long flags;
 
 	add_wait_queue(&wait_for_request, &wait);
 	for (;;) {
 		current->state = TASK_UNINTERRUPTIBLE;
-		cli();
+		spin_lock_irqsave(&io_request_lock,flags);
 		req = get_request(n, dev);
-		sti();
+		spin_unlock_irqrestore(&io_request_lock,flags);
 		if (req)
 			break;
 		run_task_queue(&tq_disk);
@@ -211,10 +235,11 @@
 static inline struct request * get_request_wait(int n, kdev_t dev)
 {
 	register struct request *req;
+	unsigned long flags;
 
-	cli();
+	spin_lock_irqsave(&io_request_lock,flags);
 	req = get_request(n, dev);
-	sti();
+	spin_unlock_irqrestore(&io_request_lock,flags);
 	if (req)
 		return req;
 	return __get_request_wait(n, dev);
@@ -261,8 +286,9 @@
 
 /*
  * add-request adds a request to the linked list.
- * It disables interrupts so that it can muck with the
- * request-lists in peace.
+ * It disables interrupts (aquires the request spinlock) so that it can muck
+ * with the request-lists in peace. Thus it should be called with no spinlocks
+ * held.
  *
  * By this point, req->cmd is always either READ/WRITE, never READA/WRITEA,
  * which is important for drive_stat_acct() above.
@@ -272,6 +298,8 @@
 {
 	struct request * tmp, **current_request;
 	short		 disk_index;
+	unsigned long flags;
+	int queue_new_request = 0;
 
 	switch (MAJOR(req->rq_dev)) {
 		case SCSI_DISK_MAJOR:
@@ -292,16 +320,20 @@
 	}
 
 	req->next = NULL;
+
+	/*
+	 * We use the goto to reduce locking complexity
+	 */
+	spin_lock_irqsave(&io_request_lock,flags);
 	current_request = get_queue(req->rq_dev);
-	cli();
+
 	if (req->bh)
 		mark_buffer_clean(req->bh);
 	if (!(tmp = *current_request)) {
 		*current_request = req;
 		if (dev->current_request != &dev->plug)
-			(dev->request_fn)();
-		sti();
-		return;
+			queue_new_request = 1;
+		goto out;
 	}
 	for ( ; tmp->next ; tmp = tmp->next) {
 		if ((IN_ORDER(tmp,req) ||
@@ -314,11 +346,21 @@
 
 /* for SCSI devices, call request_fn unconditionally */
 	if (scsi_blk_major(MAJOR(req->rq_dev)))
+		queue_new_request = 1;
+out:
+	spin_unlock_irqrestore(&io_request_lock,flags);
+
+	/*
+	 * request_fn() is usually a quite complex and slow function,
+	 * we want to call it with no spinlocks held
+	 */
+	if (queue_new_request)
 		(dev->request_fn)();
-
-	sti();
 }
 
+/*
+ * Has to be called with the request spinlock aquired
+ */
 static inline void attempt_merge (struct request *req, int max_sectors)
 {
 	struct request *next = req->next;
diff -u --recursive --new-file v2.1.92/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c
--- v2.1.92/linux/drivers/block/ns87415.c	Wed Dec 17 11:11:16 1997
+++ linux/drivers/block/ns87415.c	Thu Apr  2 09:12:23 1998
@@ -2,6 +2,7 @@
  * linux/drivers/block/ns87415.c	Version 1.00  December 7, 1997
  *
  * Copyright (C) 1997-1998  Mark Lord
+ * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
  *
  * Inspired by an earlier effort from David S. Miller (davem@caipfs.rutgers.edu)
  */
@@ -15,112 +16,12 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include "ide.h"
 
 
-#undef INCLUDE_OBSOLETE_NS87514_STUFF	/* define this if you absolutely *need* the timings stuff */
-
-
-#ifdef INCLUDE_OBSOLETE_NS87514_STUFF
-/*
- * This part adapted from code from David S. Miller (davem@caipfs.rutgers.edu)
- * which was in turn adapted from code from Mark Lord.
- *
- * Here as a temporary measure only.  Will be removed once /proc/ide/ is working.
- */
-#include "ide_modes.h"
-
-static void ns87415_program_modes(ide_drive_t *drive, byte active_count, byte recovery_count)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	byte cfg_reg, regval;
-
-	cfg_reg = (0x44 + (8 * HWIF(drive)->channel) + (4 * drive->select.b.unit));
-
-	/* set identical PIO timings for read/write */
-	regval  = (17 - active_count) | ((16 - recovery_count) << 4);
-	pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, cfg_reg, regval);
-	pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, cfg_reg + 1, regval);
-}
-
-static void set_ide_modes(ide_drive_t *drive, ide_pio_data_t *d, int bus_speed)
-{
-	int setup_time, active_time, cycle_time = d->cycle_time;
-	byte setup_count, active_count, pio_mode = d->pio_mode;
-	byte recovery_count, recovery_count2, cycle_count;
-	int recovery_time, clock_time;
-
-	if(pio_mode > 5)
-		pio_mode = 5;
-
-	setup_time = ide_pio_timings[pio_mode].setup_time;
-	active_time = ide_pio_timings[pio_mode].active_time;
-
-	recovery_time = cycle_time - (setup_time + active_time);
-	clock_time = 1000 / bus_speed;
-
-	cycle_count  = (cycle_time  + clock_time - 1) / clock_time;
-	setup_count  = (setup_time  + clock_time - 1) / clock_time;
-	active_count = (active_time + clock_time - 1) / clock_time;
-
-	if(active_count < 2)
-		active_count = 2;
-
-	recovery_count  = (recovery_time + clock_time - 1) / clock_time;
-	recovery_count2 = cycle_count - (setup_count + active_count);
-
-	if(recovery_count2 > recovery_count)
-		recovery_count = recovery_count2;
-	if(recovery_count < 2)
-		recovery_count = 2;
-	if(recovery_count > 17) {
-		active_count += recovery_count - 17;
-		recovery_count = 17;
-	}
-
-	if(active_count > 16)
-		active_count = 16;
-	if(recovery_count > 16)
-		recovery_count = 16;
-
-	printk("active[%d CLKS] recovery[%d CLKS]\n", active_count, recovery_count);
-
-	ns87415_program_modes(drive, active_count, recovery_count);
-}
-
-/* Configure for best PIO mode. */
-static void ns87415_tuneproc (ide_drive_t *drive, byte mode_wanted)
-{
-	ide_pio_data_t d;
-	int bus_speed = ide_system_bus_speed();
-
-	switch(mode_wanted) {
-	case 6:
-	case 7:
-		/* Changes to Fast-devsel are unsupported. */
-		return;
-
-	case 8:
-	case 9:
-		mode_wanted &= 1;
-		/* XXX set_prefetch_mode(index, mode_wanted); */
-		printk("%s: %sbled NS87415 prefetching...\n", drive->name, mode_wanted ? "en" : "dis");
-		return;
-	};
-
-	(void) ide_get_best_pio_mode(drive, mode_wanted, 5, &d);
-
-	printk("%s: selected NS87415 PIO mode%d (%dns)%s ",
-	       drive->name, d.pio_mode, d.cycle_time,
-	       d.overridden ? " (overriding vendor mode)" : "");
-
-	set_ide_modes(drive, &d, bus_speed);
-}
-#endif	/* INCLUDE_OBSOLETE_NS87514_STUFF */
-
-static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = {0};
+static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
 
 /*
  * This routine either enables/disables (according to drive->present)
@@ -131,24 +32,29 @@
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	unsigned int bit, new, *old = (unsigned int *) hwif->select_data;
-	unsigned int flags;
-
-	save_flags(flags);
-	cli();
+	struct pci_dev *dev = hwif->pci_dev;
+	unsigned long flags;
 
+	save_flags(flags); cli();
 	new = *old;
 
 	/* adjust IRQ enable bit */
 	bit = 1 << (8 + hwif->channel);
-	new = drive->present ? (new | bit) : (new & ~bit);
+	new = drive->present ? (new & ~bit) : (new | bit);
 
 	/* select PIO or DMA */
 	bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
 	new = use_dma ? (new | bit) : (new & ~bit);
 
 	if (new != *old) {
+		if (use_dma) {
+			bit = (1 << (5 + drive->select.b.unit));
+			outb((inb(hwif->dma_base+2) & 0x60) | bit,
+			     hwif->dma_base+2);
+		}
+
 		*old = new;
-		(void) pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, new);
+		(void) pci_write_config_dword(dev, 0x40, new);
 	}
 	restore_flags(flags);
 }
@@ -167,25 +73,35 @@
 		{
 			byte dma_stat = inb(hwif->dma_base+2);
 			int rc = (dma_stat & 7) != 4;
-			outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */
-			outb(dma_stat|6, hwif->dma_base+2);	/* clear the INTR & ERROR bits */
-			return rc;	/* verify good DMA status */
+			/* from errata: stop DMA, clear INTR & ERROR */
+			outb(7, hwif->dma_base);
+			/* clear the INTR & ERROR bits */
+			outb(dma_stat|6, hwif->dma_base+2);
+			/* verify good DMA status */
+			return rc;
 		}
 		case ide_dma_write:
 		case ide_dma_read:
-			ns87415_prepare_drive(drive, 1); /* select DMA xfer */
-			if (!ide_dmaproc(func, drive))	 /* use standard DMA stuff */
+			/* select DMA xfer */
+			ns87415_prepare_drive(drive, 1);
+			/* use standard DMA stuff */
+			if (!ide_dmaproc(func, drive))
 				return 0;
-			ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
+			/* DMA failed: select PIO xfer */
+			ns87415_prepare_drive(drive, 0);
 			return 1;
 		default:
-			return ide_dmaproc(func, drive); /* use standard DMA stuff */
+			/* use standard DMA stuff */
+			return ide_dmaproc(func, drive);
 	}
 }
 
 __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
 {
-	unsigned int ctrl, progif, using_inta;
+	struct pci_dev *dev = hwif->pci_dev;
+	unsigned int ctrl, using_inta;
+	byte progif, stat;
+	int timeout;
 
 	/*
 	 * We cannot probe for IRQ: both ports share common IRQ on INTA.
@@ -194,35 +110,51 @@
 	 *
 	 * IRQs get unmasked in selectproc when drive is first used.
 	 */
-	(void) pcibios_read_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, &ctrl);
-	(void) pcibios_read_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, &progif);
+	(void) pci_read_config_dword(dev, 0x40, &ctrl);
+	(void) pci_read_config_byte(dev, 0x09, &progif);
 	/* is irq in "native" mode? */
 	using_inta = progif & (1 << (hwif->channel << 1));
 	if (!using_inta)
 		using_inta = ctrl & (1 << (4 + hwif->channel));
-	(void) pcibios_write_config_dword(hwif->pci_bus, hwif->pci_fn, 0x40, ctrl);
 	if (hwif->mate) {
 		hwif->select_data = hwif->mate->select_data;
 	} else {
-		hwif->select_data = (unsigned int) &ns87415_control[ns87415_count++];
-		ctrl |= (1 << 8) | (1 << 9);		/* mask both IRQs */
+		hwif->select_data = (unsigned long)
+					&ns87415_control[ns87415_count++];
+		ctrl |= (1 << 8) | (1 << 9);	/* mask both IRQs */
 		if (using_inta)
-			ctrl &= ~(1 << 6);		/* unmask INTA */
+			ctrl &= ~(1 << 6);	/* unmask INTA */
 		*((unsigned int *)hwif->select_data) = ctrl;
+		(void) pci_write_config_dword(dev, 0x40, ctrl);
+
 		/*
 		 * Set prefetch size to 512 bytes for both ports,
 		 * but don't turn on/off prefetching here.
 		 */
-		pcibios_write_config_byte(hwif->pci_bus, hwif->pci_fn, 0x55, 0xee);
+		pci_write_config_byte(dev, 0x55, 0xee);
+
+#ifdef __sparc_v9__
+		/*
+		 * XXX: Reset the device, if we don't it will not respond
+		 *      to SELECT_DRIVE() properly during first probe_hwif().
+		 */
+		timeout = 10000;
+		outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		udelay(10);
+		outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		do {
+			udelay(50);
+			stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+                	if (stat == 0xff)
+                        	break;
+        	} while ((stat & BUSY_STAT) && --timeout);
+#endif
 	}
 	if (!using_inta)
 		hwif->irq = hwif->channel ? 15 : 14;	/* legacy mode */
 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-		hwif->irq = hwif->mate->irq;		/* share IRQ with mate */
+		hwif->irq = hwif->mate->irq;	/* share IRQ with mate */
 
 	hwif->dmaproc = &ns87415_dmaproc;
 	hwif->selectproc = &ns87415_selectproc;
-#ifdef INCLUDE_OBSOLETE_NS87514_STUFF
-	hwif->tuneproc = &ns87415_tuneproc;
-#endif	/* INCLUDE_OBSOLETE_NS87514_STUFF */
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/block/opti621.c linux/drivers/block/opti621.c
--- v2.1.92/linux/drivers/block/opti621.c	Wed Dec 17 11:11:16 1997
+++ linux/drivers/block/opti621.c	Thu Apr  2 09:12:23 1998
@@ -73,8 +73,6 @@
 #include <asm/io.h>
 #include "ide.h"
 #include "ide_modes.h"
-#include <linux/pci.h>
-#include <linux/bios32.h>
 
 #define OPTI621_MAX_PIO 3
 /* In fact, I do not have any PIO 4 drive
diff -u --recursive --new-file v2.1.92/linux/drivers/block/rz1000.c linux/drivers/block/rz1000.c
--- v2.1.92/linux/drivers/block/rz1000.c	Mon Feb 23 18:12:04 1998
+++ linux/drivers/block/rz1000.c	Thu Apr  2 09:12:23 1998
@@ -25,7 +25,6 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <asm/io.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include "ide.h"
 
@@ -34,10 +33,11 @@
 __initfunc(void ide_init_rz1000 (ide_hwif_t *hwif))	/* called from ide-pci.c */
 {
 	unsigned short reg;
+	struct pci_dev *dev = hwif->pci_dev;
 
 	hwif->chipset = ide_rz1000;
-	if (!pcibios_read_config_word (hwif->pci_bus, hwif->pci_fn, 0x40, &reg)
-	 && !pcibios_write_config_word(hwif->pci_bus, hwif->pci_fn, 0x40, reg & 0xdfff))
+	if (!pci_read_config_word (dev, 0x40, &reg)
+	 && !pci_write_config_word(dev, 0x40, reg & 0xdfff))
 	{
 		printk("%s: disabled chipset read-ahead (buggy RZ1000/RZ1001)\n", hwif->name);
 	} else {
@@ -50,16 +50,16 @@
 
 #else
 
-__initfunc(static void init_rz1000 (byte bus, byte fn, const char *name))
+__initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name))
 {
 	unsigned short reg, h;
 
-	if (!pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg) && !(reg & 1)) {
+	if (!pci_read_config_word (dev, PCI_COMMAND, &reg) && !(reg & PCI_COMMAND_IO)) {
 		printk("%s: buggy IDE controller disabled (BIOS)\n", name);
 		return;
 	}
-	if (!pcibios_read_config_word (bus, fn, 0x40, &reg)
-	 && !pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))
+	if (!pci_read_config_word (dev, 0x40, &reg)
+	 && !pci_write_config_word(dev, 0x40, reg & 0xdfff))
 	{
 		printk("IDE: disabled chipset read-ahead (buggy %s)\n", name);
 	} else {
@@ -82,12 +82,12 @@
 
 __initfunc(void ide_probe_for_rz100x (void))	/* called from ide.c */
 {
-	byte index, bus, fn;
+	struct pci_dev *dev = NULL;
 
-	for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, index, &bus, &fn); ++index)
-		init_rz1000 (bus, fn, "RZ1000");
-	for (index = 0; !pcibios_find_device (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, index, &bus, &fn); ++index)
-		init_rz1000 (bus, fn, "RZ1001");
+	while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1000, dev))
+		init_rz1000 (dev, "RZ1000");
+	while (dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_PD_PCTECH_RZ1001, dev))
+		init_rz1000 (dev, "RZ1001");
 }
 
 #endif CONFIG_BLK_DEV_IDEPCI
diff -u --recursive --new-file v2.1.92/linux/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c
--- v2.1.92/linux/drivers/block/sl82c105.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/sl82c105.c	Thu Apr  2 09:12:23 1998
@@ -0,0 +1,78 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include "ide.h"
+#include "ide_modes.h"
+
+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
+void ide_init_sl82c105(struct pci_dev *dev) {
+
+	unsigned short t16;
+	unsigned int t32;
+
+	pci_read_config_word(dev, PCI_COMMAND, &t16);
+	printk("SL82C105 command word: %x\n",t16);
+        t16 |= PCI_COMMAND_IO;
+        pci_write_config_word(dev, PCI_COMMAND, t16);
+	/* IDE timing */
+	pci_read_config_dword(dev, 0x44, &t32);
+	printk("IDE timing: %08x, resetting to PIO0 timing\n",t32);
+	pci_write_config_dword(dev, 0x44, 0x03e4);
+	pci_read_config_dword(dev, 0x40, &t32);
+	printk("IDE control/status register: %08x\n",t32);
+	pci_write_config_dword(dev, 0x40, 0x10ff08a1);
+}
+
+
+void ide_probe_for_sl82c105(void)
+{
+	struct pci_dev *dev = NULL;
+
+        while ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev)))
+                ide_init_sl82c105(dev);
+}
+
+void chrp_ide_probe(void) {
+
+	struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+	chrp_ide_ports_known = 1;
+
+        if(pdev) {
+		chrp_ide_regbase[0]=pdev->base_address[0] &
+			PCI_BASE_ADDRESS_IO_MASK;
+		chrp_ide_regbase[1]=pdev->base_address[2] &
+			PCI_BASE_ADDRESS_IO_MASK;
+		chrp_idedma_regbase=pdev->base_address[4] &
+			PCI_BASE_ADDRESS_IO_MASK;
+		chrp_ide_irq=pdev->irq;
+        }
+}
+
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+        ide_ioreg_t port = base;
+        int i = 8;
+
+        while (i--)
+                *p++ = port++;
+        *p++ = port;
+        if (irq != NULL)
+                *irq = chrp_ide_irq;
+}
+
diff -u --recursive --new-file v2.1.92/linux/drivers/block/trm290.c linux/drivers/block/trm290.c
--- v2.1.92/linux/drivers/block/trm290.c	Wed Dec 31 16:45:47 1997
+++ linux/drivers/block/trm290.c	Thu Apr  2 09:12:23 1998
@@ -133,7 +133,6 @@
 #include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 
 #include <asm/io.h>
@@ -213,13 +212,14 @@
 {
 	unsigned int cfgbase = 0;
 	unsigned long flags;
-	byte reg, progif;
+	byte reg;
+	struct pci_dev *dev = hwif->pci_dev;
 
 	hwif->chipset = ide_trm290;
-	if (!pcibios_read_config_byte(hwif->pci_bus, hwif->pci_fn, 0x09, &progif) && (progif & 5)
-	 && !pcibios_read_config_dword(hwif->pci_bus, hwif->pci_fn, 0x20, &cfgbase) && cfgbase)
+	cfgbase = dev->base_address[4];
+	if ((dev->class & 5) && cfgbase)
 	{
-		hwif->config_data = cfgbase & ~1;
+		hwif->config_data = cfgbase & PCI_BASE_ADDRESS_IO_MASK;
 		printk("TRM290: chip config base at 0x%04lx\n", hwif->config_data);
 	} else {
 		hwif->config_data = 0x3df0;
diff -u --recursive --new-file v2.1.92/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.1.92/linux/drivers/block/xd.c	Sun Jan  4 10:40:15 1998
+++ linux/drivers/block/xd.c	Sat Apr  4 09:36:10 1998
@@ -208,6 +208,7 @@
 		for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
 			if (check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
 				*controller = j;
+				xd_type = j;
 				*address = xd_bases[i];
 				found++;
 			}
@@ -705,9 +706,10 @@
 	switch (address) {
 		case 0x00000:
 		case 0xC8000:	break;			/*initial: 0x320 */
-		case 0xCA000:	xd_iobase = 0x324; break;
+		case 0xCA000:	if (xd[3]<=0) xd_iobase = 0x324; 
+				break;
 		case 0xD0000:				/*5150CX*/
-		case 0xD8000:	break;			/*5150CX*/
+		case 0xD8000:	break;			/*5150CX & 5150XL*/
 		default:        printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
 				break;
 	}
diff -u --recursive --new-file v2.1.92/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.92/linux/drivers/char/Makefile	Mon Jan 12 14:46:16 1998
+++ linux/drivers/char/Makefile	Sat Apr  4 09:45:13 1998
@@ -20,7 +20,8 @@
 
 L_TARGET := char.a
 M_OBJS   :=
-L_OBJS   := tty_io.o n_tty.o tty_ioctl.o pty.o mem.o random.o
+L_OBJS   := tty_io.o n_tty.o tty_ioctl.o mem.o random.o
+LX_OBJS  := pty.o
 
 ifdef CONFIG_VT
 L_OBJS += console.o vt.o vc_screen.o consolemap.o consolemap_deftbl.o
diff -u --recursive --new-file v2.1.92/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.1.92/linux/drivers/char/cyclades.c	Thu Dec  4 13:09:01 1997
+++ linux/drivers/char/cyclades.c	Thu Apr  2 09:12:23 1998
@@ -525,7 +525,6 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 
 #include <linux/version.h>
@@ -4391,7 +4390,7 @@
 cy_detect_pci(void))
 {
 #ifdef CONFIG_PCI
-  unsigned char         cyy_bus, cyy_dev_fn, cyy_rev_id;
+  unsigned char         cyy_rev_id;
   unsigned long         pci_intr_ctrl;
   unsigned char         cy_pci_irq;
   uclong                cy_pci_addr0, cy_pci_addr1, cy_pci_addr2;
@@ -4399,20 +4398,17 @@
   unsigned short        device_id,dev_index = 0,board_index = 0;
   uclong		mailbox;
   uclong		Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
+  struct pci_dev	*pdev = NULL;
 
-        if(pcibios_present() == 0) {    /* PCI bus not present */
+        if(pci_present() == 0) {    /* PCI bus not present */
                 return(0);
         }
         for (i = 0; i < NR_CARDS; i++) {
                 /* look for a Cyclades card by vendor and device id */
                 while((device_id = cy_pci_dev_id[dev_index]) != 0) {
-                        if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES,
-                                        device_id,board_index,
-                                        &cyy_bus, &cyy_dev_fn) != 0)
-                        {
+			if ((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES, device_id, pdev)) == NULL)
                                 dev_index++;    /* try next device id */
-                                board_index = 0;
-                        } else {
+                        else {
                                 board_index++;
                                 break;          /* found a board */
                         }
@@ -4422,37 +4418,29 @@
 		    break;
 
                 /* read PCI configuration area */
-                pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
-                                 PCI_INTERRUPT_LINE, &cy_pci_irq);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_0, 
-				  (unsigned int *) &cy_pci_addr0);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_1, 
-				  (unsigned int *) &cy_pci_addr1);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_2, 
-				  (unsigned int *) &cy_pci_addr2);
-                pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
-                                  PCI_REVISION_ID, &cyy_rev_id);
+		cy_pci_irq = pdev->irq;
+		cy_pci_addr0 = pdev->base_address[0];
+		cy_pci_addr1 = pdev->base_address[1];
+		cy_pci_addr2 = pdev->base_address[2];
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
 
     if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
 	   || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
 #ifdef CY_PCI_DEBUG
             printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-		cyy_bus, cyy_dev_fn);
+		pdev->bus->number, pdev->devfn);
             printk("rev_id=%d) IRQ%d\n",
 		cyy_rev_id, (int)cy_pci_irq);
             printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
 		(ulong)cy_pci_addr2, (ulong)cy_pci_addr1);
 #endif
-                cy_pci_addr1  &= 0xfffffffc;
-                cy_pci_addr2  &= 0xfffffff0;
+                cy_pci_addr1  &= PCI_BASE_ADDRESS_IO_MASK;
+                cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
 
 #if defined(__alpha__)
                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
 		    printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-		        cyy_bus, cyy_dev_fn);
+		        pdev->bus->number, pdev->devfn);
 		    printk("rev_id=%d) IRQ%d\n",
 		        cyy_rev_id, (int)cy_pci_irq);
                     printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
@@ -4537,7 +4525,7 @@
     }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){
 	    /* print message */
 		printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-		    cyy_bus, cyy_dev_fn);
+		    pdev->bus->number, pdev->devfn);
 		printk("rev_id=%d) IRQ%d\n",
 		    cyy_rev_id, (int)cy_pci_irq);
 		printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
@@ -4547,13 +4535,13 @@
     }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){
 #ifdef CY_PCI_DEBUG
             printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-		cyy_bus, cyy_dev_fn);
+		pdev->bus->number, pdev->devfn);
             printk("rev_id=%d) IRQ%d\n",
 		cyy_rev_id, (int)cy_pci_irq);
             printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
                 (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
 #endif
-                cy_pci_addr0 &= 0xfffffff0;
+                cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
 #if !defined(__alpha__)
                 cy_pci_addr0 = (unsigned int) ioremap(
                                cy_pci_addr0 & PAGE_MASK,
@@ -4562,7 +4550,7 @@
 #endif
 		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
 			   cy_pci_addr0)->mail_box_0);
-                cy_pci_addr2 &= 0xfffffff0;
+                cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
 		if (mailbox == ZE_V1) {
 #if !defined(__alpha__)
                	    cy_pci_addr2 = (unsigned int) ioremap(
diff -u --recursive --new-file v2.1.92/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.1.92/linux/drivers/char/epca.c	Tue Mar 10 10:03:31 1998
+++ linux/drivers/char/epca.c	Thu Apr  2 09:12:23 1998
@@ -106,7 +106,6 @@
 
 
 #ifdef ENABLE_PCI
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/digiPCI.h>
 #endif /* ENABLE_PCI */
@@ -1747,7 +1746,7 @@
 	--------------------------------------------------------------------- */
   
 	pci_boards_found = 0;
-	if (pcibios_present())
+	if (pci_present())
 	{
 		if(num_cards < MAXBOARDS)
 			pci_boards_found += init_PCI(num_cards);
@@ -4039,31 +4038,23 @@
 #ifdef ENABLE_PCI
 /* --------------------- Begin get_PCI_configuration  ---------------------- */
 
-int get_PCI_configuration(char bus, char device_fn, 
+int get_PCI_configuration(char bus, char device_fn,
                           unsigned int *base_addr0, unsigned int *base_addr1,
                           unsigned int *base_addr2, unsigned int *base_addr3,
                           unsigned int *base_addr4, unsigned int *base_addr5)
 { /* Begin get_PCI_configuration */
 
-	int	error;
+	struct	pci_dev *dev = pci_find_slot(bus, device_fn);
 
-	error = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,
-	                                  base_addr0);
-
-	error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1,
-                                      base_addr1);
-
-	error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2,
-                                      base_addr2);
-
-	error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_3,
-                                      base_addr3);
-
-	error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_4,
-                                      base_addr4);
+	if (!dev)
+		return(0);
 
-	error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_5,
-                                      base_addr5);
+	*base_addr0 = dev->base_address[0];
+	*base_addr1 = dev->base_address[1];
+	*base_addr2 = dev->base_address[2];
+	*base_addr3 = dev->base_address[3];
+	*base_addr4 = dev->base_address[4];
+	*base_addr5 = dev->base_address[5];
 
 	/* ------------------------------------------------------------------------
 			 NOTE - The code below mask out either the 2 or 4 bits dependent on the
@@ -4103,11 +4094,6 @@
 	else
 		(*base_addr5) &= PCI_BASE_ADDRESS_MEM_MASK;
 
-	if (error) 
-	{
-		printk(KERN_ERR "<Error> - DIGI PCI error: board not initializing due to error\n");
-		return(0);
-	}
 	return(1);
 } /* End get_PCI_configuration */
 
@@ -4311,5 +4297,3 @@
 } /* End init_PCI */
 
 #endif /* ENABLE_PCI */
-
-
diff -u --recursive --new-file v2.1.92/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.1.92/linux/drivers/char/pc_keyb.c	Wed Apr  1 20:11:49 1998
+++ linux/drivers/char/pc_keyb.c	Wed Apr  1 20:20:03 1998
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/irq.h>
 
 /* Some configuration switches are present in the include file... */
 
@@ -48,12 +49,17 @@
  * them.
  */
 
-#ifndef __i386__
-#define INIT_KBD
+/*
+ * Some x86 BIOSes do not correctly initializes the keyboard, so the
+ * "kbd-reset" command line options can be given to force a reset.
+ * [Ranger]
+ */
+#ifdef __i386__
+ int kbd_startup_reset __initdata = 0;
+#else
+ int kbd_startup_reset __initdata = 1;
 #endif
 
-#ifdef INIT_KBD
-
 __initfunc(static int kbd_wait_for_input(void))
 {
 	int     status, data;
@@ -202,7 +208,7 @@
 		printk(KERN_WARNING "initialize_kbd: %s\n", msg);
 }
 
-#endif /* INIT_KBD */
+
 
 unsigned char kbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */
 
@@ -602,7 +608,11 @@
 {
 	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
 	request_region(0x60, 16, "keyboard");
-#ifdef INIT_KBD
-	initialize_kbd();
-#endif
+	if (kbd_startup_reset) initialize_kbd();
+}
+
+/* for "kbd-reset" cmdline param */
+__initfunc(void kbd_reset_setup(char *str, int *ints))
+{
+	kbd_startup_reset = 1;
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.1.92/linux/drivers/char/pty.c	Tue Feb 17 13:12:46 1998
+++ linux/drivers/char/pty.c	Sat Apr  4 09:45:13 1998
@@ -7,6 +7,9 @@
  *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
  */
 
+#include <linux/config.h>
+#include <linux/module.h>	/* For EXPORT_SYMBOL */
+
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -22,6 +25,9 @@
 #include <asm/system.h>
 #include <asm/bitops.h>
 
+#define BUILDING_PTY_C 1
+#include <linux/devpts_fs.h>
+
 struct pty_struct {
 	int	magic;
 	struct wait_queue * open_wait;
@@ -66,6 +72,7 @@
 	if (tty->driver.subtype == PTY_TYPE_MASTER) {
 		tty_hangup(tty->link);
 		set_bit(TTY_OTHER_CLOSED, &tty->flags);
+		devpts_pty_kill(MINOR(tty->device) - tty->driver.minor_start);
 	}
 }
 
@@ -363,6 +370,5 @@
 		panic("Couldn't register compat pty driver");
 	if (tty_register_driver(&old_pty_slave_driver))
 		panic("Couldn't register compat pty slave driver");
-	
 	return 0;
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/char/rocket.c linux/drivers/char/rocket.c
--- v2.1.92/linux/drivers/char/rocket.c	Mon Feb 23 18:12:04 1998
+++ linux/drivers/char/rocket.c	Thu Apr  2 09:12:23 1998
@@ -80,7 +80,6 @@
 #include <linux/major.h>
 #include <linux/ioport.h>
 #ifdef ENABLE_PCI
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #endif
 #if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
@@ -1875,31 +1874,10 @@
 	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
 	char *str;
 	CONTROLLER_t	*ctlp;
-	unsigned short	vendor_id, device_id;
-	int	ret, error;
-	unsigned int port;
-
-	error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,
-		&vendor_id);
-	ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,
-		&device_id);
-	if (error == 0)
-		error = ret;
-	ret = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,
-		&port);
-	rcktpt_io_addr[i] = (unsigned long) port;
-	if (error == 0)
-		error = ret;
-
-	if (error) {
-		printk("PCI RocketPort error: %s not initializing due to error"
-		       "reading configuration space\n",
-		       pcibios_strerror(error));
-		return(0);
-	}
+	struct pci_dev *dev = pci_find_slot(bus, device_fn);
 
-	--rcktpt_io_addr[i];
-	switch(device_id) {
+	rcktpt_io_addr[i] = dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+	switch(dev->device) {
 	case PCI_DEVICE_ID_RP4QUAD:
 		str = "Quadcable";
 		max_num_aiops = 1;
@@ -1935,7 +1913,7 @@
 	num_aiops = sPCIInitController(ctlp, i,
 					aiopio, max_num_aiops, 0,
 					FREQ_DIS, 0);
-	printk("Rocketport controller #%d found at %d:%d, "
+	printk("Rocketport controller #%d found at %02x:%02x, "
 	       "%d AIOP(s) (PCI Rocketport %s)\n", i, bus, device_fn,
 	       num_aiops, str);
 	if(num_aiops <= 0) {
@@ -2095,7 +2073,7 @@
 			isa_boards_found++;
 	}
 #ifdef ENABLE_PCI
-	if (pcibios_present()) {
+	if (pci_present()) {
 		if(isa_boards_found < NUM_BOARDS)
 			pci_boards_found = init_PCI(isa_boards_found);
 	} else {
diff -u --recursive --new-file v2.1.92/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.92/linux/drivers/char/stallion.c	Thu Mar 26 15:57:03 1998
+++ linux/drivers/char/stallion.c	Thu Apr  2 09:12:23 1998
@@ -52,7 +52,6 @@
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #endif
 
 /*****************************************************************************/
@@ -466,7 +465,7 @@
 
 #ifdef	CONFIG_PCI
 static inline int	stl_findpcibrds(void);
-static inline int	stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char devnr);
+static inline int	stl_initpcibrd(int brdtype, struct pci_dev *dev);
 #endif
 
 /*
@@ -2530,16 +2529,16 @@
  *	configuration space.
  */
 
-static inline int stl_initpcibrd(int brdtype, unsigned char busnr, unsigned char devnr)
+static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev)
 {
 	unsigned int	bar[4];
 	stlbrd_t	*brdp;
-	int		i, rc;
+	int		i;
 	unsigned char	irq;
 
 #if DEBUG
 	printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n",
-		brdtype, busnr, devnr);
+		brdtype, dev->bus->number, dev->devfn);
 #endif
 
 	brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
@@ -2559,22 +2558,9 @@
  *	boards use these in different ways, so we just read in the whole
  *	lot and then figure out what is what later.
  */
-	for (i = 0; (i < 4); i++) {
-		rc = pcibios_read_config_dword(busnr, devnr,
-			(PCI_BASE_ADDRESS_0 + (i * 0x4)), &bar[i]);
-		if (rc) {
-			printk("STALLION: failed to read BAR register %d "
-				"from PCI board, errno=%x\n", i, rc);
-			return(0);
-		}
-	}
-
-	rc = pcibios_read_config_byte(busnr, devnr, PCI_INTERRUPT_LINE, &irq);
-	if (rc) {
-		printk("STALLION: failed to read INTERRUPT register "
-			"from PCI board, errno=%x\n", rc);
-		return(0);
-	}
+	for (i = 0; (i < 4); i++)
+		bar[i] = dev->base_address[i];
+	irq = dev->irq;
 
 #if DEBUG
 	printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__,
@@ -2620,24 +2606,18 @@
 
 static inline int stl_findpcibrds()
 {
-	unsigned char	busnr, devnr;
-	unsigned short	class;
-	int		i, rc, brdtypnr;
+	struct pci_dev	*dev = NULL;
+	int		i, rc;
 
 #if DEBUG
 	printk("stl_findpcibrds()\n");
 #endif
 
-	if (! pcibios_present())
+	if (! pci_present())
 		return(0);
 
-	for (i = 0; (i < stl_nrpcibrds); i++) {
-		for (brdtypnr = 0; ; brdtypnr++) {
-
-			rc = pcibios_find_device(stl_pcibrds[i].vendid,
-				stl_pcibrds[i].devid, brdtypnr, &busnr, &devnr);
-			if (rc)
-				break;
+	for (i = 0; (i < stl_nrpcibrds); i++)
+		while ((dev = pci_find_device(stl_pcibrds[i].vendid, stl_pcibrds[i].devid, dev))) {
 
 /*
  *			Check that we can handle more boards...
@@ -2653,22 +2633,13 @@
  *			Found a device on the PCI bus that has our vendor and
  *			device ID. Need to check now that it is really us.
  */
-			rc = pcibios_read_config_word(busnr, devnr,
-				PCI_CLASS_DEVICE, &class);
-			if (rc) {
-				printk("STALLION: failed to read class type "
-					"from PCI board, errno=%x\n", rc);
-				continue;
-			}
-			if (class == PCI_CLASS_STORAGE_IDE)
+			if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
 				continue;
 
-			rc = stl_initpcibrd(stl_pcibrds[i].brdtype, busnr,
-				devnr);
+			rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
 			if (rc)
 				return(rc);
 		}
-	}
 
 	return(0);
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/char/tga.c linux/drivers/char/tga.c
--- v2.1.92/linux/drivers/char/tga.c	Sun Dec 21 17:02:16 1997
+++ linux/drivers/char/tga.c	Thu Apr  2 09:12:23 1998
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -137,7 +136,7 @@
 #define TGA_F_HEIGHT_PADDED 18
 
 int tga_type;
-unsigned int tga_mem_base;
+unsigned long tga_mem_base;
 unsigned long tga_fb_base;
 unsigned long tga_regs_base;
 unsigned int tga_bpp, tga_fb_width, tga_fb_height, tga_fb_stride;
@@ -472,15 +471,13 @@
 __initfunc(void
 tga_console_init(void))
 {
-	unsigned char pci_bus, pci_devfn;
+	struct pci_dev *dev;
 	int status;
 	
 	/*
 	 * first, find the TGA among the PCI devices...
 	 */
-	status = pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
-				      0, &pci_bus, &pci_devfn);
-	if (status == PCIBIOS_DEVICE_NOT_FOUND) {
+	if (! (dev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL)))
 		/* PANIC!!! */
 		printk("tga_console_init: TGA not found!!! :-(\n");
 		return;
@@ -489,14 +486,12 @@
 	/*
 	 * read BASE_REG_0 for memory address
 	 */
-	pcibios_read_config_dword(pci_bus, pci_devfn,
-				  PCI_BASE_ADDRESS_0, &tga_mem_base);
-	tga_mem_base &= ~15;
+	tga_mem_base = dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
 #ifdef DEBUG
-	printk("tga_console_init: mem_base 0x%x\n", tga_mem_base);
+	printk("tga_console_init: mem_base 0x%lx\n", tga_mem_base);
 #endif /* DEBUG */
 
-	tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f;
+	tga_type = (readl(tga_mem_base) >> 12) & 0x0f;
 	if (tga_type != 0 && tga_type != 1 && tga_type != 3) {
 	  printk("TGA type (0x%x) unrecognized!\n", tga_type);
 	  return;
@@ -561,9 +556,8 @@
 	int i, j, temp;
 	unsigned char *cbp;
 
-	tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET);
-	tga_fb_base =
-	  ((unsigned long)tga_mem_base + fb_offset_presets[tga_type]);
+	tga_regs_base = (tga_mem_base + TGA_REGS_OFFSET);
+	tga_fb_base = (tga_mem_base + fb_offset_presets[tga_type]);
 
 	/* first, disable video timing */
 	TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
diff -u --recursive --new-file v2.1.92/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.92/linux/drivers/char/tty_io.c	Wed Apr  1 20:11:49 1998
+++ linux/drivers/char/tty_io.c	Sat Apr  4 09:45:14 1998
@@ -66,6 +66,7 @@
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/devpts_fs.h>
 #include <linux/file.h>
 #include <linux/console.h>
 #include <linux/timer.h>
@@ -1209,7 +1210,7 @@
 	if (device == PTMX_DEV) {
 		/* find a free pty. */
 		struct tty_driver *driver = tty_drivers;
-		int minor;
+		int minor, line;
 
 		/* find the pty driver */
 		for (driver=tty_drivers; driver; driver=driver->next)
@@ -1229,6 +1230,8 @@
 			return -EIO; /* no free ptys */
 		
 		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+		line = minor - driver->minor_start;
+		devpts_pty_new(line, MKDEV(driver->other->major, line+driver->other->minor_start));
 		noctty = 1;
 		goto init_dev_done;
 	}
diff -u --recursive --new-file v2.1.92/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.1.92/linux/drivers/misc/parport_pc.c	Wed Apr  1 20:11:52 1998
+++ linux/drivers/misc/parport_pc.c	Sat Apr  4 09:16:49 1998
@@ -458,6 +458,7 @@
 static int parport_SPP_supported(struct parport *pb)
 {
 	/* Do a simple read-write test to make sure the port exists. */
+	parport_pc_write_econtrol(pb, 0xc);
 	parport_pc_write_control(pb, 0xc);
 	parport_pc_write_data(pb, 0xaa);
 	if (parport_pc_read_data(pb) != 0xaa) return 0;
@@ -894,6 +895,7 @@
 	p->flags |= PARPORT_FLAG_COMA;
 
 	/* Done probing.  Now put the port into a sensible start-up state. */
+	parport_pc_write_econtrol(p, 0xc);
 	parport_pc_write_control(p, 0xc);
 	parport_pc_write_data(p, 0);
 
diff -u --recursive --new-file v2.1.92/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.1.92/linux/drivers/net/3c59x.c	Thu Mar 26 15:57:03 1998
+++ linux/drivers/net/3c59x.c	Thu Apr  2 09:12:23 1998
@@ -65,7 +65,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/timer.h>
 #include <asm/irq.h>			/* For NR_IRQS only. */
 #include <asm/bitops.h>
@@ -113,6 +112,7 @@
 
 #if LINUX_VERSION_CODE < 0x20115
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #elif defined(MODULE)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
@@ -532,12 +532,18 @@
 	   be best done a central PCI probe dispatch, which wouldn't work
 	   well with the current structure.  So instead we detect 3Com cards
 	   in slot order. */
-	if (pcibios_present()) {
+	if (pci_present()) {
 		static int pci_index = 0;
 		unsigned char pci_bus, pci_device_fn;
 
 		for (;pci_index < 0xff; pci_index++) {
-			unsigned char pci_irq_line, pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+			unsigned int pci_irq_line;
+			struct pci_dev *pdev;
+#else
+			unsigned char pci_irq_line;
+#endif
+			unsigned char pci_latency;
 			unsigned short pci_command, new_command, vendor, device;
 			unsigned int pci_ioaddr;
 			int board_index = 0;
@@ -550,10 +556,16 @@
 									 PCI_VENDOR_ID, &vendor);
 			pcibios_read_config_word(pci_bus, pci_device_fn,
 									 PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[0];
+#else
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_INTERRUPT_LINE, &pci_irq_line);
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
 			pcibios_read_config_word(pci_bus, pci_device_fn,
 									 PCI_COMMAND, &pci_command);
 			/* Remove I/O space marker in bit 0. */
diff -u --recursive --new-file v2.1.92/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.1.92/linux/drivers/net/de4x5.c	Wed Apr  1 20:11:52 1998
+++ linux/drivers/net/de4x5.c	Thu Apr  2 09:12:23 1998
@@ -213,7 +213,7 @@
 
         insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
 
-    For a compiled in driver, at or above line 526, place e.g.
+    For a compiled in driver, somewhere in this file, place e.g.
 	#define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP"
 
     Yes,  I know full duplex  isn't permissible on BNC  or AUI; they're just
@@ -390,7 +390,6 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -929,7 +928,7 @@
 static int     get_hw_addr(struct device *dev);
 static void    srom_repair(struct device *dev, int card);
 static int     test_bad_enet(struct device *dev, int status);
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 static void    eisa_probe(struct device *dev, u_long iobase);
 #endif
 static void    pci_probe(struct device *dev, u_long iobase);
@@ -978,12 +977,15 @@
 #endif /* MODULE */
 
 static char name[DE4X5_NAME_LENGTH + 1];
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
 #endif
 static int num_de4x5s = 0;
 static int cfrv = 0, useSROM = 0;
-static int lastEISA = 0, lastPCI = -1;
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
+static int lastEISA = 0;
+#endif
+static int lastPCI = -1;
 static struct device *lastModule = NULL;
 
 /*
@@ -1048,7 +1050,7 @@
 {
     u_long iobase = dev->base_addr;
 
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
     eisa_probe(dev, iobase);
 #endif
     pci_probe(dev, iobase);
@@ -1094,14 +1096,14 @@
     
     dev->base_addr = iobase;
     if (lp->bus == EISA) {
-	printk("%s: %s at 0x%04lx (EISA slot %ld),\n", 
+	printk("%s: %s at 0x%04lx (EISA slot %ld)", 
 	       dev->name, name, iobase, ((iobase>>12)&0x0f));
     } else {                                 /* PCI port address */
-	printk("%s: %s at 0x%04lx (PCI bus %d, device %d),\n", dev->name, name,
+	printk("%s: %s at 0x%04lx (PCI bus %d, device %d)", dev->name, name,
 	       iobase, lp->bus_num, lp->device);
     }
     
-    printk("      h/w address ");
+    printk(", h/w address ");
     status = get_hw_addr(dev);
     for (i = 0; i < ETH_ALEN - 1; i++) {     /* get the ethernet addr. */
 	printk("%2.2x:", dev->dev_addr[i]);
@@ -1305,9 +1307,8 @@
     
     lp->state = OPEN;
     de4x5_dbg_open(dev);
-    
     if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, 
-		                                     lp->adapter_name, dev)) {
+	    lp->adapter_name, dev)) {
 	printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
 	if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ,
 			                             lp->adapter_name, dev)) {
@@ -1974,7 +1975,7 @@
     return;
 }
 
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 /*
 ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
 ** the motherboard. Upto 15 EISA devices are supported.
@@ -2063,15 +2064,14 @@
 pci_probe(struct device *dev, u_long ioaddr))
 {
     u_char pb, pbus, dev_num, dnum, dev_fn, timer;
-    u_short vendor, index, status;
+    u_short dev_id, vendor, index, status;
     u_int irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     struct bus_type *lp = &bus;
-    struct pci_dev *pdev;
 
     if (lastPCI == NO_MORE_PCI) return;
 
-    if (!pcibios_present()) {
+    if (!pci_present()) {
 	lastPCI = NO_MORE_PCI;
 	return;          /* No PCI bus in this machine! */
     }
@@ -2091,75 +2091,92 @@
 	 (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
 	 index++) {
 	dev_num = PCI_SLOT(dev_fn);
-	if ((pbus || dnum) && ((pbus != pb) || (dnum != dev_num))) continue;
-	pdev = pci_find_dev(pb, dev_fn);
+	if ((!pbus && !dnum) || ((pbus == pb) && (dnum == dev_num))) {
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
+	    struct pci_dev *pdev = pci_find_slot(pb, dev_fn);
+#else
+	    u_char tirq;
+	    u_int tmp;
+#endif
+	    device = 0;
+	    pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+	    pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+	    device = dev_id;
+	    device <<= 8;
+	    if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
+		continue;
+	    }
+
+	    /* Search for an SROM on this bus */
+	    if (lp->bus_num != pb) {
+		lp->bus_num = pb;
+		srom_search(index);
+	    }
 
-	vendor = pdev->vendor;
-	device = pdev->device << 8;
-	if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
+	    /* Get the chip configuration revision register */
+	    pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
 
-	/* Search for an SROM on this bus */
-	if (lp->bus_num != pb) {
+	    /* Set the device number information */
+	    lp->device = dev_num;
 	    lp->bus_num = pb;
-	    srom_search(index);
-	}
-
-	/* Get the chip configuration revision register */
-	pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
-
-	/* Set the device number information */
-	lp->device = dev_num;
-	lp->bus_num = pb;
 	    
-	/* Set the chipset information */
-	if (is_DC2114x) device |= (cfrv & CFRV_RN);
-	lp->chipset = device;
+	    /* Set the chipset information */
+	    if (is_DC2114x) device |= (cfrv & CFRV_RN);
+	    lp->chipset = device;
 
-	/* Get the board I/O address (64 bits on sparc64) */
-	iobase = pdev->base_address[0] & CBIO_MASK;
+	    /* Get the board I/O address and IRQ */
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,85)
+	    pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+	    iobase = tmp;
+	    pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+	    irq = tirq;
+#else
+	    iobase = pdev->base_address[0];
+	    irq = pdev->irq;
+#endif
+	    iobase &= CBIO_MASK;
 
-	/* Fetch the IRQ to be used */
-	irq = pdev->irq;
-	if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
-	    
-	/* Check if I/O accesses and Bus Mastering are enabled */
-	pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-#ifdef __powerpc__
-	if (!(status & PCI_COMMAND_IO)) {
-	    status |= PCI_COMMAND_IO;
-	    pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+	    if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
+
+	    /* Check if I/O accesses and Bus Mastering are enabled */
 	    pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-	}
+#ifdef __powerpc__
+	    if (!(status & PCI_COMMAND_IO)) {
+		status |= PCI_COMMAND_IO;
+		pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+		pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+	    }
 #endif /* __powerpc__ */
-	if (!(status & PCI_COMMAND_IO)) continue;
+	    if (!(status & PCI_COMMAND_IO)) continue;
 
-	if (!(status & PCI_COMMAND_MASTER)) {
-	    status |= PCI_COMMAND_MASTER;
-	    pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
-	    pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-	}
-	if (!(status & PCI_COMMAND_MASTER)) continue;
+	    if (!(status & PCI_COMMAND_MASTER)) {
+		status |= PCI_COMMAND_MASTER;
+		pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+		pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+	    }
+	    if (!(status & PCI_COMMAND_MASTER)) continue;
 
-	/* Check the latency timer for values >= 0x60 */
-	pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
-	if (timer < 0x60) {
-	    pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
-	}
+	    /* Check the latency timer for values >= 0x60 */
+	    pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
+	    if (timer < 0x60) {
+		pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
+	    }
 
-	DevicePresent(DE4X5_APROM);
-	if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
-	    dev->irq = irq;
-	    if ((status = de4x5_hw_init(dev, iobase)) == 0) {
-		num_de4x5s++;
-		if (loading_module) {
-		    link_modules(lastModule, dev);
-		    lastPCI = index;
+	    DevicePresent(DE4X5_APROM);
+	    if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
+		dev->irq = irq;
+		if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+		    num_de4x5s++;
+		    if (loading_module) {
+			link_modules(lastModule, dev);
+			lastPCI = index;
+		    }
+		    return;
 		}
-		return;
+	    } else if (ioaddr != 0) {
+		printk("%s: region already allocated at 0x%04lx.\n", dev->name,
+		       iobase);
 	    }
-	} else if (ioaddr != 0) {
-	    printk("%s: region already allocated at 0x%04lx.\n", dev->name,
-		   iobase);
 	}
     }
 
@@ -2178,24 +2195,35 @@
 srom_search(int index))
 {
     u_char pb, dev_fn;
-    u_short dev_num, vendor, status;
+    u_short dev_id, dev_num, vendor, status;
     u_int irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     int i, j;
     struct bus_type *lp = &bus;
-    struct pci_dev *pdev;
+#ifndef __sparc_v9__
+    u_char tirq;
+    u_int tmp;
+#endif
 
     for (; 
 	 (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
 	 index++) {
-
+#ifdef __sparc_v9__
+	struct pci_dev *pdev;
+	for (pdev = pci_devices; pdev; pdev = pdev->next) {
+	    if ((pdev->bus->number == pb) && (pdev->devfn == dev_fn)) break;
+	}
+#endif
 	if (lp->bus_num != pb) return;
 	dev_num = PCI_SLOT(dev_fn);
-	pdev = pci_find_dev(pb, dev_fn);
-
-	vendor = pdev->vendor;
-	device = pdev->device << 8;
-	if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
+	device = 0;
+	pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+	pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+	device = dev_id;
+	device <<= 8;
+	if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
+	    continue;
+	}
 
 	/* Get the chip configuration revision register */
 	pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
@@ -2209,10 +2237,21 @@
 	lp->chipset = device;
 
 	/* Get the board I/O address (64 bits on sparc64) */
-	iobase = pdev->base_address[0] & CBIO_MASK;
+#ifndef __sparc_v9__
+	pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+	iobase = tmp;
+#else
+	iobase = pdev->base_address[0];
+#endif
+	iobase &= CBIO_MASK;
 
 	/* Fetch the IRQ to be used */
+#ifndef __sparc_v9__
+	pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+	irq = tirq;
+#else
 	irq = pdev->irq;
+#endif
 	if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
 	    
 	/* Check if I/O accesses are enabled */
@@ -4053,6 +4092,19 @@
     /* If possible, try to fix a broken card - SMC only so far */
     srom_repair(dev, broken);
 
+#ifdef CONFIG_PMAC
+    /* If the address starts with 00 a0, we have to bit-reverse
+       each byte of the address. */
+    if (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0xa0) {
+	for (i = 0; i < ETH_ALEN; ++i) {
+	    int x = dev->dev_addr[i];
+	    x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
+	    x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
+	    dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
+	}
+    }
+#endif /* CONFIG_PMAC */
+
     /* Test for a bad enet address */
     status = test_bad_enet(dev, status);
 
@@ -5713,29 +5765,30 @@
 static int
 count_adapters(void)
 {
-    int i, j=0;
+    int i, j;
     char name[DE4X5_STRLEN];
-    u_char pb, dev_fn;
-    u_short vendor;
+    u_char pb, dev_fn, dev_num;
+    u_short dev_id, vendor;
     u_int class = DE4X5_CLASS_CODE;
     u_int device;
-    struct pci_dev *pdev;
-
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
     u_long iobase = 0x1000;
 
-    for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
+    for (j=0, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
 	if (EISA_signature(name, EISA_ID)) j++;
     }
 #endif
-    if (!pcibios_present()) return j;
+    if (!pci_present()) return j;
 
     for (i=0; 
 	 (pcibios_find_class(class, i, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
 	 i++) {
-	pdev = pci_find_dev(pb, dev_fn);
-	vendor = pdev->vendor;
-	device = pdev->device << 8;
+	dev_num = PCI_SLOT(dev_fn);
+	device = 0;
+	pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+	pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+	device = dev_id;
+	device <<= 8;
 	if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++;
     }
 
diff -u --recursive --new-file v2.1.92/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.1.92/linux/drivers/net/defxx.c	Thu Feb 12 20:56:08 1998
+++ linux/drivers/net/defxx.c	Thu Apr  2 09:12:23 1998
@@ -213,7 +213,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <asm/byteorder.h>
@@ -455,9 +454,8 @@
 	int				i;				/* used in for loops */
 	int				version_disp;	/* was version info string already displayed? */
 	int				port_len;		/* length of port address range (in bytes) */
-	u8				pci_bus;		/* PCI bus number (0-255) */
-	u8				pci_dev_fun;	/* PCI device and function numbers (0-255) */
 	u16				port;			/* temporary I/O (port) address */
+	struct pci_dev *		pdev = NULL;		/* PCI device record */
 	u16				command;		/* PCI Configuration space Command register val */
 	u32				slot_id;		/* EISA hardware (slot) ID read from adapter */
 	DFX_board_t		*bp;			/* board pointer */
@@ -530,61 +528,58 @@
 
 	/* Scan for FDDI PCI controllers */
 
-	if (pcibios_present())						/* is PCI BIOS even present? */
-		for (i=0; i < DFX_MAX_NUM_BOARDS; i++)	/* scan for up to 8 PCI cards */
-			if (pcibios_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, i, &pci_bus, &pci_dev_fun) == 0)
+	if (pci_present())						/* is PCI even present? */
+		while ((pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, pdev)))
+			{
+			if (!version_disp)					/* display version info if adapter is found */
 				{
-				if (!version_disp)					/* display version info if adapter is found */
-					{
-					version_disp = 1;				/* set display flag to TRUE so that */
-					printk(version);				/* we only display this string ONCE */
-					}
+				version_disp = 1;				/* set display flag to TRUE so that */
+				printk(version);				/* we only display this string ONCE */
+				}
 
-				/* Verify that I/O enable bit is set (PCI slot is enabled) */
+			/* Verify that I/O enable bit is set (PCI slot is enabled) */
 
-				pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, &command);
-				if ((command & PCI_COMMAND_IO) == 0)
-					printk("I/O enable bit not set!  Verify that slot is enabled\n");
-				else
-					{
-					/* Turn off memory mapped space and enable mastering */
+			pci_read_config_word(pdev, PCI_COMMAND, &command);
+			if ((command & PCI_COMMAND_IO) == 0)
+				printk("I/O enable bit not set!  Verify that slot is enabled\n");
+			else
+				{
+				/* Turn off memory mapped space and enable mastering */
 
-					command |= PCI_COMMAND_MASTER;
-					command &= ~PCI_COMMAND_MEMORY;
-					pcibios_write_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, command);
+				command |= PCI_COMMAND_MASTER;
+				command &= ~PCI_COMMAND_MEMORY;
+				pci_write_config_word(pdev, PCI_COMMAND, command);
 
-					/* Read I/O base address from PCI Configuration Space */
-				
-					pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_BASE_ADDRESS_1, &port);
-					port &= PCI_BASE_ADDRESS_IO_MASK;		/* clear I/O bit (bit 0) */
+				/* Get I/O base address from PCI Configuration Space */
+
+				port = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
 
-					/* Verify port address range is not already being used */
+				/* Verify port address range is not already being used */
+
+				port_len = PFI_K_CSR_IO_LEN;
+				if (check_region(port, port_len) == 0)
+					{
+					/* Allocate a new device structure for this adapter */
 
-					port_len = PFI_K_CSR_IO_LEN;
-					if (check_region(port, port_len) == 0)
+					dev = dfx_alloc_device(dev, port);
+					if (dev != NULL)
 						{
-						/* Allocate a new device structure for this adapter */
+						/* Initialize board structure with bus-specific info */
 
-						dev = dfx_alloc_device(dev, port);
-						if (dev != NULL)
-							{
-							/* Initialize board structure with bus-specific info */
-
-							bp = (DFX_board_t *) dev->priv;
-							bp->dev = dev;
-							bp->bus_type = DFX_BUS_TYPE_PCI;
-							bp->pci_bus = pci_bus;
-							bp->pci_dev_fun = pci_dev_fun;
-							if (dfx_driver_init(dev) == DFX_K_SUCCESS)
-								num_boards++;		/* only increment global board count on success */
-							else
-								dev->base_addr = 0;	/* clear port address field in device structure on failure */
-							}
+						bp = (DFX_board_t *) dev->priv;
+						bp->dev = dev;
+						bp->bus_type = DFX_BUS_TYPE_PCI;
+						bp->pci_dev = pdev;
+						if (dfx_driver_init(dev) == DFX_K_SUCCESS)
+							num_boards++;		/* only increment global board count on success */
+						else
+							dev->base_addr = 0;	/* clear port address field in device structure on failure */
 						}
-					else
-						printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
 					}
+				else
+					printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
 				}
+			}
 
 	/*
 	 * If we're at this point we're going through dfx_probe() for the first
@@ -823,18 +818,19 @@
 		}
 	else
 		{
+		struct pci_dev *pdev = bp->pci_dev;
+
 		/* Get the interrupt level from the PCI Configuration Table */
 
-		pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_INTERRUPT_LINE, &val);
-		dev->irq = val;					/* save IRQ value in device table */
+		dev->irq = pdev->irq;
 
 		/* Check Latency Timer and set if less than minimal */
 
-		pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, &val);
+		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
 		if (val < PFI_K_LAT_TIMER_MIN)	/* if less than min, override with default */
 			{
 			val = PFI_K_LAT_TIMER_DEF;
-			pcibios_write_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, val);
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
 			}
 
 		/* Enable interrupts at PCI bus interface chip (PFI) */
diff -u --recursive --new-file v2.1.92/linux/drivers/net/defxx.h linux/drivers/net/defxx.h
--- v2.1.92/linux/drivers/net/defxx.h	Mon Nov 18 01:31:31 1996
+++ linux/drivers/net/defxx.h	Thu Apr  2 09:12:23 1998
@@ -1754,8 +1754,7 @@
 	struct device			*dev;							/* pointer to device structure */
 	u32						bus_type;						/* bus type (0 == PCI, 1 == EISA) */
 	u16						base_addr;						/* base I/O address (same as dev->base_addr) */
-	u8						pci_bus;						/* PCI bus number */
-	u8						pci_dev_fun;					/* PCI device and function numbers */
+	struct pci_dev *				pci_dev;
 	u32						full_duplex_enb;				/* FDDI Full Duplex enable (1 == on, 2 == off) */
 	u32						req_ttrt;						/* requested TTRT value (in 80ns units) */
 	u32						burst_size;						/* adapter burst size (enumerated) */
diff -u --recursive --new-file v2.1.92/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.1.92/linux/drivers/net/dgrs.c	Tue Mar 10 10:03:32 1998
+++ linux/drivers/net/dgrs.c	Thu Apr  2 09:12:23 1998
@@ -87,7 +87,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -109,6 +108,7 @@
 	#define COPY_FROM_USER(DST,SRC,LEN)	copy_from_user(DST,SRC,LEN)
 	#define COPY_TO_USER(DST,SRC,LEN)	copy_to_user(DST,SRC,LEN)
 #else
+	#include <linux/bios32.h>
 	#define IOREMAP(ADDR, LEN)		vremap(ADDR, LEN)
 	#define IOUNMAP(ADDR)			vfree(ADDR)
 	#define COPY_FROM_USER(DST,SRC,LEN)	memcpy_fromfs(DST,SRC,LEN)
@@ -1373,14 +1373,19 @@
 	/*
 	 *	First, check for PCI boards
 	 */
-	if (pcibios_present())
+	if (pci_present())
 	{
 		int pci_index = 0;
 
 		for (; pci_index < 8; pci_index++)
 		{
 			uchar	pci_bus, pci_device_fn;
+#if LINUX_VERSION_CODE < 0x20100
 			uchar	pci_irq;
+#else
+			uint	pci_irq;
+			struct pci_dev *pdev;
+#endif
 			uchar	pci_latency;
 			ushort	pci_command;
 
@@ -1390,6 +1395,7 @@
 							&pci_device_fn))
 					break;
 
+#if LINUX_VERSION_CODE < 0x20100
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 					PCI_INTERRUPT_LINE, &pci_irq);
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
@@ -1398,6 +1404,13 @@
 					PCI_BASE_ADDRESS_1, &io);
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 					PCI_BASE_ADDRESS_2, &mem);
+#else
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq = pdev->irq;
+			plxreg = pdev->base_address[0];
+			io = pdev->base_address[1];
+			mem = pdev->base_address[2];
+#endif
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 					0x30, &plxdma);
 			irq = pci_irq;
diff -u --recursive --new-file v2.1.92/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.1.92/linux/drivers/net/eepro100.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/net/eepro100.c	Thu Apr  2 09:12:23 1998
@@ -59,7 +59,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -120,6 +119,7 @@
 
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #endif
 
 /* The total I/O port extent of the board.  Nominally 0x18, but rounded up
@@ -473,10 +473,16 @@
 {
 	int cards_found = 0;
 
-	if (pcibios_present()) {
+	if (pci_present()) {
 		static int pci_index = 0;
 		for (; pci_index < 8; pci_index++) {
-			unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency;
+			unsigned char pci_bus, pci_device_fn, pci_latency;
+#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
+			unsigned int pci_irq_line;
+			struct pci_dev *pdev;
+#else
+			unsigned char pci_irq_line;
+#endif
 #if (LINUX_VERSION_CODE >= VERSION(1,3,44))
 			int pci_ioaddr;
 #else
@@ -489,11 +495,17 @@
 									pci_index, &pci_bus,
 									&pci_device_fn))
 			  break;
+#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[1];
+#else
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_INTERRUPT_LINE, &pci_irq_line);
 			/* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 									  PCI_BASE_ADDRESS_1, &pci_ioaddr);
+#endif
 			/* Remove I/O space marker in bit 0. */
 			pci_ioaddr &= ~3;
 			if (speedo_debug > 2)
diff -u --recursive --new-file v2.1.92/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.1.92/linux/drivers/net/hp100.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/net/hp100.c	Thu Apr  2 09:12:24 1998
@@ -83,7 +83,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -331,6 +330,9 @@
   int ioaddr = 0;
 #ifdef CONFIG_PCI
   int pci_start_index = 0;
+#ifdef LINUX_2_1
+  struct pci_dev *pdev;
+#endif
 #endif
 
 #ifdef HP100_DEBUG_B
@@ -363,7 +365,7 @@
   /* at first - scan PCI bus(es) */
 
 #ifdef CONFIG_PCI
-  if ( pcibios_present() )
+  if ( pci_present() )
     {
       int pci_index;
 
@@ -384,8 +386,14 @@
           break;
 
 	  __pci_found:
+
+#ifdef LINUX_2_1
+	  pdev = pci_find_slot(pci_bus, pci_device_fn);
+	  ioaddr = pdev->base_address[0];
+#else
           pcibios_read_config_dword( pci_bus, pci_device_fn,
                                      PCI_BASE_ADDRESS_0, &ioaddr );
+#endif
 
           ioaddr &= ~3;    /* remove I/O space marker in bit 0. */
 
diff -u --recursive --new-file v2.1.92/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v2.1.92/linux/drivers/net/lance.c	Thu Feb 12 20:56:08 1998
+++ linux/drivers/net/lance.c	Thu Apr  2 09:12:24 1998
@@ -45,7 +45,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -285,7 +284,7 @@
 enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6};
 
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned char pci_irq_line = 0;
+static unsigned int pci_irq_line = 0;
 
 /* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers.
    Assume yes until we know the memory size. */
@@ -317,36 +316,26 @@
 		lance_need_isa_bounce_buffers = 0;
 
 #if defined(CONFIG_PCI) && !defined(CONFIG_PCNET32)
-    if (pcibios_present()) {
-	    int pci_index;
+    if (pci_present()) {
+	    struct pci_dev *pdev = NULL;
 		if (lance_debug > 1)
-			printk("lance.c: PCI bios is present, checking for devices...\n");
-		for (pci_index = 0; pci_index < 8; pci_index++) {
+			printk("lance.c: PCI is present, checking for devices...\n");
+		while (pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev)) {
 			unsigned char pci_bus, pci_device_fn;
 			unsigned int pci_ioaddr;
 			unsigned short pci_command;
 
-			if (pcibios_find_device (PCI_VENDOR_ID_AMD,
-									 PCI_DEVICE_ID_AMD_LANCE, pci_index,
-									 &pci_bus, &pci_device_fn) != 0)
-				break;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_INTERRUPT_LINE, &pci_irq_line);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-			/* Remove I/O space marker in bit 0. */
-			pci_ioaddr &= ~3;
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 			/* PCI Spec 2.1 states that it is either the driver or PCI card's
 	 		 * responsibility to set the PCI Master Enable Bit if needed.
 			 *	(From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
 			 */
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_COMMAND, &pci_command);
+			pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 			if ( ! (pci_command & PCI_COMMAND_MASTER)) {
 				printk("PCI Master Bit has not been set. Setting...\n");
 				pci_command |= PCI_COMMAND_MASTER;
-				pcibios_write_config_word(pci_bus, pci_device_fn,
-										  PCI_COMMAND, pci_command);
+				pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 			}
 			printk("Found PCnet/PCI at %#x, irq %d.\n",
 				   pci_ioaddr, pci_irq_line);
diff -u --recursive --new-file v2.1.92/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.1.92/linux/drivers/net/ne.c	Mon Feb 23 18:12:05 1998
+++ linux/drivers/net/ne.c	Thu Apr  2 09:12:24 1998
@@ -40,7 +40,6 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/system.h>
@@ -117,7 +116,7 @@
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned char pci_irq_line = 0;
+static unsigned int pci_irq_line = 0;
 
 int ne_probe(struct device *dev);
 static int ne_probe1(struct device *dev, int ioaddr);
@@ -182,7 +181,7 @@
 
 #ifdef CONFIG_PCI
     /* Then look for any installed PCI clones */
-    if (pcibios_present() && (ne_probe_pci(dev) == 0))
+    if (pci_present() && (ne_probe_pci(dev) == 0))
 	return 0;
 #endif
 
@@ -207,27 +206,19 @@
 	int i;
 
 	for (i = 0; pci_clone_list[i].vendor != 0; i++) {
-		unsigned char pci_bus, pci_device_fn;
+		struct pci_dev *pdev = NULL;
 		unsigned int pci_ioaddr;
-		int pci_index;
 
-		for (pci_index = 0; pci_index < 8; pci_index++) {
-			if (pcibios_find_device (pci_clone_list[i].vendor,
-					pci_clone_list[i].dev_id, pci_index,
-					&pci_bus, &pci_device_fn) != 0)
-				break;	/* No more of these type of cards */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_0, &pci_ioaddr);
-			/* Strip the I/O address out of the returned value */
-			pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+		while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) {
+			pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 			/* Avoid already found cards from previous calls */
 			if (check_region(pci_ioaddr, NE_IO_EXTENT))
 				continue;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-					PCI_INTERRUPT_LINE, &pci_irq_line);
-			break;	/* Beauty -- got a valid card. */
+			pci_irq_line = pdev->irq;
+			if (pci_irq_line == 0) continue;	/* Try next PCI ID */
 		}
-		if (pci_irq_line == 0) continue;	/* Try next PCI ID */
+		if (!pdev)
+			continue;
 		printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
 				pci_clone_list[i].name,
 				pci_ioaddr, pci_irq_line);
diff -u --recursive --new-file v2.1.92/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.1.92/linux/drivers/net/pcnet32.c	Thu Feb 12 20:56:09 1998
+++ linux/drivers/net/pcnet32.c	Thu Apr  2 09:12:24 1998
@@ -25,7 +25,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -78,7 +77,7 @@
  *	   in arch/i386/bios32.c
  * v0.21:  added endian conversion for ppc, from work by cort@cs.nmt.edu
  * v0.22:  added printing of status to ring dump
- * v0.23:  changed enet_statistics to net_devive_stats
+ * v0.23:  changed enet_statistics to net_device_stats
  */
 
 
@@ -172,7 +171,7 @@
 __initfunc(int pcnet32_probe (struct device *dev))
 {
     unsigned int  ioaddr = dev ? dev->base_addr: 0;
-    unsigned char irq_line = dev ? dev->irq : 0;
+    unsigned int  irq_line = dev ? dev->irq : 0;
     int *port;
     
     if (ioaddr > 0x1ff)
@@ -181,30 +180,20 @@
       return ENXIO;
     
 #if defined(CONFIG_PCI)
-    if (pcibios_present()) {
-	int pci_index;
+    if (pci_present()) {
+	struct pci_dev *pdev = NULL;
 	
 	printk("pcnet32.c: PCI bios is present, checking for devices...\n");
-	for (pci_index = 0; pci_index < 8; pci_index++) {
-	    unsigned char pci_bus, pci_device_fn;
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) {
 	    unsigned short pci_command;
 
-	    if (pcibios_find_device (PCI_VENDOR_ID_AMD,
-				     PCI_DEVICE_ID_AMD_LANCE, pci_index,
-				     &pci_bus, &pci_device_fn) != 0)
-	      break;
-	    pcibios_read_config_byte(pci_bus, pci_device_fn,
-				     PCI_INTERRUPT_LINE, &irq_line);
-	    pcibios_read_config_dword(pci_bus, pci_device_fn,
-				      PCI_BASE_ADDRESS_0, &ioaddr);
-	    /* Remove I/O space marker in bit 0. */
-	    ioaddr &= ~3;
+	    irq_line = pdev->irq;
+	    ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 	    /* PCI Spec 2.1 states that it is either the driver or PCI card's
 	     * responsibility to set the PCI Master Enable Bit if needed.
 	     *	(From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
 	     */
-	    pcibios_read_config_word(pci_bus, pci_device_fn,
-				     PCI_COMMAND, &pci_command);
+	    pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 	    
 	    /* Avoid already found cards from previous pcnet32_probe() calls */
 	    if (check_region(ioaddr, PCNET32_TOTAL_SIZE))
@@ -213,8 +202,7 @@
 	    if ( ! (pci_command & PCI_COMMAND_MASTER)) {
 		printk("PCI Master Bit has not been set. Setting...\n");
 		pci_command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
-		pcibios_write_config_word(pci_bus, pci_device_fn,
-					  PCI_COMMAND, pci_command);
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 	    }
 #ifdef __powerpc__
 	    irq_line = 15;
diff -u --recursive --new-file v2.1.92/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.1.92/linux/drivers/net/sunhme.c	Thu Feb 12 20:56:09 1998
+++ linux/drivers/net/sunhme.c	Thu Apr  2 09:12:24 1998
@@ -45,7 +45,6 @@
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/pbm.h>
 #endif
 
@@ -55,7 +54,10 @@
 static struct happy_meal *root_happy_dev = NULL;
 #endif
 
-/* #define HMEDEBUG */
+#undef HMEDEBUG
+#undef SXDEBUG
+#undef RXDEBUG
+#undef TXDEBUG
 
 #ifdef HMEDEBUG
 #define HMD(x)  printk x
@@ -1584,8 +1586,11 @@
 	happy_meal_poll_stop(hp, tregs);
 }
 
-/* #define TXD(x) printk x */
+#ifdef TXDEBUG
+#define TXD(x) printk x
+#else
 #define TXD(x)
+#endif
 
 static inline void happy_meal_tx(struct happy_meal *hp)
 {
@@ -1676,8 +1681,11 @@
 	TXD((">"));
 }
 
-/* #define RXD(x) printk x */
+#ifdef RXDEBUG
+#define RXD(x) printk x
+#else
 #define RXD(x)
+#endif
 
 /* Originally I use to handle the allocation failure by just giving back just
  * that one ring buffer to the happy meal.  Problem is that usually when that
@@ -1705,7 +1713,7 @@
 
 		/* Check for errors. */
 		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-			RXD(("ERR(%08lx)]", flags));
+			RXD(("ERR(%08x)]", flags));
 			hp->net_stats.rx_errors++;
 			if(len < ETH_ZLEN)
 				hp->net_stats.rx_length_errors++;
@@ -1724,11 +1732,8 @@
 		}
 		skb = hp->rx_skbs[elem];
 #ifdef NEED_DMA_SYNCHRONIZATION
-#ifdef CONFIG_PCI
-		if(!(hp->happy_flags & HFLAG_PCI))
-#endif
-			mmu_sync_dma(kva_to_hva(hp, skb->data),
-				     skb->len, hp->happy_sbus_dev->my_bus);
+		mmu_sync_dma(kva_to_hva(hp, skb->data),
+			     skb->len, hp->happy_sbus_dev->my_bus);
 #endif
 		if(len > RX_COPY_THRESHOLD) {
 			struct sk_buff *new_skb;
@@ -1819,7 +1824,7 @@
 
 		/* Check for errors. */
 		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-			RXD(("ERR(%08lx)]", flags));
+			RXD(("ERR(%08x)]", flags));
 			hp->net_stats.rx_errors++;
 			if(len < ETH_ZLEN)
 				hp->net_stats.rx_length_errors++;
@@ -1926,7 +1931,7 @@
 
 		/* Check for errors. */
 		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-			RXD(("ERR(%08lx)]", flags));
+			RXD(("ERR(%08x)]", flags));
 			hp->net_stats.rx_errors++;
 			if(len < ETH_ZLEN)
 				hp->net_stats.rx_length_errors++;
@@ -1975,7 +1980,7 @@
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
 	unsigned int happy_status    = hme_read32(hp, &gregs->stat);
 
-	HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
 	dev->interrupt = 1;
 
@@ -2020,7 +2025,7 @@
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
 	unsigned int happy_status     = readl((unsigned long)&gregs->stat);
 
-	HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
 	dev->interrupt = 1;
 
@@ -2065,7 +2070,7 @@
 	struct hmeal_tcvregs *tregs   = hp->tcvregs;
 	unsigned int happy_status    = hme_read32(hp, &gregs->stat);
 
-	HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
 	dev->interrupt = 1;
 
@@ -2181,8 +2186,11 @@
 	return 0;
 }
 
-/* #define SXD(x) printk x */
+#ifdef SXDEBUG
+#define SXD(x) printk x
+#else
 #define SXD(x)
+#endif
 
 static int happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
 {
@@ -2700,19 +2708,20 @@
 		}
 	}
 #ifdef CONFIG_PCI
-	if(pcibios_present()) {
+	if(pci_present()) {
 		struct pci_dev *pdev;
 
-		for(pdev = pci_devices; pdev; pdev = pdev->next) {
+		pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+				       PCI_DEVICE_ID_SUN_HAPPYMEAL, 0);
+		while (pdev) {
 			if(cards)
 				dev = NULL;
-			if((pdev->vendor == PCI_VENDOR_ID_SUN) &&
-			   (pdev->device == PCI_DEVICE_ID_SUN_HAPPYMEAL)) {
-				cards++;
-				if((v = happy_meal_pci_init(dev, pdev)))
-					return v;
-			}
-
+			cards++;
+			if((v = happy_meal_pci_init(dev, pdev)))
+				return v;
+			pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+					       PCI_DEVICE_ID_SUN_HAPPYMEAL,
+					       pdev);
 		}
 	}
 #endif
diff -u --recursive --new-file v2.1.92/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.1.92/linux/drivers/net/tlan.c	Thu Feb 12 20:56:09 1998
+++ linux/drivers/net/tlan.c	Thu Apr  2 09:12:24 1998
@@ -29,7 +29,6 @@
 
 #include "tlan.h"
 
-#include <linux/bios32.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
@@ -96,7 +95,7 @@
 };
 
 
-static int	TLan_PciProbe( u8 *, u8 *, u8 *, u8 *, u32 *, u32 * );
+static int	TLan_PciProbe( u8 *, u8 *, int *, u8 *, u32 *, u32 * );
 static int	TLan_Init( struct device * );
 static int	TLan_Open(struct device *dev);
 static int	TLan_StartTx(struct sk_buff *, struct device *);
@@ -193,7 +192,7 @@
 	int		failed;
 	int		found;
 	u32		io_base;
-	u8		irq;
+	int		irq;
 	u8		rev;
 
 	printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n",
@@ -319,7 +318,8 @@
 	static int	pad_allocated = 0;
 	int		found;
 	TLanPrivateInfo	*priv;
-	u8		bus, dfn, irq, rev;
+	u8		bus, dfn, rev;
+	int		irq;
 	u32		io_base, dl_ix;
 
 	found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix );
@@ -398,7 +398,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
+int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
 {
 	static int dl_index = 0;
 	static int pci_index = 0;
@@ -409,7 +409,7 @@
 	int	reg;
 
 
-	if ( ! pcibios_present() ) {
+	if ( ! pci_present() ) {
 		printk( "TLAN:   PCI Bios not present.\n" );
 		return 0;
 	}
@@ -425,6 +425,7 @@
 		);
 
 		if ( ! not_found ) {
+			struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn);
 
 			TLAN_DBG(
 				TLAN_DEBUG_GNRL,
@@ -433,19 +434,18 @@
 				TLanDeviceList[dl_index].deviceId
 			);
 
-			pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_REVISION_ID, pci_rev);
-			pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_INTERRUPT_LINE, pci_irq);
-			pcibios_read_config_word ( *pci_bus,  *pci_dfn, PCI_COMMAND, &pci_command);
-			pcibios_read_config_dword( *pci_bus,  *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_base);
-			pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev);
+			*pci_irq = pdev->irq;
+			pci_read_config_word ( pdev, PCI_COMMAND, &pci_command);
+			pci_read_config_byte ( pdev, PCI_LATENCY_TIMER, &pci_latency);
 
 			if (pci_latency < 0x10) {
-				pcibios_write_config_byte( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, 0xff);
+				pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 0xff);
 				TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    Setting latency timer to max.\n");
 			}
 
-			for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg +=4 ) {
-				pcibios_read_config_dword( *pci_bus, *pci_dfn, reg, pci_io_base);
+			for ( reg = 0; reg <= 5; reg ++ ) {
+				*pci_io_base = pdev->base_address[reg];
 				if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {
 					*pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;
 					TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    IO mapping is available at %x.\n", *pci_io_base);
diff -u --recursive --new-file v2.1.92/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.1.92/linux/drivers/net/tulip.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/net/tulip.c	Thu Apr  2 09:12:24 1998
@@ -82,7 +82,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -125,8 +124,10 @@
 #include <linux/delay.h>
 #endif
 #if (LINUX_VERSION_CODE >= 0x20100)
+#ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 #endif
+#endif
 #ifdef SA_SHIRQ
 #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
 #else
@@ -135,6 +136,7 @@
 
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #endif
 
 /* This my implementation of shared IRQs, now only used for 1.2.13. */
@@ -453,11 +455,17 @@
 	   well with the current structure.  So instead we detect just the
 	   Tulip cards in slot order. */
 
-	if (pcibios_present()) {
+	if (pci_present()) {
 		unsigned char pci_bus, pci_device_fn;
 
 		for (;pci_index < 0xff; pci_index++) {
-			unsigned char pci_irq_line, pci_latency;
+			unsigned char pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+			unsigned int pci_irq_line;
+			struct pci_dev *pdev;
+#else
+			unsigned char pci_irq_line;
+#endif
 			unsigned short pci_command, vendor, device;
 			unsigned int pci_ioaddr, chip_idx = 0;
 
@@ -473,10 +481,16 @@
 									 PCI_VENDOR_ID, &vendor);
 			pcibios_read_config_word(pci_bus, pci_device_fn,
 									 PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[0];
+#else
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_INTERRUPT_LINE, &pci_irq_line);
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
 			/* Remove I/O space marker in bit 0. */
 			pci_ioaddr &= ~3;
 
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.1.92/linux/drivers/pci/Makefile	Fri Jan 30 11:28:08 1998
+++ linux/drivers/pci/Makefile	Thu Apr  2 09:12:24 1998
@@ -9,9 +9,18 @@
 # parent makefile.
 #
 
-L_OBJS   := pci.o
 L_TARGET := pci.a
 
+# Nasty trick as nobody references pcisyms.o, but we still want it linked.
+ifeq ($(CONFIG_MODULES),y)
+O_TARGET = pci_syms.o
+OX_OBJS  = pcisyms.o
+O_OBJS   = pci.o
+L_OBJS   := pci_syms.o
+else
+L_OBJS   := pci.o
+endif
+
 ifdef CONFIG_PROC_FS
 L_OBJS   += proc.o
 ifdef CONFIG_PCI_OLD_PROC
@@ -22,5 +31,7 @@
 ifdef CONFIG_PCI_OPTIMIZE
 L_OBJS   += quirks.o
 endif
+
+L_OBJS   += compat.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/compat.c linux/drivers/pci/compat.c
--- v2.1.92/linux/drivers/pci/compat.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/compat.c	Thu Apr  2 09:12:24 1998
@@ -0,0 +1,43 @@
+/*
+ *	$Id: compat.c,v 1.1 1998/02/16 10:35:50 mj Exp $
+ *
+ *	PCI Bus Services -- Function For Backward Compatibility
+ *
+ *	Copyright 1998 Martin Mares
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+int
+pcibios_find_class(unsigned int class, unsigned short index, unsigned char *bus, unsigned char *devfn)
+{
+	struct pci_dev *dev = NULL;
+	int cnt = 0;
+
+	while ((dev = pci_find_class(class, dev)))
+		if (index == cnt++) {
+			*bus = dev->bus->number;
+			*devfn = dev->devfn;
+			return PCIBIOS_SUCCESSFUL;
+		}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+int
+pcibios_find_device(unsigned short vendor, unsigned short device, unsigned short index,
+		    unsigned char *bus, unsigned char *devfn)
+{
+	struct pci_dev *dev = NULL;
+	int cnt = 0;
+
+	while ((dev = pci_find_device(vendor, device, dev)))
+		if (index == cnt++) {
+			*bus = dev->bus->number;
+			*devfn = dev->devfn;
+			return PCIBIOS_SUCCESSFUL;
+		}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.1.92/linux/drivers/pci/oldproc.c	Wed Apr  1 20:11:52 1998
+++ linux/drivers/pci/oldproc.c	Thu Apr  2 09:12:24 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: oldproc.c,v 1.4 1998/01/05 14:16:18 mj Exp $
+ *	$Id: oldproc.c,v 1.10 1998/03/15 13:50:11 ecd Exp $
  *
  *	Backward-compatible procfs interface for PCI.
  *
@@ -10,7 +10,6 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/sched.h>
@@ -220,9 +219,11 @@
 	DEVICE( OLICOM,		OLICOM_OC2183,	"OC-2183/2185"),
 	DEVICE( OLICOM,		OLICOM_OC2326,	"OC-2326"),
 	DEVICE( OLICOM,		OLICOM_OC6151,	"OC-6151/6152"),
-	DEVICE( SUN,		SUN_EBUS,	"EBUS"),
-	DEVICE( SUN,		SUN_HAPPYMEAL,	"Happy Meal"),
+	DEVICE( SUN,		SUN_EBUS,	"PCI-EBus Bridge"),
+	DEVICE( SUN,		SUN_HAPPYMEAL,	"Happy Meal Ethernet"),
+	DEVICE( SUN,		SUN_SIMBA,	"Advanced PCI Bridge"),
 	DEVICE( SUN,		SUN_PBM,	"PCI Bus Module"),
+	DEVICE( SUN,		SUN_SABRE,	"Ultra IIi PCI"),
 	DEVICE( CMD,		CMD_640,	"640 (buggy)"),
 	DEVICE( CMD,		CMD_643,	"643"),
 	DEVICE( CMD,		CMD_646,	"646"),
@@ -273,6 +274,8 @@
 	DEVICE( ASP,		ASP_ABP940UW,	"ABP940UW"),
 	DEVICE( CERN,		CERN_SPSB_PMC,	"STAR/RD24 SCI-PCI (PMC)"),
 	DEVICE( CERN,		CERN_SPSB_PCI,	"STAR/RD24 SCI-PCI (PMC)"),
+	DEVICE( CERN,		CERN_HIPPI_DST,	"HIPPI destination"),
+	DEVICE( CERN,		CERN_HIPPI_SRC,	"HIPPI source"),
 	DEVICE( IMS,		IMS_8849,	"8849"),
 	DEVICE( TEKRAM2,	TEKRAM2_690c,	"DC690c"),
 	DEVICE( TUNDRA,		TUNDRA_CA91C042,"CA91C042 Universe"),
@@ -378,6 +381,7 @@
 	DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf"),
 	DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf"),
 	DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf"),
+	DEVICE( ESSENTIAL,      ROADRUNNER,     "RoadRunner serial HIPPI"),
 	DEVICE( CYCLADES,	CYCLOM_Y_Lo,	"Cyclom-Y below 1Mbyte"),
 	DEVICE( CYCLADES,	CYCLOM_Y_Hi,	"Cyclom-Y above 1Mbyte"),
 	DEVICE( CYCLADES,	CYCLOM_Z_Lo,	"Cyclom-Z below 1Mbyte"),
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.92/linux/drivers/pci/pci.c	Wed Apr  1 20:11:52 1998
+++ linux/drivers/pci/pci.c	Mon Apr  6 14:01:34 1998
@@ -1,42 +1,28 @@
 /*
- *	$Id: pci.c,v 1.55 1997/12/27 12:17:54 mj Exp $
+ *	$Id: pci.c,v 1.71 1998/03/30 11:14:35 mj Exp $
  *
- *	PCI services that are built on top of the BIOS32 service.
+ *	PCI Bus Services
  *
- *	Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
+ *	Copyright 1993 -- 1998 Drew Eckhardt, Frederic Potter,
  *	David Mosberger-Tang, Martin Mares
  */
 
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/malloc.h>
 
 #include <asm/page.h>
 
 struct pci_bus pci_root;
-struct pci_dev *pci_devices = 0;
+struct pci_dev *pci_devices = NULL;
+static struct pci_dev **pci_last_dev_p = &pci_devices;
 
 #undef DEBUG
 
-/*
- * pci_malloc() returns initialized memory of size SIZE.  Can be
- * used only while pci_init() is active.
- */
-__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
-{
-	void *mem;
-
-	mem = (void*) *mem_startp;
-	*mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-	memset(mem, 0, size);
-	return mem;
-}
-
-
 const char *pcibios_strerror(int error)
 {
 	static char buf[32];
@@ -68,7 +54,45 @@
 }
 
 
-unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
+struct pci_dev *
+pci_find_slot(unsigned int bus, unsigned int devfn)
+{
+	struct pci_dev *dev;
+
+	for(dev=pci_devices; dev; dev=dev->next)
+		if (dev->bus->number == bus && dev->devfn == devfn)
+			break;
+	return dev;
+}
+
+
+struct pci_dev *
+pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
+{
+	if (!from)
+		from = pci_devices;
+	else
+		from = from->next;
+	while (from && (from->vendor != vendor || from->device != device))
+		from = from->next;
+	return from;
+}
+
+
+struct pci_dev *
+pci_find_class(unsigned int class, struct pci_dev *from)
+{
+	if (!from)
+		from = pci_devices;
+	else
+		from = from->next;
+	while (from && from->class != class)
+		from = from->next;
+	return from;
+}
+
+
+__initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
 {
 	unsigned int devfn, l, max, class;
 	unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
@@ -97,7 +121,8 @@
 			continue;
 		}
 
-		dev = pci_malloc(sizeof(*dev), mem_startp);
+		dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+		memset(dev, 0, sizeof(*dev));
 		dev->bus = bus;
 		dev->devfn  = devfn;
 		dev->vendor = l & 0xffff;
@@ -113,13 +138,19 @@
 		pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
 		class >>= 8;				    /* upper 3 bytes */
 		dev->class = class;
+		dev->hdr_type = hdr_type;
 
 		switch (hdr_type & 0x7f) {		    /* header type */
-		case 0:					    /* standard header */
+		case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
 			if (class >> 8 == PCI_CLASS_BRIDGE_PCI)
 				goto bad;
-			/* read irq level (may be changed during pcibios_fixup()): */
-			pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
+			/*
+			 * If the card generates interrupts, read IRQ number
+			 * (some architectures change it during pcibios_fixup())
+			 */
+			pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);
+			if (irq)
+				pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
 			dev->irq = irq;
 			/*
 			 * read base address registers, again pcibios_fixup() can
@@ -130,7 +161,7 @@
 				dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
 			}
 			break;
-		case 1:					    /* bridge header */
+		case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */
 			if (class >> 8 != PCI_CLASS_BRIDGE_PCI)
 				goto bad;
 			for (reg = 0; reg < 2; reg++) {
@@ -138,6 +169,14 @@
 				dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
 			}
 			break;
+		case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
+			if (class >> 16 != PCI_BASE_CLASS_BRIDGE)
+				goto bad;
+			for (reg = 0; reg < 2; reg++) {
+				pcibios_read_config_dword(bus->number, devfn, PCI_CB_MEMORY_BASE_0 + (reg << 3), &l);
+				dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
+			}
+			break;
 		default:				    /* unknown header */
 		bad:
 			printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
@@ -154,8 +193,8 @@
 		 * Put it into the global PCI device chain. It's used to
 		 * find devices once everything is set up.
 		 */
-		dev->next = pci_devices;
-		pci_devices = dev;
+		*pci_last_dev_p = dev;
+		pci_last_dev_p = &dev->next;
 
 		/*
 		 * Now insert it into the list of devices held
@@ -174,7 +213,8 @@
 			/*
 			 * Insert it into the tree of buses.
 			 */
-			child = pci_malloc(sizeof(*child), mem_startp);
+			child = kmalloc(sizeof(*child), GFP_ATOMIC);
+			memset(child, 0, sizeof(*child));
 			child->next = bus->children;
 			bus->children = child;
 			child->self = dev;
@@ -203,11 +243,14 @@
 			pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
 			if ((buses & 0xFFFFFF) != 0)
 			  {
+			    unsigned int cmax;
+
 			    child->primary = buses & 0xFF;
 			    child->secondary = (buses >> 8) & 0xFF;
 			    child->subordinate = (buses >> 16) & 0xFF;
 			    child->number = child->secondary;
-			    max = pci_scan_bus(child, mem_startp);
+			    cmax = pci_scan_bus(child);
+			    if (cmax > max) max = cmax;
 			  }
 			else
 			  {
@@ -223,7 +266,7 @@
 			    /*
 			     * Now we can scan all subordinate buses:
 			     */
-			    max = pci_scan_bus(child, mem_startp);
+			    max = pci_scan_bus(child);
 			    /*
 			     * Set the subordinate bus number to its real
 			     * value:
@@ -250,36 +293,31 @@
 }
 
 
-__initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_end))
+__initfunc(void pci_init(void))
 {
-	mem_start = pcibios_init(mem_start, mem_end);
+	pcibios_init();
 
-	if (!pcibios_present()) {
+	if (!pci_present()) {
 		printk("PCI: No PCI bus detected\n");
-		return mem_start;
 	}
 
-	printk("Probing PCI hardware.\n");
+	printk("PCI: Probing PCI hardware.\n");
 
 	memset(&pci_root, 0, sizeof(pci_root));
-	pci_root.subordinate = pci_scan_bus(&pci_root, &mem_start);
+	pci_root.subordinate = pci_scan_bus(&pci_root);
 
 	/* give BIOS a chance to apply platform specific fixes: */
-	mem_start = pcibios_fixup(mem_start, mem_end);
+	pcibios_fixup();
 
 #ifdef CONFIG_PCI_OPTIMIZE
 	pci_quirks_init();
 #endif
-
-	return mem_start;
 }
 
-struct pci_dev *pci_find_dev(unsigned char bus, unsigned char devfn)
-{
-	struct pci_dev *pdev;
-	for (pdev = pci_devices; pdev; pdev = pdev->next) {
-		if ((pdev->bus->number==bus) && (pdev->devfn==devfn)) break;
 
-	}
-	return pdev;
+__initfunc(void pci_setup (char *str, int *ints))
+{
+	str = pcibios_setup(str);
+	if (*str)
+		printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.1.92/linux/drivers/pci/pcisyms.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/pcisyms.c	Thu Apr  2 09:12:24 1998
@@ -0,0 +1,28 @@
+/*
+ *	$Id: pcisyms.c,v 1.2 1998/02/16 10:35:57 mj Exp $
+ *
+ *	PCI Bus Services -- Exported Symbols
+ *
+ *	Copyright 1998 Martin Mares
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+EXPORT_SYMBOL(pcibios_present);
+EXPORT_SYMBOL(pcibios_read_config_byte);
+EXPORT_SYMBOL(pcibios_read_config_word);
+EXPORT_SYMBOL(pcibios_read_config_dword);
+EXPORT_SYMBOL(pcibios_write_config_byte);
+EXPORT_SYMBOL(pcibios_write_config_word);
+EXPORT_SYMBOL(pcibios_write_config_dword);
+EXPORT_SYMBOL(pcibios_strerror);
+EXPORT_SYMBOL(pci_devices);
+EXPORT_SYMBOL(pci_find_class);
+EXPORT_SYMBOL(pci_find_device);
+EXPORT_SYMBOL(pci_find_slot);
+
+/* Backward compatibility */
+
+EXPORT_SYMBOL(pcibios_find_class);
+EXPORT_SYMBOL(pcibios_find_device);
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.1.92/linux/drivers/pci/proc.c	Mon Feb 23 18:12:06 1998
+++ linux/drivers/pci/proc.c	Thu Apr  2 09:12:24 1998
@@ -1,14 +1,13 @@
 /*
- *	$Id: proc.c,v 1.1 1997/12/22 17:22:31 mj Exp $
+ *	$Id: proc.c,v 1.8 1998/03/12 14:32:51 mj Exp $
  *
  *	Procfs interface for the PCI bus.
  *
- *	Copyright (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *	Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
@@ -49,14 +48,27 @@
 	int pos = *ppos;
 	unsigned char bus = dev->bus->number;
 	unsigned char dfn = dev->devfn;
-	int cnt;
+	int cnt, size;
 
-	if (pos >= PCI_CFG_SPACE_SIZE)
+	/*
+	 * Normal users can read only the standardized portion of the
+	 * configuration space as several chips lock up when trying to read
+	 * undefined locations (think of Intel PIIX4 as a typical example).
+	 */
+
+	if (fsuser())
+		size = PCI_CFG_SPACE_SIZE;
+	else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+		size = 128;
+	else
+		size = 64;
+
+	if (pos >= size)
 		return 0;
-	if (nbytes >= PCI_CFG_SPACE_SIZE)
-		nbytes = PCI_CFG_SPACE_SIZE;
-	if (pos + nbytes > PCI_CFG_SPACE_SIZE)
-		nbytes = PCI_CFG_SPACE_SIZE - pos;
+	if (nbytes >= size)
+		nbytes = size;
+	if (pos + nbytes > size)
+		nbytes = size - pos;
 	cnt = nbytes;
 
 	if (!access_ok(VERIFY_WRITE, buf, cnt))
@@ -260,16 +272,9 @@
 	get_pci_dev_info
 };
 
-__initfunc(void proc_bus_pci_init(void))
+__initfunc(void proc_bus_pci_add(struct pci_bus *bus, struct proc_dir_entry *proc_pci))
 {
-	struct proc_dir_entry *proc_pci;
-	struct pci_bus *bus;
-
-	if (!pcibios_present())
-		return;
-	proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus);
-	proc_register(proc_pci, &proc_pci_devices);
-	for(bus = &pci_root; bus; bus = bus->next) {
+	while (bus) {
 		char name[16];
 		struct proc_dir_entry *de;
 		struct pci_dev *dev;
@@ -287,5 +292,19 @@
 			e->data = dev;
 			e->size = PCI_CFG_SPACE_SIZE;
 		}
+		if (bus->children)
+			proc_bus_pci_add(bus->children, proc_pci);
+		bus = bus->next;
 	}
+}
+
+__initfunc(void proc_bus_pci_init(void))
+{
+	struct proc_dir_entry *proc_pci;
+
+	if (!pci_present())
+		return;
+	proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus);
+	proc_register(proc_pci, &proc_pci_devices);
+	proc_bus_pci_add(&pci_root, proc_pci);
 }
diff -u --recursive --new-file v2.1.92/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- v2.1.92/linux/drivers/pci/quirks.c	Sun Dec 21 17:27:18 1997
+++ linux/drivers/pci/quirks.c	Thu Apr  2 09:12:24 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: quirks.c,v 1.2 1997/09/20 21:43:34 davem Exp $
+ * $Id: quirks.c,v 1.3 1998/02/06 19:51:42 mj Exp $
  *
  * PCI Chipset-Specific Quirks
  *
@@ -13,7 +13,6 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v2.1.92/linux/drivers/scsi/53c7,8xx.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/scsi/53c7,8xx.c	Thu Apr  2 09:12:24 1998
@@ -243,7 +243,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
@@ -1413,53 +1412,47 @@
 __initfunc(static int 
 ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, 
     unsigned char bus, unsigned char device_fn, long long options)) {
-    unsigned short vendor_id, device_id, command;
+    unsigned short command;
 #ifdef LINUX_1_2
     unsigned long
 #else
     unsigned int 
 #endif
 	base, io_port; 
-    unsigned char irq, revision;
+    unsigned char revision;
     int error, expected_chip;
     int expected_id = -1, max_revision = -1, min_revision = -1;
-    int i;
+    int i, irq;
+    struct pci_dev *pdev = pci_find_slot(bus, device_fn);
 
     printk("scsi-ncr53c7,8xx : at PCI bus %d, device %d,  function %d\n",
 	bus, (int) (device_fn & 0xf8) >> 3, 
     	(int) device_fn & 7);
 
-    if (!pcibios_present()) {
-	printk("scsi-ncr53c7,8xx : not initializing due to lack of PCI BIOS,\n"
+    if (!pdev) {
+	printk("scsi-ncr53c7,8xx : not initializing -- PCI device not found,\n"
 	       "        try using memory, port, irq override instead.\n");
 	return -1;
     }
 
-    if ((error = pcibios_read_config_word (bus, device_fn, PCI_VENDOR_ID, 
-	&vendor_id)) ||
-	(error = pcibios_read_config_word (bus, device_fn, PCI_DEVICE_ID, 
-	    &device_id)) ||
-	(error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, 
+    if ((error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, 
 	    &command)) ||
-	(error = pcibios_read_config_dword (bus, device_fn, 
-	    PCI_BASE_ADDRESS_0, &io_port)) || 
-	(error = pcibios_read_config_dword (bus, device_fn, 
-	    PCI_BASE_ADDRESS_1, &base)) ||
 	(error = pcibios_read_config_byte (bus, device_fn, PCI_CLASS_REVISION,
-	    &revision)) ||
-	(error = pcibios_read_config_byte (bus, device_fn, PCI_INTERRUPT_LINE,
-	    &irq))) {
+	    &revision))) {
 	printk ("scsi-ncr53c7,8xx : error %s not initializing due to error reading configuration space\n"
 		"	 perhaps you specified an incorrect PCI bus, device, or function.\n"
 		, pcibios_strerror(error));
 	return -1;
     }
+    io_port = pdev->base_address[0];
+    base = pdev->base_address[1];
+    irq = pdev->irq;
 
     /* If any one ever clones the NCR chips, this will have to change */
 
-    if (vendor_id != PCI_VENDOR_ID_NCR) {
+    if (pdev->vendor != PCI_VENDOR_ID_NCR) {
 	printk ("scsi-ncr53c7,8xx : not initializing, 0x%04x is not NCR vendor ID\n",
-	    (int) vendor_id);
+	    (int) pdev->vendor);
 	return -1;
     }
 
@@ -1467,14 +1460,16 @@
     if ( ! (command & PCI_COMMAND_MASTER)) {
       printk("SCSI: PCI Master Bit has not been set. Setting...\n");
       command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
-      pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
-      if (io_port >= 0x10000000) {
+      pci_write_config_word(pdev, PCI_COMMAND, command);
+
+      if (io_port >= 0x10000000 && is_prep ) {
 	      /* Mapping on PowerPC can't handle this! */
 	      unsigned long new_io_port;
 	      new_io_port = (io_port & 0x00FFFFFF) | 0x01000000;
 	      printk("SCSI: I/O moved from %08X to %08x\n", io_port, new_io_port);
 	      io_port = new_io_port;
-	      pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+	      pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, io_port);
+	      pdev->base_address[0] = io_port;
       }
     }
 #endif
@@ -1519,7 +1514,7 @@
     }
 
     for (i = 0; i < NPCI_CHIP_IDS; ++i) {
-	if (device_id == pci_chip_ids[i].pci_device_id) {
+	if (pdev->device == pci_chip_ids[i].pci_device_id) {
 	    max_revision = pci_chip_ids[i].max_revision;
 	    min_revision = pci_chip_ids[i].min_revision;
 	    expected_chip = pci_chip_ids[i].chip;
@@ -1528,10 +1523,10 @@
 	    expected_id = pci_chip_ids[i].pci_device_id;
     }
 
-    if (chip && device_id != expected_id) 
+    if (chip && pdev->device != expected_id) 
 	printk ("scsi-ncr53c7,8xx : warning : device id of 0x%04x doesn't\n"
                 "                   match expected 0x%04x\n",
-	    (unsigned int) device_id, (unsigned int) expected_id );
+	    (unsigned int) pdev->device, (unsigned int) expected_id );
     
     if (max_revision != -1 && revision > max_revision) 
 	printk ("scsi-ncr53c7,8xx : warning : revision of %d is greater than %d.\n",
@@ -1598,7 +1593,7 @@
 	} 
     }
 
-    if (pcibios_present()) {
+    if (pci_present()) {
 	for (i = 0; i < NPCI_CHIP_IDS; ++i) 
 	    for (pci_index = 0;
 		!pcibios_find_device (PCI_VENDOR_ID_NCR, 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c
--- v2.1.92/linux/drivers/scsi/53c7xx.c	Thu Mar 26 15:57:03 1998
+++ linux/drivers/scsi/53c7xx.c	Thu Apr  2 09:12:24 1998
@@ -244,8 +244,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
@@ -670,6 +668,7 @@
     return h;
 }
 
+#if 0
 /*
  * Function : request_synchronous (int host, int target)
  * 
@@ -717,6 +716,7 @@
     restore_flags(flags);
     return 0;
 }
+#endif
 
 /*
  * Function : request_disconnect (int host, int on_or_off)
@@ -1121,16 +1121,12 @@
 
 /* 
  * Function : static int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, 
- *	int chip, u32 base, int io_port, int irq, int dma,
- *	long long options, int clock);
+ *	int chip, u32 base, int io_port, int irq, int dma, long long options,
+ *	int clock);
  *
  * Purpose : initializes a NCR53c7,8x0 based on base addresses,
  *	IRQ, and DMA channel.	
  *	
- *	Useful where a new NCR chip is backwards compatible with
- *	a supported chip, but the DEVICE ID has changed so it 
- *	doesn't show up when the autoprobe does a pcibios_find_device.
- *
  * Inputs : tpnt - Template for this SCSI adapter, board - board level
  *	product, chip - 710
  * 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/53c7xx.h linux/drivers/scsi/53c7xx.h
--- v2.1.92/linux/drivers/scsi/53c7xx.h	Thu Mar 26 15:57:03 1998
+++ linux/drivers/scsi/53c7xx.h	Thu Apr  2 09:12:24 1998
@@ -1247,14 +1247,6 @@
 					   digits of part number */
 
     char valid_ids[8];			/* Valid SCSI ID's for adapter */
-    /*
-     * PCI bus, device, function, only for NCR53c8x0 chips.
-     * pci_valid indicates that the PCI configuration information
-     * is valid, and we can twiddle MAX_LAT, etc. as recommended
-     * for maximum performance in the NCR documentation.
-     */
-    unsigned char pci_bus, pci_device_fn;
-    unsigned pci_valid:1;
 
     u32 *dsp;				/* dsp to restart with after
 					   all stacked interrupts are
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c
--- v2.1.92/linux/drivers/scsi/AM53C974.c	Sun Dec 21 17:04:48 1997
+++ linux/drivers/scsi/AM53C974.c	Thu Apr  2 09:12:25 1998
@@ -3,7 +3,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/blk.h>
@@ -35,6 +34,8 @@
  *   Robin Cutshaw (robin@xfree86.org) and is used here in a 
  *   slightly modified form.
  *
+ *  PCI detection rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
  *  For the remaining code:
  *    Copyright 1994, D. Frieauff
  *    EMail: fri@rsx42sun0.dofn.de
@@ -189,23 +190,6 @@
 #define DEF_RAE                 0    /* CNTLREG4, RAE active negation on REQ, ACK only */
 #define DEF_RADE                1    /* 1CNTLREG4, active negation on REQ, ACK and data */
 
-/*** PCI block ***/
-/* standard registers are defined in <linux/pci.h> */
-#ifndef PCI_VENDOR_ID_AMD
-#define PCI_VENDOR_ID_AMD	0x1022
-#define PCI_DEVICE_ID_AMD_SCSI  0x2020
-#endif
-#define PCI_BASE_MASK           0xFFFFFFE0
-#define PCI_COMMAND_PERREN      0x40
-#define PCI_SCRATCH_REG_0	0x40	/* 16 bits */
-#define PCI_SCRATCH_REG_1	0x42	/* 16 bits */
-#define PCI_SCRATCH_REG_2	0x44	/* 16 bits */
-#define PCI_SCRATCH_REG_3	0x46	/* 16 bits */
-#define PCI_SCRATCH_REG_4	0x48	/* 16 bits */
-#define PCI_SCRATCH_REG_5	0x4A	/* 16 bits */
-#define PCI_SCRATCH_REG_6	0x4C	/* 16 bits */
-#define PCI_SCRATCH_REG_7	0x4E	/* 16 bits */
-
 /*** SCSI block ***/
 #define CTCLREG		    	0x00	/* r	current transf. count, low byte    */
 #define CTCMREG		   	0x04	/* r 	current transf. count, middle byte */
@@ -363,108 +347,15 @@
     int max_offset;	                /* max. sync. offset, 0 = asynchronous */
     } override_t;
 
-/************ PCI stuff *************/
-#define AM53C974_PCIREG_OPEN()                    outb(0xF1, 0xCF8); outb(0, 0xCFA)
-#define AM53C974_PCIREG_CLOSE()                   outb(0, 0xCF8)
-#define AM53C974_PCIREG_READ_BYTE(instance,a)     ( inb((a) + (instance)->io_port) )
-#define AM53C974_PCIREG_READ_WORD(instance,a)     ( inw((a) + (instance)->io_port) )
-#define AM53C974_PCIREG_READ_DWORD(instance,a)    ( inl((a) + (instance)->io_port) )
-#define AM53C974_PCIREG_WRITE_BYTE(instance,x,a)  ( outb((x), (a) + (instance)->io_port) )
-#define AM53C974_PCIREG_WRITE_WORD(instance,x,a)  ( outw((x), (a) + (instance)->io_port) )
-#define AM53C974_PCIREG_WRITE_DWORD(instance,x,a) ( outl((x), (a) + (instance)->io_port) )
-
-typedef struct _pci_config_t {
-    /* start of official PCI config space header */
-    union {
-        unsigned int device_vendor;
-	struct {
-	  unsigned short vendor;
-	  unsigned short device;
- 	  } dv;
-        } dv_id;
-#define _device_vendor dv_id.device_vendor
-#define _vendor dv_id.dv.vendor
-#define _device dv_id.dv.device
-    union {
-        unsigned int status_command;
-	struct {
-	  unsigned short command;
-	  unsigned short status;
-	  } sc;
-        } stat_cmd;
-#define _status_command stat_cmd.status_command
-#define _command stat_cmd.sc.command
-#define _status  stat_cmd.sc.status
-    union {
-        unsigned int class_revision;
-	struct {
-	    unsigned char rev_id;
-	    unsigned char prog_if;
-	    unsigned char sub_class;
-	    unsigned char base_class;
-	} cr;
-    } class_rev;
-#define _class_revision class_rev.class_revision
-#define _rev_id     class_rev.cr.rev_id
-#define _prog_if    class_rev.cr.prog_if
-#define _sub_class  class_rev.cr.sub_class
-#define _base_class class_rev.cr.base_class
-    union {
-        unsigned int bist_header_latency_cache;
-	struct {
-	    unsigned char cache_line_size;
-	    unsigned char latency_timer;
-	    unsigned char header_type;
-	    unsigned char bist;
-	} bhlc;
-    } bhlc;
-#define _bist_header_latency_cache bhlc.bist_header_latency_cache
-#define _cache_line_size bhlc.bhlc.cache_line_size
-#define _latency_timer   bhlc.bhlc.latency_timer
-#define _header_type     bhlc.bhlc.header_type
-#define _bist            bhlc.bhlc.bist
-    unsigned int _base0;
-    unsigned int _base1;
-    unsigned int _base2;
-    unsigned int _base3;
-    unsigned int _base4;
-    unsigned int _base5;
-    unsigned int rsvd1;
-    unsigned int rsvd2;
-    unsigned int _baserom;
-    unsigned int rsvd3;
-    unsigned int rsvd4;
-    union {
-        unsigned int max_min_ipin_iline;
-	struct {
-	    unsigned char int_line;
-	    unsigned char int_pin;
-	    unsigned char min_gnt;
-	    unsigned char max_lat;
-	} mmii;
-    } mmii;
-#define _max_min_ipin_iline mmii.max_min_ipin_iline
-#define _int_line mmii.mmii.int_line
-#define _int_pin  mmii.mmii.int_pin
-#define _min_gnt  mmii.mmii.min_gnt
-#define _max_lat  mmii.mmii.max_lat
-    /* end of official PCI config space header */
-    unsigned short _ioaddr; /* config type 1 - private I/O addr    */
-    unsigned int _pcibus;  /* config type 2 - private bus id      */
-    unsigned int _cardnum; /* config type 2 - private card number */
-} pci_config_t;
-
 
 #ifdef AM53C974_DEBUG
-static void AM53C974_print_pci(struct Scsi_Host *instance);
 static void AM53C974_print_phase(struct Scsi_Host *instance);
 static void AM53C974_print_queues(struct Scsi_Host *instance);
 #endif /* AM53C974_DEBUG */
 static void AM53C974_print(struct Scsi_Host *instance);
 static void AM53C974_keywait(void);
-static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt);
-static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt);
-static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config);
+static __inline__ int AM53C974_pci_detect(Scsi_Host_Template *tpnt);
+static int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev);
 static void AM53C974_config_after_reset(struct Scsi_Host *instance);
 static __inline__ void initialize_SCp(Scsi_Cmnd *cmd);
 static __inline__ void run_main(void);
@@ -502,52 +393,6 @@
 #ifdef AM53C974_DEBUG
 static int deb_stop = 1;
 
-/**************************************************************************
- * Function : void AM53C974_print_pci(struct Scsi_Host *instance)
- *
- * Purpose : dump the PCI registers for debugging purposes
- *
- * Input : instance - which AM53C974
- **************************************************************************/
-static void AM53C974_print_pci(struct Scsi_Host *instance)
-{
-int            i;
-unsigned short vendor_id, device_id, command, status, scratch[8];
-unsigned long  class_revision, base; 
-unsigned char  irq, cache_line_size, latency_timer, header_type;
-
-AM53C974_PCIREG_OPEN();
-
-for (i = 0; i < 8; i++) *(scratch + i) = AM53C974_PCIREG_READ_WORD(instance, PCI_SCRATCH_REG_0 + 2*i);
-vendor_id = AM53C974_PCIREG_READ_WORD(instance, PCI_VENDOR_ID);
-device_id = AM53C974_PCIREG_READ_WORD(instance, PCI_DEVICE_ID);
-command   = AM53C974_PCIREG_READ_WORD(instance, PCI_COMMAND);
-status    = AM53C974_PCIREG_READ_WORD(instance, PCI_STATUS);
-class_revision = AM53C974_PCIREG_READ_DWORD(instance, PCI_CLASS_REVISION);
-cache_line_size = AM53C974_PCIREG_READ_BYTE(instance, PCI_CACHE_LINE_SIZE);
-latency_timer = AM53C974_PCIREG_READ_BYTE(instance, PCI_LATENCY_TIMER);
-header_type = AM53C974_PCIREG_READ_BYTE(instance, PCI_HEADER_TYPE);
-base = AM53C974_PCIREG_READ_DWORD(instance, PCI_BASE_ADDRESS_0);
-irq = AM53C974_PCIREG_READ_BYTE(instance, PCI_INTERRUPT_LINE);
-
-AM53C974_PCIREG_CLOSE();
-
-
-printk("------------- start of PCI register dump -------------\n");
-printk("PCI_VENDOR_ID:       0x%x\n", vendor_id);
-printk("PCI_DEVICE_ID:       0x%x\n", device_id);
-printk("PCI_COMMAND:         0x%x\n", command);
-printk("PCI_STATUS:          0x%x\n", status);
-printk("PCI_CLASS_REVISION:  0x%lx\n", class_revision);
-printk("PCI_CACHE_LINE_SIZE: 0x%x\n", cache_line_size);
-printk("PCI_LATENCY_TIMER:   0x%x\n", latency_timer);
-printk("PCI_HEADER_TYPE:     0x%x\n", header_type);
-printk("PCI_BASE_ADDRESS_0:  0x%lx\n", base);
-printk("PCI_INTERRUPT_LINE:  %d\n", irq);
-for (i = 0; i < 8; i++) printk("PCI_SCRATCH_%d:       0x%x\n", i, scratch[i]);
-printk("------------- end of PCI register dump -------------\n\n");
-}
-
 static struct {
     unsigned char value;
     char *name;
@@ -732,7 +577,7 @@
 
 #if defined (CONFIG_PCI)
 /**************************************************************************
-* Function : int AM53C974_bios_detect(Scsi_Host_Template *tpnt)
+* Function : int AM53C974_pci_detect(Scsi_Host_Template *tpnt)
 *
 * Purpose : detects and initializes AM53C974 SCSI chips with PCI Bios
 *
@@ -740,161 +585,34 @@
 * 
 * Returns : number of host adapters detected
 **************************************************************************/
-static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt)
+static __inline__ int AM53C974_pci_detect(Scsi_Host_Template *tpnt)
 {
 int count = 0;        /* number of boards detected */
-int pci_index;
-pci_config_t pci_config;
+struct pci_dev *pdev = NULL;
+unsigned short command;
+
+while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pdev))) {
+    pci_read_config_word(pdev, PCI_COMMAND, &command);
 
-for (pci_index = 0; pci_index <= 16; ++pci_index) {
-    unsigned char pci_bus, pci_device_fn;
-    if (pcibios_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pci_index, &pci_bus, &pci_device_fn) != 0)
-       break;
-
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &pci_config._vendor);
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &pci_config._device);
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_config._command);
-    pcibios_read_config_word(pci_bus, pci_device_fn, PCI_STATUS, &pci_config._status);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_CLASS_REVISION, &pci_config._class_revision);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_CACHE_LINE_SIZE, &pci_config._cache_line_size);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_config._latency_timer);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_HEADER_TYPE, &pci_config._header_type);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_BIST, &pci_config._bist);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_config._base0);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_config._base1);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_config._base2);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_config._base3);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_config._base4);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_config._base5);
-    pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_ROM_ADDRESS, &pci_config._baserom);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_config._int_line);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_PIN, &pci_config._int_pin);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MIN_GNT, &pci_config._min_gnt);
-    pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MAX_LAT, &pci_config._max_lat);
-    pci_config._pcibus = 0xFFFFFFFF;
-    pci_config._cardnum = 0xFFFFFFFF;
- 
     /* check whether device is I/O mapped -- should be */
-    if (!(pci_config._command & PCI_COMMAND_IO)) continue;
+    if (!(command & PCI_COMMAND_IO)) continue;
 
     /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility
        to set the PCI Master Enable Bit if needed. 
        (from Mark Stockton <marks@schooner.sys.hou.compaq.com>) */
-    if (!(pci_config._command & PCI_COMMAND_MASTER)) {
-       pci_config._command |= PCI_COMMAND_MASTER;
+    if (!(command & PCI_COMMAND_MASTER)) {
+       command |= PCI_COMMAND_MASTER;
        printk("PCI Master Bit has not been set. Setting...\n");
-       pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, pci_config._command); }
+       pci_write_config_word(pdev, PCI_COMMAND, command); }
 
     /* everything seems OK now, so initialize */
-    if (AM53C974_init(tpnt, pci_config)) count++ ;
+    if (AM53C974_init(tpnt, pdev)) count++ ;
     }
 return (count);
 }
 #endif
 
 /**************************************************************************
-* Function : int AM53C974_nobios_detect(Scsi_Host_Template *tpnt)
-*
-* Purpose : detects and initializes AM53C974 SCSI chips using PCI config 2 
-*
-* Inputs : tpnt - host template
-* 
-* Returns : number of host adapters detected
-*
-* NOTE : This code assumes the controller on PCI bus 0.
-*
-* Origin: Robin Cutshaw (robin@xfree86.org)
-**************************************************************************/
-static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt)
-{
-int          count = 0;		/* number of boards detected */
-pci_config_t pci_config;
-
-/* first try PCI config method 1 */
-for (pci_config._pcibus = 0; pci_config._pcibus < 0x10; pci_config._pcibus++) {
-    for (pci_config._cardnum = 0; pci_config._cardnum < 0x20; pci_config._cardnum++) {
-        unsigned long config_cmd;
-	config_cmd = 0x80000000 | (pci_config._pcibus<<16) | (pci_config._cardnum<<11);
-
-        outl(config_cmd, 0xCF8);         /* ioreg 0 */
-        pci_config._device_vendor = inl(0xCFC);
-
-        if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) {
-           outl(config_cmd | PCI_COMMAND, 0xCF8); pci_config._status_command  = inl(0xCFC);
-           outl(config_cmd | PCI_CLASS_REVISION, 0xCF8); pci_config._class_revision = inl(0xCFC);
-           outl(config_cmd | PCI_CACHE_LINE_SIZE, 0xCF8); pci_config._bist_header_latency_cache = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_0, 0xCF8); pci_config._base0 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_1, 0xCF8); pci_config._base1 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_2, 0xCF8); pci_config._base2 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_3, 0xCF8); pci_config._base3 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_4, 0xCF8); pci_config._base4 = inl(0xCFC);
-           outl(config_cmd | PCI_BASE_ADDRESS_5, 0xCF8); pci_config._base5 = inl(0xCFC);
-           outl(config_cmd | PCI_ROM_ADDRESS, 0xCF8); pci_config._baserom = inl(0xCFC);
-           outl(config_cmd | PCI_INTERRUPT_LINE, 0xCF8); pci_config._max_min_ipin_iline = inl(0xCFC);
-
-           /* check whether device is I/O mapped -- should be */
-           if (!(pci_config._command & PCI_COMMAND_IO)) continue;
-
-           /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility
-              to set the PCI Master Enable Bit if needed. 
-              From Mark Stockton <marks@schooner.sys.hou.compaq.com> */
-           if (!(pci_config._command & PCI_COMMAND_MASTER)) {
-              pci_config._command |= PCI_COMMAND_MASTER;
-              printk("Config 1; PCI Master Bit has not been set. Setting...\n");
-              outl(config_cmd | PCI_COMMAND, 0xCF8); outw(pci_config._command, 0xCFC); }
-
-           /* everything seems OK now, so initialize */
-           if (AM53C974_init(tpnt, pci_config)) count++ ;
-           }
-        }
-    }
-outb(0, 0xCF8); /* is this really necessary? */
-
-/* try PCI config method 2, if no device was detected by method 1 */
-if (!count) {
-   AM53C974_PCIREG_OPEN();
-
-   pci_config._pcibus = 0xFFFFFFFF;
-   pci_config._cardnum = 0xFFFFFFFF;
-
-   for (pci_config._ioaddr = 0xC000; pci_config._ioaddr < 0xD000; pci_config._ioaddr += 0x0100) {
-       pci_config._device_vendor = inl(pci_config._ioaddr);
-
-       if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) {
-          pci_config._status_command = inl(pci_config._ioaddr + PCI_COMMAND);
-          pci_config._class_revision = inl(pci_config._ioaddr + PCI_CLASS_REVISION);
-          pci_config._bist_header_latency_cache = inl(pci_config._ioaddr + PCI_CACHE_LINE_SIZE);
-          pci_config._base0 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_0);
-          pci_config._base1 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_1);
-          pci_config._base2 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_2);
-          pci_config._base3 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_3);
-          pci_config._base4 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_4);
-          pci_config._base5 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_5);
-          pci_config._baserom = inl(pci_config._ioaddr + PCI_ROM_ADDRESS);
-          pci_config._max_min_ipin_iline = inl(pci_config._ioaddr + PCI_INTERRUPT_LINE);
-
-          /* check whether device is I/O mapped -- should be */
-          if (!(pci_config._command & PCI_COMMAND_IO)) continue;
-
-          /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility
-             to set the PCI Master Enable Bit if needed.
-             From Mark Stockton <marks@schooner.sys.hou.compaq.com> */
-          if (!(pci_config._command & PCI_COMMAND_MASTER)) {
-              pci_config._command |= PCI_COMMAND_MASTER;
-              printk("Config 2; PCI Master Bit has not been set. Setting...\n");
-              outw(pci_config._command, pci_config._ioaddr + PCI_COMMAND); }
-
-          /* everything seems OK now, so initialize */
-          if (AM53C974_init(tpnt, pci_config)) count++ ;
-          }
-       }
-   AM53C974_PCIREG_CLOSE();
-   }
-
-return(count);
-}
-
-/**************************************************************************
 * Function : int AM53C974_detect(Scsi_Host_Template *tpnt)
 *
 * Purpose : detects and initializes AM53C974 SCSI chips
@@ -905,21 +623,19 @@
 **************************************************************************/
 __initfunc(int AM53C974_detect(Scsi_Host_Template *tpnt))
 {
-int count;        /* number of boards detected */
+int count = 0;        /* number of boards detected */
 
 tpnt->proc_dir = &proc_scsi_am53c974;
 
 #if defined (CONFIG_PCI)
-if (pcibios_present())
-   count = AM53C974_bios_detect(tpnt);
-  else
+if (pci_present())
+   count = AM53C974_pci_detect(tpnt);
 #endif
-count = AM53C974_nobios_detect(tpnt);
 return (count);
 }
 
 /**************************************************************************
-* Function : int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config)
+* Function : int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev)
 *
 * Purpose : initializes instance and corresponding AM53/79C974 chip,
 *
@@ -932,7 +648,7 @@
 *       set up by the BIOS (as reflected by contents of register CNTLREG1).
 *       This is the only BIOS assistance we need.
 **************************************************************************/
-__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config))
+__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev))
 {
 AM53C974_local_declare();
 int                      i, j;
@@ -947,9 +663,8 @@
 instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata));
 hostdata = (struct AM53C974_hostdata *)instance->hostdata;
 instance->base = NULL;
-instance->io_port = pci_config._base0 & (pci_config._base0 & 0x1 ? 
-                                         0xFFFFFFFC : 0xFFFFFFF0);
-instance->irq = pci_config._int_line;
+instance->io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+instance->irq = pdev->irq;
 instance->dma_channel = -1;
 AM53C974_setio(instance);
 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/README.in2000 linux/drivers/scsi/README.in2000
--- v2.1.92/linux/drivers/scsi/README.in2000	Thu Jul 17 20:24:38 1997
+++ linux/drivers/scsi/README.in2000	Wed Apr  1 20:41:12 1998
@@ -1,4 +1,11 @@
 
+UPDATE NEWS: version 1.32 - 28 Mar 98
+
+   Removed the check for legal IN2000 hardware versions:
+   It appears that the driver works fine with serial
+   EPROMs (the 8-pin chip that defines hardware rev) as
+   old as 2.1, so we'll assume that all cards are OK.
+
 UPDATE NEWS: version 1.31 - 6 Jul 97
 
    Fixed a bug that caused incorrect SCSI status bytes to be
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.1.92/linux/drivers/scsi/aic7xxx.c	Sun Jan  4 10:55:09 1998
+++ linux/drivers/scsi/aic7xxx.c	Thu Apr  2 09:12:25 1998
@@ -107,7 +107,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
@@ -626,49 +625,6 @@
 #define aic7xxx_position(cmd)	((cmd)->SCp.have_data_in)
 
 /*
- * "Static" structures. Note that these are NOT initialized
- * to zero inside the kernel - we have to initialize them all
- * explicitly.
- *
- * We support multiple adapter cards per interrupt, but keep a
- * linked list of Scsi_Host structures for each IRQ.  On an interrupt,
- * use the IRQ as an index into aic7xxx_boards[] to locate the card
- * information.
- */
-static struct Scsi_Host *aic7xxx_boards[NR_IRQS + 1];
-
-/*
- * When we detect and register the card, it is possible to
- * have the card raise a spurious interrupt.  Because we need
- * to support multiple cards, we cannot tell which card caused
- * the spurious interrupt.  And, we might not even have added
- * the card info to the linked list at the time the spurious
- * interrupt gets raised.  This variable is suppose to keep track
- * of when we are registering a card and how many spurious
- * interrupts we have encountered.
- *
- *   0 - do not allow spurious interrupts.
- *   1 - allow 1 spurious interrupt
- *   2 - have 1 spurious interrupt, do not allow any more.
- *
- * I've made it an integer instead of a boolean in case we
- * want to allow more than one spurious interrupt for debugging
- * purposes.  Otherwise, it could just go from true to false to
- * true (or something like that).
- *
- * When the driver detects the cards, we'll set the count to 1
- * for each card detection and registration.  After the registration
- * of a card completes, we'll set the count back to 0.  So far, it
- * seems to be enough to allow a spurious interrupt only during
- * card registration; if a spurious interrupt is going to occur,
- * this is where it happens.
- *
- * We should be able to find a way to avoid getting the spurious
- * interrupt.  But until we do, we have to keep this ugly code.
- */
-static int aic7xxx_spurious_count;
-
-/*
  * As of Linux 2.1, the mid-level SCSI code uses virtual addresses
  * in the scatter-gather lists.  We need to convert the virtual
  * addresses to physical addresses.
@@ -746,11 +702,11 @@
         struct aic7xxx_scb    *q_next;        /* next scb in queue */
 	scb_flag_type          flags;         /* current state of scb */
 	struct hw_scatterlist *sg_list;       /* SG list in adapter format */
-        unsigned char          sg_count;
 	unsigned char          sense_cmd[6];  /*
                                                * Allocate 6 characters for
                                                * sense command.
                                                */
+        unsigned char          sg_count;
 };
 
 /*
@@ -792,13 +748,14 @@
  */
 struct aic7xxx_host {
   struct Scsi_Host        *host;             /* pointer to scsi host */
+  struct aic7xxx_host     *next;             /* pointer to next aic7xxx device */
   int                      host_no;          /* SCSI host number */
   int                      instance;         /* aic7xxx instance number */
   int                      scsi_id;          /* host adapter SCSI ID */
   int                      scsi_id_b;        /*   channel B for twin adapters */
   int                      irq;              /* IRQ for this adapter */
-  int                      base;             /* card base address */
-  unsigned int             mbase;            /* I/O memory address */
+  unsigned long            base;             /* card base address */
+  unsigned long            mbase;            /* I/O memory address */
   volatile unsigned char  *maddr;            /* memory mapped address */
 #define A_SCANNED               0x0001
 #define B_SCANNED               0x0002
@@ -833,7 +790,6 @@
   unsigned char            qfullcount;
   unsigned char            cmdoutcnt;
   unsigned char            curqincnt;
-  struct Scsi_Host        *next;             /* allow for multiple IRQs */
   unsigned char            activescbs;       /* active scbs */
   scb_queue_type           waiting_scbs;     /*
                                               * SCBs waiting for space in
@@ -923,15 +879,15 @@
     hscb->control,
     hscb->target_channel_lun,
     hscb->SCSI_cmd_length,
-    hscb->SCSI_cmd_pointer );
+    le32_to_cpu(hscb->SCSI_cmd_pointer) );
   printk("        datlen:%d data:0x%lx segs:0x%x segp:0x%lx\n",
-    hscb->data_count,
-    hscb->data_pointer,
+    le32_to_cpu(hscb->data_count),
+    le32_to_cpu(hscb->data_pointer),
     hscb->SG_segment_count,
-    hscb->SG_list_pointer);
+    le32_to_cpu(hscb->SG_list_pointer));
   printk("        sg_addr:%lx sg_len:%ld\n",
-    hscb->sg_list[0].address,
-    hscb->sg_list[0].length);
+    le32_to_cpu(hscb->sg_list[0].address),
+    le32_to_cpu(hscb->sg_list[0].length));
 }
 #endif
 
@@ -963,6 +919,7 @@
                                               */
 static int aic7xxx_enable_ultra = 0;         /* enable ultra SCSI speeds */
 static int aic7xxx_verbose = 0;	             /* verbose messages */
+static struct aic7xxx_host *first_aic7xxx = NULL; /* list of all our devices */
 
 
 /****************************************************************************
@@ -995,7 +952,7 @@
 {
   if (p->maddr != NULL)
   {
-#ifdef __alpha__
+#if defined(__alpha__) || defined(__sparc_v9__) || defined(__powerpc__)
     int i;
 
     for (i=0; i < size; i++)
@@ -2300,7 +2257,7 @@
 
   	busy_scb = p->scb_data->scb_array[busy_scbid];
   
-  	next_scbid = busy_scb->hscb->data_count >> 24;
+  	next_scbid = le32_to_cpu(busy_scb->hscb->data_count) >> 24;
 
   	if (next_scbid == SCB_LIST_NULL)
         {
@@ -2492,8 +2449,12 @@
 static void
 aic7xxx_reset_current_bus(struct aic7xxx_host *p)
 {
+  unsigned long processor_flags;
   unsigned char scsiseq;
 
+  save_flags(processor_flags);
+  cli();
+
   /* Disable reset interrupts. */
   outb(inb(p->base + SIMODE1) & ~ENSCSIRST, p->base + SIMODE1);
 
@@ -2512,6 +2473,8 @@
   outb(inb(p->base + SIMODE1) | ENSCSIRST, p->base + SIMODE1);
 
   udelay(1000);
+
+  restore_flags(processor_flags);
 }
 
 /*+F*************************************************************************
@@ -3257,8 +3220,8 @@
 	if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
 	{
           printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-        	 "SEQINT 0x%x, scb %d, flags 0x%x, cmd 0x%x.\n", p->host_no,
-        	 intstat, scb_index, scb->flags, (unsigned int) scb->cmd);
+        	 "SEQINT 0x%x, scb %d, flags 0x%x, cmd 0x%lx.\n", p->host_no,
+        	 intstat, scb_index, scb->flags, (unsigned long) scb->cmd);
 	}
 	else
 	{
@@ -3294,8 +3257,8 @@
         	scb->sense_cmd[1] = (cmd->lun << 5);
         	scb->sense_cmd[4] = sizeof(cmd->sense_buffer);
 
-        	scb->sg_list[0].address = VIRT_TO_BUS(&cmd->sense_buffer);
-        	scb->sg_list[0].length = sizeof(cmd->sense_buffer);
+        	scb->sg_list[0].address = cpu_to_le32(VIRT_TO_BUS(&cmd->sense_buffer));
+        	scb->sg_list[0].length = cpu_to_le32(sizeof(cmd->sense_buffer));
         	cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
 
                 /*
@@ -3308,18 +3271,15 @@
         	hscb->SG_segment_count = 1;
 
         	addr = VIRT_TO_BUS(&scb->sg_list[0]);
-        	memcpy(&hscb->SG_list_pointer, &addr,
-        	       sizeof(hscb->SG_list_pointer));
+                hscb->SG_list_pointer = cpu_to_le32(addr);
+                hscb->data_pointer = scb->sg_list[0].address;
 
-        	memcpy(&hscb->data_pointer, &(scb->sg_list[0].address),
-        	       sizeof(hscb->data_pointer));
         	/* Maintain SCB_LINKED_NEXT */
-        	hscb->data_count &= 0xFF000000;
+        	hscb->data_count &= cpu_to_le32(0xFF000000);
   		hscb->data_count |= scb->sg_list[0].length;
 
         	addr = VIRT_TO_BUS(scb->sense_cmd);
-        	memcpy(&hscb->SCSI_cmd_pointer, &addr,
-        	       sizeof(hscb->SCSI_cmd_pointer));
+                hscb->SCSI_cmd_pointer = cpu_to_le32(addr);
         	hscb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
 
                 scb->sg_count = hscb->SG_segment_count;
@@ -3496,7 +3456,9 @@
         for (i = 0; i < scb->sg_count; i++)
         {
           printk(KERN_INFO "     sg[%d] - Addr 0x%x : Length %d\n",
-                 i, scb->sg_list[i].address, scb->sg_list[i].length);
+                 i,
+                 le32_to_cpu(scb->sg_list[i].address),
+                 le32_to_cpu(scb->sg_list[i].length));
         }
 	/*
 	 * XXX - What do we really want to do on an overrun?  The
@@ -3835,43 +3797,21 @@
  *
  * Description:
  *   SCSI controller interrupt handler.
- *
- *   NOTE: Since we declared this using SA_INTERRUPT, interrupts should
- *         be disabled all through this function unless we say otherwise.
  *-F*************************************************************************/
 static void
 aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct aic7xxx_host *p;
+  struct aic7xxx_host *p = (struct aic7xxx_host *) dev_id;
   unsigned char intstat;
   unsigned long flags;
 
-  p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata;
-
-  /*
-   * Search for the host with a pending interrupt.  If we can't find
-   * one, then we've encountered a spurious interrupt.
-   */
-  while ((p != NULL) && !(inb(p->base + INTSTAT) & INT_PEND))
-  {
-    if (p->next == NULL)
-    {
-      p = NULL;
-    }
-    else
-    {
-      p = (struct aic7xxx_host *) p->next->hostdata;
-    }
-  }
-
-  if (p == NULL)
-    return;
-
   /*
    * Handle all the interrupt sources - especially for SCSI
    * interrupts, we won't get a second chance at them.
    */
   intstat = inb(p->base + INTSTAT);
+  if (! (intstat & INT_PEND))	/* Interrupt for another device */
+    return;
 
   /*
    * Keep track of interrupts for /proc/scsi
@@ -4181,6 +4121,7 @@
   }
 }
 
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_probe
@@ -4258,6 +4199,7 @@
 
   return (AIC_NONE);
 }
+#endif /* __sparc_v9__ or __powerpc__ */
 
 /*+F*************************************************************************
  * Function:
@@ -4962,7 +4904,7 @@
 {
   int i;
   unsigned char sblkctl, flags = 0;
-  int max_targets;
+  int max_targets, irq_flags = 0;
   int found = 1;
   char channel_ids[] = {'A', 'B', 'C'};
   unsigned char target_settings;
@@ -5066,7 +5008,6 @@
   p->host = host;
   p->host_no = host->host_no;
   p->isr_count = 0;
-  p->next = NULL;
   p->completeq.head = NULL;
   p->completeq.tail = NULL;
   scbq_init(&p->scb_data->free_scbs);
@@ -5079,53 +5020,20 @@
     p->device_status[i].active_cmds = 0;
     p->device_status[i].last_reset = 0;
   }
-  if (aic7xxx_boards[p->irq] == NULL)
-  {
-    int result;
-    int irq_flags = 0;
 
+  /*
+   * Request an IRQ for the board. Only allow sharing IRQs with PCI devices.
+   */
 #ifdef AIC7XXX_OLD_ISR_TYPE
-    irg_flags = SA_INTERRUPT;
+  irq_flags = SA_INTERRUPT;
 #endif
-    /*
-     * Warning! This must be done before requesting the irq.  It is
-     * possible for some boards to raise an interrupt as soon as
-     * they are enabled.  So when we request the irq from the Linux
-     * kernel, an interrupt is triggered immediately.  Therefore, we
-     * must ensure the board data is correctly set before the request.
-     */
-    aic7xxx_boards[p->irq] = host;
-
-    /*
-     * Register IRQ with the kernel.  Only allow sharing IRQs with
-     * PCI devices.
-     */
-    if (p->chip_class == AIC_777x)
-    {
-      result = (request_irq(p->irq, aic7xxx_isr, irq_flags, "aic7xxx", NULL));
-    }
-    else
-    {
-      result = (request_irq(p->irq, aic7xxx_isr, irq_flags | SA_SHIRQ,
-                "aic7xxx", NULL));
-    }
-    if (result < 0)
-    {
-      printk(KERN_WARNING "aic7xxx: Couldn't register IRQ %d, ignoring.\n",
-             p->irq);
-      aic7xxx_boards[p->irq] = NULL;
-      return (0);
-    }
-  }
-  else
+  if (p->chip_class != AIC_777x)
+    irq_flags |= SA_SHIRQ;
+  if (request_irq(p->irq, aic7xxx_isr, irq_flags, "aic7xxx", p) < 0)
   {
-    /*
-     * We have found a host adapter sharing an IRQ of a previously
-     * registered host adapter. Add this host adapter's Scsi_Host
-     * to the beginning of the linked list of hosts at the same IRQ.
-     */
-    p->next = aic7xxx_boards[p->irq];
-    aic7xxx_boards[p->irq] = host;
+    printk(KERN_WARNING "aic7xxx: Couldn't register IRQ %d, ignoring.\n",
+           p->irq);
+    return (0);
   }
 
   /*
@@ -5325,17 +5233,7 @@
       printk("aic7xxx: Unable to allocate hardware SCB array; "
              "failing detection.\n");
       release_region(p->base, MAXREG - MINREG);
-      /*
-       * Ensure that we only free the IRQ when there is _not_ another
-       * aic7xxx adapter sharing this IRQ.  The adapters are always
-       * added to the beginning of the list, so we can grab the next
-       * pointer and place it back in the board array.
-       */
-      if (p->next == NULL)
-      {
-        free_irq(p->irq, aic7xxx_isr);
-      }
-      aic7xxx_boards[p->irq] = p->next;
+      free_irq(p->irq, p);
       return(0);
     }
     /* At least the control byte of each SCB needs to be 0. */
@@ -5399,6 +5297,12 @@
    */
   unpause_sequencer(p, /* unpause_always */ TRUE);
 
+  /*
+   * Add it to our list of adapters.
+   */
+  p->next = first_aic7xxx;
+  first_aic7xxx = p;
+
   return (found);
 }
 
@@ -5453,7 +5357,7 @@
  *   and a pointer to a aic7xxx_host struct upon success.
  *-F*************************************************************************/
 static struct aic7xxx_host *
-aic7xxx_alloc(Scsi_Host_Template *sht, unsigned int base, unsigned int mbase,
+aic7xxx_alloc(Scsi_Host_Template *sht, unsigned long base, unsigned long mbase,
     aha_chip_type chip_type, int flags, scb_data_type *scb_data)
 {
   struct aic7xxx_host *p = NULL;
@@ -5768,36 +5672,23 @@
 aic7xxx_detect(Scsi_Host_Template *template)
 {
   int found = 0;
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
   aha_status_type adapter_bios;
+  unsigned char hcntrl, hostconf, irq = 0;
+  int slot, base;
+#endif
   aha_chip_class_type chip_class;
   aha_chip_type chip_type;
-  int slot, base;
   int chan_num = 0;
-  unsigned char hcntrl, sxfrctl1, sblkctl, hostconf, irq = 0;
+  unsigned char sxfrctl1, sblkctl;
   int i;
   struct aic7xxx_host *p;
 
-  /*
-   * Since we may allow sharing of IRQs, it is imperative
-   * that we "null-out" the aic7xxx_boards array. It is
-   * not guaranteed to be initialized to 0 (NULL). We use
-   * a NULL entry to indicate that no prior hosts have
-   * been found/registered for that IRQ.
-   */
-  for (i = 0; i < NUMBER(aic7xxx_boards); i++)
-  {
-    aic7xxx_boards[i] = NULL;
-  }
-
   template->proc_dir = &proc_scsi_aic7xxx;
   template->name = aic7xxx_info(NULL);
   template->sg_tablesize = AIC7XXX_MAX_SG;
 
-  /*
-   * Initialize the spurious count to 0.
-   */
-  aic7xxx_spurious_count = 0;
-
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
   /*
    * EISA/VL-bus card signature probe.
    */
@@ -5834,11 +5725,6 @@
       }
 
       /*
-       * We found a card, allow 1 spurious interrupt.
-       */
-      aic7xxx_spurious_count = 1;
-
-      /*
        * Pause the card preserving the IRQ type.  Allow the operator
        * to override the IRQ trigger.
        */
@@ -5925,7 +5811,7 @@
           default:  /* Won't get here. */
             break;
         }
-        printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%x, IRQ %d (%s), ",
+        printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s), ",
                (p->flags & USE_DEFAULTS) ? "dis" : "en", p->base, p->irq,
                (p->pause & IRQMS) ? "level sensitive" : "edge triggered");
         /*
@@ -5984,18 +5870,15 @@
           aic7xxx_free(p);
         }
       }
-      /*
-       * Disallow spurious interrupts.
-       */
-      aic7xxx_spurious_count = 0;
     }
   }
+#endif /* __sparc_v9__ or __powerpc__ */
 
 #ifdef CONFIG_PCI
   /*
    * PCI-bus probe.
    */
-  if (pcibios_present())
+  if (pci_present())
   {
     struct
     {
@@ -6021,102 +5904,94 @@
     };
 
     int error, flags;
-    int done = 0;
-    unsigned int iobase, mbase;
     unsigned short index = 0;
-    unsigned char pci_bus, pci_device_fn;
     unsigned char ultra_enb = 0;
     unsigned int  devconfig, class_revid;
     scb_data_type *shared_scb_data = NULL;
     char rev_id[] = {'B', 'C', 'D'};
+    struct pci_dev *pdev = NULL;
+    unsigned long iobase, mbase;
+    unsigned int irq;
 
     for (i = 0; i < NUMBER(aic7xxx_pci_devices); i++)
-    {
-      done = FALSE;
-      while (!done)
-      {
-        if (pcibios_find_device(aic7xxx_pci_devices[i].vendor_id,
-                                aic7xxx_pci_devices[i].device_id,
-                                index, &pci_bus, &pci_device_fn))
-        {
-          index = 0;
-          done = TRUE;
-        }
-        else  /* Found an Adaptec PCI device. */
-        {
-          chip_class = aic7xxx_pci_devices[i].chip_class;
-          chip_type = aic7xxx_pci_devices[i].chip_type;
-          chan_num = 0;
-          flags = 0;
-          switch (aic7xxx_pci_devices[i].chip_type)
-          {
-            case AIC_7855:
-              flags |= USE_DEFAULTS;
-              break;
-
-            case AIC_7872:  /* 3940 */
-            case AIC_7882:  /* 3940-Ultra */
-              flags |= MULTI_CHANNEL;
-              chan_num = number_of_3940s & 0x1;  /* Has 2 controllers */
-              number_of_3940s++;
-              break;
-
-            case AIC_7873:  /* 3985 */
-            case AIC_7883:  /* 3985-Ultra */
-              chan_num = number_of_3985s;  /* Has 3 controllers */
-              flags |= MULTI_CHANNEL;
-              number_of_3985s++;
-              if (number_of_3985s == 3)
-              {
-                number_of_3985s = 0;
-                shared_scb_data = NULL;
-              }
-              break;
-
-            default:
-              break;
-          }
+      while ((pdev = pci_find_device(aic7xxx_pci_devices[i].vendor_id,
+                                     aic7xxx_pci_devices[i].device_id,
+				    pdev)))
+      {
+        chip_class = aic7xxx_pci_devices[i].chip_class;
+        chip_type = aic7xxx_pci_devices[i].chip_type;
+        chan_num = 0;
+        flags = 0;
+        switch (aic7xxx_pci_devices[i].chip_type)
+        {
+          case AIC_7855:
+            flags |= USE_DEFAULTS;
+            break;
 
-          /*
-           * Read sundry information from PCI BIOS.
-           */
-          error = pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                            PCI_BASE_ADDRESS_0, &iobase);
-          error += pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                            PCI_INTERRUPT_LINE, &irq);
-          error += pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                            PCI_BASE_ADDRESS_1, &mbase);
-          error += pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                             DEVCONFIG, &devconfig);
-          error += pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                             CLASS_PROGIF_REVID, &class_revid);
+          case AIC_7872:  /* 3940 */
+          case AIC_7882:  /* 3940-Ultra */
+            flags |= MULTI_CHANNEL;
+            chan_num = number_of_3940s & 0x1;  /* Has 2 controllers */
+            number_of_3940s++;
+            break;
 
-          printk("aic7xxx: <%s> at PCI %d\n",
-                 board_names[chip_type], PCI_SLOT(pci_device_fn));
+          case AIC_7873:  /* 3985 */
+          case AIC_7883:  /* 3985-Ultra */
+            chan_num = number_of_3985s;  /* Has 3 controllers */
+            flags |= MULTI_CHANNEL;
+            number_of_3985s++;
+            if (number_of_3985s == 3)
+            {
+              number_of_3985s = 0;
+              shared_scb_data = NULL;
+            }
+            break;
 
-          /*
-           * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so
-           * we mask it off.
-           */
-          iobase &= PCI_BASE_ADDRESS_IO_MASK;
+          default:
+            break;
+        }
 
-          p = aic7xxx_alloc(template, iobase, mbase, chip_type, flags,
-                            shared_scb_data);
+        /*
+         * Read sundry information from PCI BIOS.
+         */
+	iobase = pdev->base_address[0];
+	mbase = pdev->base_address[1];
+	irq = pdev->irq;
+        error = pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
+        error += pci_read_config_dword(pdev, CLASS_PROGIF_REVID, &class_revid);
+        printk("aic7xxx: <%s> at PCI %d\n",
+               board_names[chip_type], PCI_SLOT(pdev->devfn));
 
-          if (p == NULL)
-          {
-            printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
-            continue;
-          }
+        /*
+         * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so
+         * we mask it off.
+         */
+	iobase &= PCI_BASE_ADDRESS_IO_MASK;
+        p = aic7xxx_alloc(template, iobase, mbase, chip_type, flags, shared_scb_data);
+        if(p) {
+          unsigned short pci_command;
+
+          /* Enable bus mastering since this thing must do DMA. */
+          pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+          pci_command |= PCI_COMMAND_MASTER;
+#ifdef __powerpc__
+          /* Enable I/O and memory-space access */
+          pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+#endif
+          pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+        } else {
+          printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+          continue;
+        }
 
-          /* Remember to set the channel number, irq, and chip class. */
-          p->chan_num = chan_num;
-          p->irq = irq;
-          p->chip_class = chip_class;
+        /* Remember to set the channel number, irq, and chip class. */
+        p->chan_num = chan_num;
+        p->irq = irq;
+        p->chip_class = chip_class;
 #ifdef AIC7XXX_PAGE_ENABLE
-          p->flags |= PAGE_ENABLED;
+        p->flags |= PAGE_ENABLED;
 #endif
-          p->instance = found;
+        p->instance = found;
 
           /*
            * Remember how the card was setup in case there is no seeprom.
@@ -6236,8 +6111,8 @@
           /*
            * Print some additional information about the adapter.
            */
-          printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%x, "
-                 "IO Mem 0x%x, IRQ %d",
+          printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, "
+                 "IO Mem 0x%lx, IRQ %x",
                  (p->flags & USE_DEFAULTS) ? "dis" : "en",
                  p->base, p->mbase, p->irq);
           if ((class_revid & DEVREVID) < 3)
@@ -6246,13 +6121,6 @@
           }
           printk("\n");
 
-          /*
-           * I don't think we need to bother with allowing
-           * spurious interrupts for the 787x/785x, but what
-           * the hey.
-           */
-          aic7xxx_spurious_count = 1;
-
           if (aic7xxx_extended)
             p->flags |= EXTENDED_TRANSLATION;
 
@@ -6294,13 +6162,7 @@
           }
 
           index++;
-          /*
-           * Disable spurious interrupts.
-           */
-          aic7xxx_spurious_count = 0;
-        }  /* Found an Adaptec PCI device. */
-      }
-    }
+      }  /* Found an Adaptec PCI device. */
   }
 #endif CONFIG_PCI
 
@@ -6391,9 +6253,11 @@
   /*
    * XXX - this relies on the host data being stored in a
    *       little-endian format.
+   *
+   * No longer is that an issue, I've "big-endian'ified" this driver. -DaveM
    */
   hscb->SCSI_cmd_length = cmd->cmd_len;
-  hscb->SCSI_cmd_pointer = VIRT_TO_BUS(cmd->cmnd);
+  hscb->SCSI_cmd_pointer = cpu_to_le32(VIRT_TO_BUS(cmd->cmnd));
 
   if (cmd->use_sg)
   {
@@ -6410,19 +6274,19 @@
     sg = (struct scatterlist *)cmd->request_buffer;
     for (i = 0; i < cmd->use_sg; i++)
     {
-      scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
-      scb->sg_list[i].length = (unsigned int) sg[i].length;
+      scb->sg_list[i].address = cpu_to_le32(VIRT_TO_BUS(sg[i].address));
+      scb->sg_list[i].length = cpu_to_le32((unsigned int) sg[i].length);
     }
-    hscb->SG_list_pointer = VIRT_TO_BUS(scb->sg_list);
+    hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(scb->sg_list));
     hscb->SG_segment_count = cmd->use_sg;
     scb->sg_count = hscb->SG_segment_count;
 
     /* Copy the first SG into the data pointer area. */
     hscb->data_pointer = scb->sg_list[0].address;
-    hscb->data_count = scb->sg_list[0].length | (SCB_LIST_NULL << 24);
+    hscb->data_count = scb->sg_list[0].length | cpu_to_le32(SCB_LIST_NULL << 24);
 #if 0
     printk("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
-           cmd->use_sg, aic7xxx_length(cmd, 0), hscb->data_count);
+           cmd->use_sg, aic7xxx_length(cmd, 0), le32_to_cpu(hscb->data_count));
 #endif
   }
   else
@@ -6435,11 +6299,11 @@
     {
       hscb->SG_segment_count = 1;
       scb->sg_count = 1;
-      scb->sg_list[0].address = VIRT_TO_BUS(cmd->request_buffer);
-      scb->sg_list[0].length = cmd->request_bufflen;
-      hscb->SG_list_pointer = VIRT_TO_BUS(&scb->sg_list[0]);
-      hscb->data_count = scb->sg_list[0].length | (SCB_LIST_NULL << 24);
-      hscb->data_pointer = VIRT_TO_BUS(cmd->request_buffer);
+      scb->sg_list[0].address = cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
+      scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen);
+      hscb->SG_list_pointer = cpu_to_le32(VIRT_TO_BUS(&scb->sg_list[0]));
+      hscb->data_count = scb->sg_list[0].length | cpu_to_le32(SCB_LIST_NULL << 24);
+      hscb->data_pointer = cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
     }
     else
     {
@@ -6447,7 +6311,7 @@
       scb->sg_count = 0;
       hscb->SG_list_pointer = 0;
       hscb->data_pointer = 0;
-      hscb->data_count = SCB_LIST_NULL << 24;
+      hscb->data_count = cpu_to_le32(SCB_LIST_NULL << 24);
     }
   }
 }
@@ -6594,7 +6458,7 @@
   pause_sequencer(p);
   while (inb(p->base + INTSTAT) & INT_PEND);
   {
-    aic7xxx_isr(p->irq, (void *) NULL, (void *) NULL);
+    aic7xxx_isr(p->irq, (void *) p, (void *) NULL);
     pause_sequencer(p);
   } 
   if ((cmd != scb->cmd) || ((scb->flags & SCB_ACTIVE) == 0))
@@ -6749,7 +6613,7 @@
       if (hscb_index == SCB_LIST_NULL)
       {
         disconnected = TRUE;
-        linked_next = (scb->hscb->data_count >> 24) & 0xFF;
+        linked_next = (le32_to_cpu(scb->hscb->data_count) >> 24) & 0xFF;
       }
       else
       {
@@ -6767,8 +6631,8 @@
          * linked next pointer.
          */
         scb->hscb->control |= ABORT_SCB | MK_MESSAGE;
-        scb->hscb->data_count &= ~0xFF000000;
-        scb->hscb->data_count |= linked_next << 24;
+        scb->hscb->data_count &= cpu_to_le32(~0xFF000000);
+        scb->hscb->data_count |= cpu_to_le32(linked_next << 24);
         if ((p->flags & PAGE_ENABLED) == 0)
         {
           scb->hscb->control &= ~DISCONNECTED;
@@ -6942,7 +6806,8 @@
 {
   struct aic7xxx_scb *scb = NULL;
   struct aic7xxx_host *p;
-  int    base, found, tindex, min_target, max_target;
+  unsigned long base;
+  int    found, tindex, min_target, max_target;
   int    result = -1;
   char   channel = 'A';
   unsigned long processor_flags;
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/aic7xxx.h linux/drivers/scsi/aic7xxx.h
--- v2.1.92/linux/drivers/scsi/aic7xxx.h	Sun Dec 21 17:04:48 1997
+++ linux/drivers/scsi/aic7xxx.h	Thu Apr  2 09:12:25 1998
@@ -25,6 +25,12 @@
 
 #define AIC7XXX_H_VERSION  "$Revision: 3.2 $"
 
+#ifdef __i386__
+#define AIC7XXX_BIOSPARAM	aic7xxx_biosparam
+#else
+#define AIC7XXX_BIOSPARAM	NULL
+#endif
+
 /*
  * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
  * to do with card config are filled in after the card is detected.
@@ -36,7 +42,7 @@
 	queuecommand:    aic7xxx_queue,						\
 	abort:           aic7xxx_abort,						\
 	reset:           aic7xxx_reset,						\
-	bios_param:      aic7xxx_biosparam,					\
+	bios_param:      AIC7XXX_BIOSPARAM,					\
 	can_queue:       -1,			/* max simultaneous cmds      */\
 	this_id:         -1,			/* scsi id of host adapter    */\
 	sg_tablesize:    SG_ALL,		/* max scatter-gather cmds    */\
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- v2.1.92/linux/drivers/scsi/aic7xxx_proc.c	Tue Dec  2 20:41:21 1997
+++ linux/drivers/scsi/aic7xxx_proc.c	Thu Apr  2 09:12:25 1998
@@ -86,45 +86,18 @@
 {
   struct Scsi_Host *HBAptr;
   struct aic7xxx_host *p;
-  int    found = FALSE;
   int    size = 0;
-  unsigned char i;
 #ifdef AIC7XXX_PROC_STATS
   struct aic7xxx_xferstats *sp;
   unsigned char target, lun;
+  int i;
 #endif
 
   HBAptr = NULL;
-  for (i=0; i < NUMBER(aic7xxx_boards); i++)
-  {
-    if ((HBAptr = aic7xxx_boards[i]) != NULL)
-    {
-      if (HBAptr->host_no == hostno)
-      {
-        break;
-      }
-
-      while ((HBAptr->hostdata != NULL) && !found &&
-          ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL))
-      {
-        if (HBAptr->host_no == hostno)
-        {
-          found = TRUE;
-        }
-      }
-
-      if (!found)
-      {
-        HBAptr = NULL;
-      }
-      else
-      {
-        break;
-      }
-    }
-  }
+  for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next)
+    ;
 
-  if (HBAptr == NULL)
+  if (!p)
   {
     size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
     if (size > length)
@@ -136,6 +109,7 @@
       return (length);
     }
   }
+  HBAptr = p->host;
 
   if (inout == TRUE) /* Has data been written to the file? */ 
   {
@@ -217,8 +191,8 @@
   size += sprintf(BLS, "                         (%s chipset)\n",
       chip_names[p->chip_class]);
   size += sprintf(BLS, "               Host Bus: %s\n", bus_names[p->bus_type]);
-  size += sprintf(BLS, "                Base IO: %#.4x\n", p->base);
-  size += sprintf(BLS, "         Base IO Memory: 0x%x\n", p->mbase);
+  size += sprintf(BLS, "                Base IO: 0x%lx\n", p->base);
+  size += sprintf(BLS, "         Base IO Memory: 0x%lx\n", p->mbase);
   size += sprintf(BLS, "                    IRQ: %d\n", HBAptr->irq);
   size += sprintf(BLS, "                   SCBs: Used %d, HW %d, Page %d\n",
       p->scb_data->numscbs, p->scb_data->maxhscbs, p->scb_data->maxscbs);
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.1.92/linux/drivers/scsi/eata.c	Mon Sep 15 09:41:09 1997
+++ linux/drivers/scsi/eata.c	Sun Apr  5 11:26:29 1998
@@ -1,6 +1,14 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *   
+ *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
+ *          io_port is now unsigned long.
+ *
+ *      17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88
+ *          Use new scsi error handling code (if linux version >= 2.1.88).
+ *          Use new interrupt code.
+ *
+ *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
@@ -127,7 +135,7 @@
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -331,9 +339,7 @@
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
-#undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
-#undef  DEBUG_SMP
 
 #define MAX_ISA 4
 #define MAX_VESA 0 
@@ -343,15 +349,14 @@
 #define MAX_CHANNEL 4
 #define MAX_LUN 32
 #define MAX_TARGET 32
-#define MAX_IRQ 16
 #define MAX_MAILBOXES 64
 #define MAX_SGLIST 64
-#define MAX_LARGE_SGLIST 252
+#define MAX_LARGE_SGLIST 122
 #define MAX_INTERNAL_RETRIES 64
 #define MAX_CMD_PER_LUN 2
 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)
 
-#define SKIP UINT_MAX
+#define SKIP ULONG_MAX
 #define FALSE 0
 #define TRUE 1
 #define FREE 0
@@ -415,15 +420,15 @@
    ulong  data_len;     /* Number of valid bytes after this field */
    ulong  sign;         /* ASCII "EATA" signature */
    unchar        :4,    /* unused low nibble */
-	  version:4;    /* EATA version, should be 0x1 */
+          version:4;    /* EATA version, should be 0x1 */
    unchar  ocsena:1,    /* Overlap Command Support Enabled */
-	   tarsup:1,    /* Target Mode Supported */
+           tarsup:1,    /* Target Mode Supported */
            trnxfr:1,    /* Truncate Transfer Cmd NOT Necessary */
            morsup:1,    /* More Supported */
-	   dmasup:1,    /* DMA Supported */
-	   drqvld:1,    /* DRQ Index (DRQX) is valid */
-	      ata:1,    /* This is an ATA device */
-	   haaval:1;    /* Host Adapter Address Valid */
+           dmasup:1,    /* DMA Supported */
+           drqvld:1,    /* DRQ Index (DRQX) is valid */
+              ata:1,    /* This is an ATA device */
+           haaval:1;    /* Host Adapter Address Valid */
    ushort cp_pad_len;   /* Number of pad bytes after cp_len */
    unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */
    ulong  cp_len;       /* Number of valid bytes in cp */
@@ -432,19 +437,19 @@
    ushort unused;
    ushort scatt_size;   /* Max number of entries in scatter/gather table */
    unchar     irq:4,    /* Interrupt Request assigned to this controller */
-	   irq_tr:1,    /* 0 for edge triggered, 1 for level triggered */
-	   second:1,    /* 1 if this is a secondary (not primary) controller */
-	     drqx:2;    /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */
+           irq_tr:1,    /* 0 for edge triggered, 1 for level triggered */
+           second:1,    /* 1 if this is a secondary (not primary) controller */
+             drqx:2;    /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */
    unchar  sync;        /* 1 if scsi target id 7...0 is running sync scsi */
 
    /* Structure extension defined in EATA 2.0B */
    unchar  isaena:1,    /* ISA i/o addressing is disabled/enabled */
-	 forcaddr:1,    /* Port address has been forced */
+         forcaddr:1,    /* Port address has been forced */
          large_sg:1,    /* 1 if large SG lists are supported */
              res1:1,
-		 :4;
+                 :4;
    unchar  max_id:5,    /* Max SCSI target ID number */
-	 max_chan:3;    /* Max SCSI channel number on this board */
+         max_chan:3;    /* Max SCSI channel number on this board */
 
    /* Structure extension defined in EATA 2.0C */
    unchar   max_lun;    /* Max SCSI LUN number */
@@ -463,17 +468,17 @@
 struct eata_config {
    ushort len;          /* Number of bytes following this field */
    unchar edis:1,       /* Disable EATA interface after config command */
-	 ocena:1,       /* Overlapped Commands Enabled */
-	mdpena:1,       /* Transfer all Modified Data Pointer Messages */
-	tarena:1,       /* Target Mode Enabled for this controller */
-	      :4;
+         ocena:1,       /* Overlapped Commands Enabled */
+        mdpena:1,       /* Transfer all Modified Data Pointer Messages */
+        tarena:1,       /* Target Mode Enabled for this controller */
+              :4;
    unchar cpad[511];
    };
 
 /* Returned status packet structure */
 struct mssp {
    unchar adapter_status:7,    /* State related to current command */
-		     eoc:1;    /* End Of Command (1 = command completed) */
+                     eoc:1;    /* End Of Command (1 = command completed) */
    unchar target_status;       /* SCSI status received after data transfer */
    unchar unused[2];
    ulong inv_res_len;          /* Number of bytes not transferred */
@@ -489,13 +494,13 @@
 /* MailBox SCSI Command Packet */
 struct mscp {
    unchar  sreset:1,     /* SCSI Bus Reset Signal should be asserted */
-	     init:1,     /* Re-initialize controller and self test */
-	   reqsen:1,     /* Transfer Request Sense Data to addr using DMA */
-	       sg:1,     /* Use Scatter/Gather */
-		 :1,
-	   interp:1,     /* The controller interprets cp, not the target */ 
-	     dout:1,     /* Direction of Transfer is Out (Host to Target) */
-	      din:1;     /* Direction of Transfer is In (Target to Host) */
+             init:1,     /* Re-initialize controller and self test */
+           reqsen:1,     /* Transfer Request Sense Data to addr using DMA */
+               sg:1,     /* Use Scatter/Gather */
+                 :1,
+           interp:1,     /* The controller interprets cp, not the target */ 
+             dout:1,     /* Direction of Transfer is Out (Host to Target) */
+              din:1;     /* Direction of Transfer is In (Target to Host) */
    unchar sense_len;     /* Request Sense Length */
    unchar unused[3];
    unchar  fwnest:1,     /* Send command to a component of an Array Group */
@@ -507,9 +512,9 @@
    unchar  target:5,     /* SCSI target ID */
           channel:3;     /* SCSI channel number */
    unchar     lun:5,     /* SCSI logical unit number */
-	   luntar:1,     /* This cp is for Target (not LUN) */
-	   dispri:1,     /* Disconnect Privilege granted */
-	      one:1;     /* 1 */
+           luntar:1,     /* This cp is for Target (not LUN) */
+           dispri:1,     /* Disconnect Privilege granted */
+              one:1;     /* 1 */
    unchar mess[3];       /* Massage to/from Target */
    unchar cdb[12];       /* Command Descriptor Block */
    ulong  data_len;      /* If sg=0 Data Length, if sg=1 sglist length */
@@ -526,7 +531,6 @@
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
    unsigned int last_cp_used;           /* Index of last mailbox used */
    unsigned int iocount;                /* Total i/o done for this board */
-   unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
@@ -542,9 +546,12 @@
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "EATA";
-static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
+static char sha[MAX_BOARDS];
 
-static unsigned int io_port[] __initdata = { 
+/* Initialize num_boards so that ihdlr can work while detect is in progress */
+static unsigned int num_boards = MAX_BOARDS;
+
+static unsigned long io_port[] __initdata = { 
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -665,7 +672,7 @@
    return;
 }
 
-static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
+static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {
 
    while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) {
       udelay(1L);
@@ -675,7 +682,7 @@
    return FALSE;
 }
 
-static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) {
+static inline int do_dma(unsigned long iobase, unsigned int addr, unchar cmd) {
 
    if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE;
 
@@ -690,7 +697,7 @@
    return FALSE;
 }
 
-static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
+static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) {
    unsigned int loop = MAXLOOP;
    ushort *p;
 
@@ -698,7 +705,7 @@
 
       while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) {
          udelay(1L);
-	 if (--loop == 0) return TRUE;
+         if (--loop == 0) return TRUE;
          }
 
       loop = MAXLOOP;
@@ -709,7 +716,7 @@
 }
 
 __initfunc (static inline int port_detect \
-      (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char protocol_rev;
    struct eata_info info;
@@ -723,7 +730,7 @@
    sprintf(name, "%s%d", driver_name, j);
 
    if(check_region(port_base, REGION_SIZE)) {
-      printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base);
+      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
       return FALSE;
       }
 
@@ -738,7 +745,7 @@
 
    if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
       printk("%s: config structure size (%ld bytes) too short, detaching.\n", 
-	     name, DEV2H(info.data_len));
+             name, DEV2H(info.data_len));
       return FALSE;
       }
    else if (DEV2H(info.data_len) == EATA_2_0A_SIZE)
@@ -774,7 +781,7 @@
       }
 
    if (!info.haaval || info.ata) {
-      printk("%s: address 0x%03x, unusable %s board (%d%d), detaching.\n",
+      printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n",
              name, port_base, bus_type, info.haaval, info.ata);
       return FALSE;
       }
@@ -782,7 +789,7 @@
    if (info.drqvld) {
 
       if (subversion ==  ESA)
-	 printk("%s: warning, weird %s board using DMA.\n", name, bus_type);
+         printk("%s: warning, weird %s board using DMA.\n", name, bus_type);
 
       subversion = ISA;
       dma_channel = dma_channel_table[3 - info.drqx];
@@ -790,7 +797,7 @@
    else {
 
       if (subversion ==  ISA)
-	 printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);
+         printk("%s: warning, weird %s board not using DMA.\n", name, bus_type);
 
       subversion = ESA;
       dma_channel = NO_DMA;
@@ -803,19 +810,20 @@
 
    if (subversion == ESA && !info.irq_tr)
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
-	     name, irq);
+             name, irq);
 
-   /* Board detected, allocate its IRQ if not already done */
-   if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq,
-              eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
+   /* Board detected, allocate its IRQ */
+   if (request_irq(irq, eata2x_interrupt_handler,
+             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
+             driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
       return FALSE;
       }
 
    if (subversion == ISA && request_dma(dma_channel, driver_name)) {
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
-	     name, dma_channel);
-      free_irq(irq, NULL);
+             name, dma_channel);
+      free_irq(irq, &sha[j]);
       return FALSE;
       }
 
@@ -840,7 +848,7 @@
    if (sh[j] == NULL) {
       printk("%s: unable to register host, detaching.\n", name);
 
-      if (!irqlist[irq]) free_irq(irq, NULL);
+      free_irq(irq, &sha[j]);
 
       if (subversion == ISA) free_dma(dma_channel);
 
@@ -865,7 +873,6 @@
    HD(j)->subversion = subversion;
    HD(j)->protocol_rev = protocol_rev;
    HD(j)->board_number = j;
-   irqlist[irq]++;
 
    if (HD(j)->subversion == ESA)
       sh[j]->unchecked_isa_dma = FALSE;
@@ -937,10 +944,11 @@
       }
    else                                 tag_type = 'n';
 
-   printk("%s: 2.0%c, %s 0x%03x, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\
-          "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type, sh[j]->io_port,
-          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
-          tag_type, YESNO(linked_comm), max_queue_depth);
+   printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\
+          "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type,
+          (unsigned long)sh[j]->io_port, sh[j]->irq, dma_name,
+          sh[j]->sg_tablesize, sh[j]->can_queue, tag_type, YESNO(linked_comm),
+          max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -1012,7 +1020,7 @@
    unsigned char bus, devfn;
    unsigned int addr, k;
 
-   if (!pcibios_present()) return;
+   if (!pci_present()) return;
 
    for (k = 0; k < MAX_PCI; k++) {
 
@@ -1056,11 +1064,6 @@
       }
 #endif
 
-   for (k = 0; k < MAX_IRQ; k++) {
-      irqlist[k] = 0;
-      calls[k] = 0;
-      }
-
    for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL;
 
    if (!setup_done) add_pci_ports();
@@ -1073,8 +1076,9 @@
       }
 
    if (j > 0) 
-      printk("EATA/DMA 2.0x: Copyright (C) 1994-1997 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
+   num_boards = j;
    restore_flags(flags);
    return j;
 }
@@ -1138,26 +1142,26 @@
       if (i >= sh[j]->can_queue) i = 0;
 
       if (HD(j)->cp_stat[i] == FREE) {
-	 HD(j)->last_cp_used = i;
-	 break;
-	 }
+         HD(j)->last_cp_used = i;
+         break;
+         }
       }
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
       if (HD(j)->in_reset) 
-	 printk("%s: qcomm, already in reset.\n", BN(j));
+         printk("%s: qcomm, already in reset.\n", BN(j));
       else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
                == SCSI_RESET_SUCCESS) 
-	 panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
+         panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    /* Set pointer to control packet structure */
@@ -1178,21 +1182,21 @@
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-			BN(j), i, SCpnt->channel, SCpnt->target,
+                        BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-	cpp->dout = TRUE;
-	break;
-	}
+        cpp->dout = TRUE;
+        break;
+        }
 
    if ((cpp->din = !cpp->dout))
       for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
-	   cpp->din = FALSE;
-	   break;
-	   }
+           cpp->din = FALSE;
+           break;
+           }
 
    cpp->reqsen = TRUE;
    cpp->dispri = TRUE;
@@ -1253,7 +1257,7 @@
              SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    HD(j)->cp_stat[i] = IN_USE;
@@ -1272,14 +1276,14 @@
    if (SCarg->host_scribble == NULL
        || SCarg->serial_number != SCarg->serial_number_at_timeout) {
       printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
-	     BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+             BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
    printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", 
-	  BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+          BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -1300,8 +1304,8 @@
       printk("%s: abort, mbox %d is in use.\n", BN(j), i);
 
       if (SCarg != HD(j)->cp[i].SCpnt)
-	 panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
-	       BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
+         panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
+               BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
 
       if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
@@ -1327,7 +1331,7 @@
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
       printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-	     BN(j), i, SCarg->pid);
+             BN(j), i, SCarg->pid);
       SCarg->scsi_done(SCarg);
       restore_flags(flags);
       return SCSI_ABORT_SUCCESS;
@@ -1347,7 +1351,7 @@
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
    printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
-	  BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
    if (SCarg->host_scribble == NULL)
@@ -1384,13 +1388,13 @@
       if (HD(j)->cp_stat[i] == FREE) continue;
 
       if (HD(j)->cp_stat[i] == LOCKED) {
-	 HD(j)->cp_stat[i] = FREE;
-	 printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
-	 continue;
-	 }
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
+         continue;
+         }
 
       if (!(SCpnt = HD(j)->cp[i].SCpnt))
-	 panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
       if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
          HD(j)->cp_stat[i] = ABORTING;
@@ -1405,13 +1409,13 @@
          }
 
       if (SCpnt->host_scribble == NULL)
-	 panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
+         panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
       if (*(unsigned int *)SCpnt->host_scribble != i) 
-	 panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
+         panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
       if (SCpnt->scsi_done == NULL) 
-	 panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
       }
@@ -1446,7 +1450,7 @@
          HD(j)->cp_stat[i] = LOCKED;
 
          printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-	        BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
@@ -1458,7 +1462,7 @@
          HD(j)->cp_stat[i] = FREE;
 
          printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-	        BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else
@@ -1640,229 +1644,200 @@
 
 }
 
-static void eata2x_interrupt_handler(int irq, void *dev_id,
+static void eata2x_interrupt_handler(int irq, void *shap,
                                      struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned long flags;
-   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, reg;
+   unsigned int i, j, k, c, status, tstatus, reg;
+   unsigned int n, n_ready, il[MAX_MAILBOXES];
    struct mssp *spp;
    struct mscp *cpp;
 
-   save_flags(flags);
-   cli();
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+ 
+   if (sh[j]->irq != irq)
+       panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
+ 
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
+ 
+   /* Check if this board need to be serviced */
+   if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return;
 
-   if (!irqlist[irq]) {
-      printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq);
-      restore_flags(flags);
-      return;
-      }
+   n_ready = 0;
 
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", 
-			driver_name, irq, calls[irq]);
+   /* Find the mailboxes to be serviced on this board */
+   for (i = 0; i < sh[j]->can_queue; i++) {
+      spp = &HD(j)->sp[i];
 
-   /* Service all the boards configured on this irq */
-   for (j = 0; sh[j] != NULL; j++) {
+      /* Check if this mailbox has completed the operation */
+      if (spp->eoc == FALSE) continue;
 
-      if (sh[j]->irq != irq) continue;
+      spp->eoc = FALSE;
+      il[n_ready++] = i;
+      }
 
-      loops = 0;
+   /* Read the status register to clear the interrupt indication */
+   reg = inb(sh[j]->io_port + REG_STATUS);
 
-      /* Loop until all interrupts for a board are serviced */
-      while (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) {
-	 total_loops++;
-	 loops++;
+   /* Mailbox service loop */
+   for (n = 0; n < n_ready; n++) {
+      i = il[n];
+      spp = &HD(j)->sp[i];
 
-	 if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
-			      BN(j), HD(j)->iocount);
-   
-	 /* Read the status register to clear the interrupt indication */
-	 reg = inb(sh[j]->io_port + REG_STATUS);
-   
-	 /* Service all mailboxes of this board */
-	 for (i = 0; i < sh[j]->can_queue; i++) {
-	    spp = &HD(j)->sp[i];
-   
-	    /* Check if this mailbox has completed the operation */
-	    if (spp->eoc == FALSE) continue;
-   
-	    spp->eoc = FALSE;
-   
-	    if (HD(j)->cp_stat[i] == IGNORE) {
-	       HD(j)->cp_stat[i] = FREE;
-	       continue;
-	       }
-	    else if (HD(j)->cp_stat[i] == LOCKED) {
-	       HD(j)->cp_stat[i] = FREE;
-	       printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
-		      BN(j), i, HD(j)->iocount);
-	       continue;
-	       }
-	    else if (HD(j)->cp_stat[i] == FREE) {
-	       printk("%s: ihdlr, mbox %d is free, count %d.\n", 
-		      BN(j), i, HD(j)->iocount);
-	       continue;
-	       }
-	    else if (HD(j)->cp_stat[i] == IN_RESET)
-	       printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-	    else if (HD(j)->cp_stat[i] != IN_USE) 
-	       panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
-   
-	    HD(j)->cp_stat[i] = FREE;
-	    cpp = &HD(j)->cp[i];
-	    SCpnt = spp->SCpnt;
-   
-	    if (SCpnt == NULL)
-	       panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
-   
-	    if (SCpnt != cpp->SCpnt)
-	       panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n",
-		     BN(j), i, SCpnt, cpp->SCpnt);
-   
-	    if (SCpnt->host_scribble == NULL)
-	       panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n",
-		     BN(j), i, SCpnt->pid, SCpnt);
-   
-	    if (*(unsigned int *)SCpnt->host_scribble != i) 
-	       panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\
-		     " irq %d.\n", BN(j), i, SCpnt->pid, 
-		     *(unsigned int *)SCpnt->host_scribble, irq);
-   
-         if (linked_comm && SCpnt->device->queue_depth > 2
-                                           && TLDEV(SCpnt->device->type))
-            flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
+      if (HD(j)->cp_stat[i] == IGNORE) {
+         HD(j)->cp_stat[i] = FREE;
+         return;
+         }
+      else if (HD(j)->cp_stat[i] == LOCKED) {
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+                HD(j)->iocount);
+         return;
+         }
+      else if (HD(j)->cp_stat[i] == FREE) {
+         printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+                HD(j)->iocount);
+         return;
+         }
+      else if (HD(j)->cp_stat[i] == IN_RESET)
+         printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+      else if (HD(j)->cp_stat[i] != IN_USE) 
+         panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
 
-	    tstatus = status_byte(spp->target_status);
-   
-	    switch (spp->adapter_status) {
-	       case ASOK:     /* status OK */
-   
-		  /* Forces a reset if a disk drive keeps returning BUSY */
-		  if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-		     status = DID_ERROR << 16;
-   
-		  /* If there was a bus reset, redo operation on each target */
-		  else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-     		           && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-		     status = DID_BUS_BUSY << 16;
-   
-		  /* Works around a flaw in scsi.c */
-		  else if (tstatus == CHECK_CONDITION
-			   && SCpnt->device->type == TYPE_DISK
-			   && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-		     status = DID_BUS_BUSY << 16;
+      HD(j)->cp_stat[i] = FREE;
+      cpp = &HD(j)->cp[i];
+      SCpnt = spp->SCpnt;
 
-		  else
-		     status = DID_OK << 16;
-   
-		  if (tstatus == GOOD)
-		     HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-   
-		  if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-		     printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                            "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-			    SCpnt->channel, SCpnt->target, SCpnt->lun, 
-                            SCpnt->pid, spp->target_status, 
-                            SCpnt->sense_buffer[2]);
-   
-		  HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-   
-                  if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+      if(SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
-		  break;
-	       case ASST:     /* Selection Time Out */
-	       case 0x02:     /* Command Time Out   */
-   
-		  if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-		     status = DID_ERROR << 16;
-		  else {
-		     status = DID_TIME_OUT << 16;
-		     HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-		     }
-   
-		  break;
+      if (SCpnt != cpp->SCpnt)
+         panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", BN(j), i,
+               SCpnt, cpp->SCpnt);
 
-               /* Perform a limited number of internal retries */
-	       case 0x03:     /* SCSI Bus Reset Received */
-	       case 0x04:     /* Initial Controller Power-up */
-   
-		  for (c = 0; c <= sh[j]->max_channel; c++) 
-		     for (k = 0; k < sh[j]->max_id; k++) 
-		        HD(j)->target_redo[k][c] = TRUE;
-   
-	          if (SCpnt->device->type != TYPE_TAPE
-                      && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-		     status = DID_BUS_BUSY << 16;
-		     HD(j)->retries++;
-                     HD(j)->last_retried_pid = SCpnt->pid;
-                     }
-	          else 
-		     status = DID_ERROR << 16;
-
-		  break;
-	       case 0x05:     /* Unexpected Bus Phase */
-	       case 0x06:     /* Unexpected Bus Free */
-	       case 0x07:     /* Bus Parity Error */
-	       case 0x08:     /* SCSI Hung */
-	       case 0x09:     /* Unexpected Message Reject */
-	       case 0x0a:     /* SCSI Bus Reset Stuck */
-	       case 0x0b:     /* Auto Request-Sense Failed */
-	       case 0x0c:     /* Controller Ram Parity Error */
-	       default:
-		  status = DID_ERROR << 16;
-		  break;
-	       }
-   
-	    SCpnt->result = status | spp->target_status;
-	    HD(j)->iocount++;
+      if (SCpnt->host_scribble == NULL)
+         panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+               SCpnt->pid, SCpnt);
 
-	    if (loops > 1) HD(j)->multicount++;
+      if (*(unsigned int *)SCpnt->host_scribble != i) 
+         panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n",
+              BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
+
+      if (linked_comm && SCpnt->device->queue_depth > 2
+                                        && TLDEV(SCpnt->device->type))
+      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
+
+      tstatus = status_byte(spp->target_status);
+
+      switch (spp->adapter_status) {
+         case ASOK:     /* status OK */
+
+            /* Forces a reset if a disk drive keeps returning BUSY */
+            if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+               status = DID_ERROR << 16;
+
+            /* If there was a bus reset, redo operation on each target */
+            else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                     && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+               status = DID_BUS_BUSY << 16;
+
+            /* Works around a flaw in scsi.c */
+            else if (tstatus == CHECK_CONDITION
+                     && SCpnt->device->type == TYPE_DISK
+                     && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+               status = DID_BUS_BUSY << 16;
+
+            else
+               status = DID_OK << 16;
+
+            if (tstatus == GOOD)
+               HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
+
+            if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+               printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                      "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                      SCpnt->channel, SCpnt->target, SCpnt->lun, 
+                      SCpnt->pid, spp->target_status, 
+                      SCpnt->sense_buffer[2]);
+
+            HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
+
+            if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+
+            break;
+         case ASST:     /* Selection Time Out */
+         case 0x02:     /* Command Time Out   */
+
+            if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
+               status = DID_ERROR << 16;
+            else {
+               status = DID_TIME_OUT << 16;
+               HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+               }
+
+            break;
+
+         /* Perform a limited number of internal retries */
+         case 0x03:     /* SCSI Bus Reset Received */
+         case 0x04:     /* Initial Controller Power-up */
+
+            for (c = 0; c <= sh[j]->max_channel; c++) 
+               for (k = 0; k < sh[j]->max_id; k++) 
+                  HD(j)->target_redo[k][c] = TRUE;
+
+            if (SCpnt->device->type != TYPE_TAPE
+                && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+               status = DID_BUS_BUSY << 16;
+               HD(j)->retries++;
+               HD(j)->last_retried_pid = SCpnt->pid;
+               }
+            else 
+               status = DID_ERROR << 16;
+
+            break;
+         case 0x05:     /* Unexpected Bus Phase */
+         case 0x06:     /* Unexpected Bus Free */
+         case 0x07:     /* Bus Parity Error */
+         case 0x08:     /* SCSI Hung */
+         case 0x09:     /* Unexpected Message Reject */
+         case 0x0a:     /* SCSI Bus Reset Stuck */
+         case 0x0b:     /* Auto Request-Sense Failed */
+         case 0x0c:     /* Controller Ram Parity Error */
+         default:
+            status = DID_ERROR << 16;
+            break;
+         }
+
+      SCpnt->result = status | spp->target_status;
+      HD(j)->iocount++;
 
 #if defined (DEBUG_INTERRUPT)
-	    if (SCpnt->result || do_trace)
+      if (SCpnt->result || do_trace)
 #else
-	    if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-		(spp->adapter_status != ASOK && 
-		spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-		do_trace || msg_byte(spp->target_status))
+      if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+          (spp->adapter_status != ASOK && 
+          spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+          do_trace || msg_byte(spp->target_status))
 #endif
-	       printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-		      " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-		      BN(j), i, spp->adapter_status, spp->target_status,
-		      SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                      reg, HD(j)->iocount);
-   
-	    /* Set the command state to inactive */
-	    SCpnt->host_scribble = NULL;
-   
-	    restore_flags(flags);
-	    SCpnt->scsi_done(SCpnt);
-	    cli();
-
-	    }   /* Mailbox loop */
+         printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+                " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+                BN(j), i, spp->adapter_status, spp->target_status,
+                SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+                reg, HD(j)->iocount);
 
-	 }   /* Multiple command loop */
-
-      }   /* Boards loop */
+      /* Set the command state to inactive */
+      SCpnt->host_scribble = NULL;
 
-   calls[irq]++;
+      SCpnt->scsi_done(SCpnt);
 
-#if defined (DEBUG_SMP)
-   if (total_loops == 0) 
-     printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
-	    driver_name, irq, calls[irq]);
-#endif
+      }   /* Mailbox loop */
 
-   if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", 
-			driver_name, irq, calls[irq]);
+   if (n_ready > 1)
+      printk("%s: ihdlr, multiple commands (%d) completed.\n", BN(j), n_ready);
 
-#if defined (DEBUG_STATISTICS)
-   if ((calls[irq] % 100000) == 10000)
-      for (j = 0; sh[j] != NULL; j++)
-	 printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j),
-		calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount);
-#endif
+   if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-   restore_flags(flags);
    return;
 }
 
@@ -1881,7 +1856,7 @@
    for (i = 0; i < sh[j]->can_queue; i++) 
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
-   if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL);
+   free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v2.1.92/linux/drivers/scsi/eata.h	Sun Dec 21 17:04:48 1997
+++ linux/drivers/scsi/eata.h	Sun Apr  5 11:26:29 1998
@@ -1,5 +1,5 @@
 /*
- *	eata.h - used by the low-level driver for EATA/DMA SCSI host adapters.
+ *        eata.h - used by the low-level driver for EATA/DMA SCSI host adapters.
  */
 #ifndef _EATA_H
 #define _EATA_H
@@ -12,19 +12,41 @@
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "3.11.00"
+#define EATA_VERSION "4.02.00"
 
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,88)
+
+#define EATA {                                                               \
+                name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
+                detect:            eata2x_detect,                            \
+                release:           eata2x_release,                           \
+                queuecommand:      eata2x_queuecommand,                      \
+                abort:             eata2x_abort,                             \
+                reset:             eata2x_reset,                             \
+                bios_param:        scsicam_bios_param,                       \
+                this_id:           7,                                        \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering:    ENABLE_CLUSTERING,                        \
+                use_new_eh_code: 1    /* Enable new error code */            \
+             }
+
+#else /* Use old scsi code */
+
+#define EATA {                                                               \
+                name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
+                detect:            eata2x_detect,                            \
+                release:           eata2x_release,                           \
+                queuecommand:      eata2x_queuecommand,                      \
+                abort:             eata2x_abort,                             \
+                reset:             eata2x_reset,                             \
+                bios_param:        scsicam_bios_param,                       \
+                this_id:           7,                                        \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering:    ENABLE_CLUSTERING                         \
+             }
+
+#endif
 
-#define EATA {									\
-		name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",      \
-		detect:            eata2x_detect,				\
-		release:           eata2x_release,          		        \
-		queuecommand:      eata2x_queuecommand,			        \
-		abort:             eata2x_abort,				\
-		reset:             eata2x_reset,				\
-		bios_param:        scsicam_bios_param,   			\
-		this_id:           7,   /* this_id, reset by detect */          \
-		unchecked_isa_dma: 1,   /* unchecked isa dma, reset by detect */\
-		use_clustering:    ENABLE_CLUSTERING                            \
-		}
 #endif
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v2.1.92/linux/drivers/scsi/eata_dma.c	Mon Oct 28 14:31:24 1996
+++ linux/drivers/scsi/eata_dma.c	Thu Apr  2 09:12:25 1998
@@ -1406,7 +1406,7 @@
     u32 error, i, x;
     u8 pal1, pal2, pal3;
 
-    if (pcibios_present()) {
+    if (pci_present()) {
 	for (i = 0; i <= MAXPCI; ++i, ++pci_index) {
 	    if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, 
 				    pci_index, &pci_bus, &pci_device_fn))
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c
--- v2.1.92/linux/drivers/scsi/eata_pio.c	Thu Aug  1 05:43:04 1996
+++ linux/drivers/scsi/eata_pio.c	Thu Apr  2 09:12:25 1998
@@ -880,7 +880,7 @@
     u16 rev_device;
     u32 error, i, x;
 
-    if (pcibios_present()) {
+    if (pci_present()) {
 	for (i = 0; i <= MAXPCI; ++i, ++pci_index) {
 	    if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, 
 				    pci_index, &pci_bus, &pci_device_fn))
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.1.92/linux/drivers/scsi/fdomain.c	Fri Nov  7 10:16:36 1997
+++ linux/drivers/scsi/fdomain.c	Thu Apr  2 09:12:25 1998
@@ -20,6 +20,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
 
+ * PCI detection rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
  **************************************************************************
 
  SUMMARY:
@@ -266,7 +268,6 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/proc_fs.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/stat.h>
 
@@ -749,168 +750,63 @@
    return 1;			/* success */
 }
 
-static int fdomain_pci_nobios_detect( int *irq, int *iobase )
-{
-   int i;
-   int flag = 0;
-
-   /* The proper way of doing this is to use ask the PCI bus for the device
-      IRQ and interrupt level.  But we can't do that if PCI BIOS32 support
-      isn't compiled into the kernel, or if a PCI BIOS32 isn't present.
-
-      Instead, we scan down a bunch of addresses (Future Domain tech
-      support says we will probably find the address before we get to
-      0xf800).  This works fine on some systems -- other systems may have
-      to scan more addresses.  If you have to modify this section for your
-      installation, please send mail to faith@cs.unc.edu. */
-
-   for (i = 0xfff8; i > 0xe000; i -= 8) {
-      if (check_region( i, 0x10 )) {
-#if DEBUG_DETECT
-	 printk( " (%x inuse)," , i );
-#endif
-	 continue;
-      }
-      if ((flag = fdomain_is_valid_port( i ))) break;
-   }
-
-   if (!flag) return 0;		/* iobase not found */
-
-   *irq    = fdomain_get_irq( i );
-   *iobase = i;
-
-   return 1;			/* success */
-}
-
 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
    iobase) This function gets the Interrupt Level and I/O base address from
-   the PCI configuration registers.  The I/O base address is masked with
-   0xfff8 since on my card the address read from the PCI config registers
-   is off by one from the actual I/O base address necessary for accessing
-   the status and control registers on the card (PCI config register gives
-   0xf801, actual address is 0xf800).  This is likely a bug in the FD
-   config code that writes to the PCI registers, however using a mask
-   should be safe since I think the scan done by the card to determine the
-   I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at
-   least the old scan code we used to use to get the I/O base did...  Also,
-   the device ID from the PCI config registers is 0x0 and should be 0x60e9
-   as it is in the status registers (offset 5 from I/O base).  If this is
-   changed in future hardware/BIOS changes it will need to be fixed in this
-   detection function.  Comments, bug reports, etc... on this function
-   should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley.  */
+   the PCI configuration registers. */
 
 #ifdef CONFIG_PCI
 static int fdomain_pci_bios_detect( int *irq, int *iobase )
 {
-   int              error;
-   unsigned char    pci_bus, pci_dev_fn;    /* PCI bus & device function */
-   unsigned char    pci_irq;                /* PCI interrupt line */
-   unsigned int     pci_base;               /* PCI I/O base address */
-   unsigned short   pci_vendor, pci_device; /* PCI vendor & device IDs */
-
-   /* If the PCI BIOS doesn't exist, use the old-style detection routines.
-      Otherwise, get the I/O base address and interrupt from the PCI config
-      registers. */
-   
-   if (!pcibios_present()) return fdomain_pci_nobios_detect( irq, iobase );
+   unsigned int     pci_irq;                /* PCI interrupt line */
+   unsigned long    pci_base;               /* PCI I/O base address */
+   struct pci_dev   *pdev = NULL;
+
+   if (!pci_present()) return 0;
 
 #if DEBUG_DETECT
    /* Tell how to print a list of the known PCI devices from bios32 and
       list vendor and device IDs being used if in debug mode.  */
       
-   printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" );
+   printk( "\nINFO: use lspci -v to see list of PCI devices\n" );
    printk( "\nTMC-3260 detect:"
 	   " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
 	   PCI_VENDOR_ID_FD, 
 	   PCI_DEVICE_ID_FD_36C70 );
 #endif 
 
-   /* We will have to change this if more than 1 PCI bus is present and the
-      FD scsi host is not on the first bus (i.e., a PCI to PCI bridge,
-      which is not supported by bios32 right now anyway).  This should
-      probably be done by a call to pcibios_find_device but I can't get it
-      to work...  Also the device ID reported from the PCI config registers
-      does not match the device ID quoted in the tech manual or available
-      from offset 5 from the I/O base address.  It should be 0x60E9, but it
-      is 0x0 if read from the PCI config registers.  I guess the FD folks
-      neglected to write it to the PCI registers...  This loop is necessary
-      to get the device function (at least until someone can get
-      pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */
-    
-   pci_bus = 0;
-
-   for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) {
-      pcibios_read_config_word( pci_bus,
-				pci_dev_fn,
-				PCI_VENDOR_ID,
-				&pci_vendor );
-
-      if (pci_vendor == PCI_VENDOR_ID_FD) {
-	 pcibios_read_config_word( pci_bus,
-				   pci_dev_fn,
-				   PCI_DEVICE_ID,
-				   &pci_device );
-
-	 if (pci_device == PCI_DEVICE_ID_FD_36C70) {
-	    /* Break out once we have the correct device.  If other FD
-	       PCI devices are added to this driver we will need to add
-	       an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */
-	    break;
-	 } else {
-	    /* If we can't find an FD scsi card we give up. */
-	    return 0;
-	 }
-      }
-   }
+   if ((pdev = pci_find_device(PCI_VENDOR_ID, PCI_DEVICE_ID, pdev)) == NULL)
+     return 0;
        
 #if DEBUG_DETECT
    printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
-	   pci_bus,
-	   (pci_dev_fn & 0xf8) >> 3, 
-	   pci_dev_fn & 7 );
+	   pdev->bus->number,
+	   PCI_SLOT(pdev->devfn),
+	   PCI_FUNC(pdev->devfn));
 #endif
 
    /* We now have the appropriate device function for the FD board so we
       just read the PCI config info from the registers.  */
 
-   if ((error = pcibios_read_config_dword( pci_bus,
-					   pci_dev_fn, 
-					   PCI_BASE_ADDRESS_0,
-					   &pci_base ))
-       || (error = pcibios_read_config_byte( pci_bus,
-					     pci_dev_fn, 
-					     PCI_INTERRUPT_LINE,
-					     &pci_irq ))) {
-      printk ( "PCI ERROR: Future Domain 36C70 not initializing"
-	       " due to error reading configuration space\n" );
-      return 0;
-   } else {
+   pci_base = pdev->base_address[0];
+   pci_irq = pdev->irq;
 #if DEBUG_DETECT
       printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", 
 	      pci_irq, pci_base );
 #endif
 
-      /* Now we have the I/O base address and interrupt from the PCI
-	 configuration registers.  Unfortunately it seems that the I/O base
-	 address is off by one on my card so I mask it with 0xfff8.  This
-	 must be some kind of goof in the FD code that does the autoconfig
-	 and writes to the PCI registers (or maybe I just don't understand
-	 something).  If they fix it in later versions of the card or BIOS
-	 we may have to adjust the address based on the signature or
-	 something...  */
+   /* Now we have the I/O base address and interrupt from the PCI
+      configuration registers. */
 
-      *irq    = pci_irq;
-      *iobase = (pci_base & 0xfff8);
+   *irq    = pci_irq;
+   *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);
 
 #if DEBUG_DETECT
-      printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); 
-      printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
+   printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); 
+   printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
 #endif
 
-      if (!fdomain_is_valid_port( *iobase )) return 0;
-      return 1;
-   }
-   return 0;
+   if (!fdomain_is_valid_port( *iobase )) return 0;
+   return 1;
 }
 #endif
 
@@ -978,7 +874,8 @@
 #ifdef CONFIG_PCI
 	 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
 #else
-	 flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base );
+	 printk(KERN_ERR "No PCI support in this kernel, giving up.\n");
+	 flag = 0;
 #endif
       }
 	 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- v2.1.92/linux/drivers/scsi/gdth.c	Tue Nov  4 09:17:30 1997
+++ linux/drivers/scsi/gdth.c	Thu Apr  2 09:12:25 1998
@@ -23,6 +23,19 @@
  * Tested with Linux 1.2.13, ..., 2.1.61                                *
  *                                                                      *
  * $Log: gdth.c,v $
+ * Revision 1.3  1998/02/25 23:52:32  ecd
+ * Final round of PCI device driver patches by Martin Mares.
+ *
+ * I could not verify each and every change to the drivers locally,
+ * please consult linux/Documentation/pci.txt to understand changes
+ * made in case patching should be necessary.
+ *
+ * Revision 1.2  1997/11/12 23:58:51  davem
+ * Merge to 2.1.63 to get the Ingo P5 bugfix.
+ * I did not touch the sound changes at all, Alan
+ * please look into that stuff as it is your
+ * territory.
+ *
  * Revision 1.10  1997/10/31 12:29:57  achim
  * Read heads/sectors from host drive
  *
@@ -60,7 +73,7 @@
  * Initial revision
  *
  *
- * $Id: gdth.c,v 1.10 1997/10/31 12:29:57 achim Exp $ 
+ * $Id: gdth.c,v 1.3 1998/02/25 23:52:32 ecd Exp $ 
  ************************************************************************/
 
 #ifdef MODULE
@@ -71,7 +84,6 @@
 #include <linux/kernel.h>
 #include <linux/head.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -83,6 +95,8 @@
 #include <linux/timer.h>
 #if LINUX_VERSION_CODE >= 0x020100
 #include <linux/reboot.h>
+#else
+#include <linux/bios32.h>
 #endif
 
 #include <asm/dma.h>
@@ -440,7 +454,7 @@
     TRACE(("gdth_search_pci() device_id %d, index %d\n",
                  device_id,index));
 
-    if (!pcibios_present())
+    if (!pci_present())
         return 0;
 
     if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index,
@@ -448,6 +462,22 @@
         return 0;
 
     /* GDT PCI controller found, now read resources from config space */
+#if LINUX_VERSION_CODE >= 0x20155
+    {
+	struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn);
+	base0 = pdev->base_address[0];
+	base1 = pdev->base_address[1];
+	base2 = pdev->base_address[2];
+	if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
+                                           PCI_ROM_ADDRESS,
+                                           (int *) &pcistr->bios))) {
+		printk("GDT-PCI: error %s reading configuration space",
+		       pcibios_strerror(error));
+		return -1;
+		}
+	pcistr->irq = pdev->irq;
+    }
+#else
 #if LINUX_VERSION_CODE >= 0x010300
 #define GDTH_BASEP      (int *)
 #else
@@ -471,6 +501,7 @@
                pcibios_strerror(error));
         return -1;
     }
+#endif
 
     pcistr->device_id = device_id;
     if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000 or GDT6000B */
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- v2.1.92/linux/drivers/scsi/in2000.c	Thu Jul 17 20:24:38 1997
+++ linux/drivers/scsi/in2000.c	Wed Apr  1 20:41:12 1998
@@ -123,8 +123,8 @@
 #include "hosts.h"
 
 
-#define IN2000_VERSION    "1.31"
-#define IN2000_DATE       "06/July/1997"
+#define IN2000_VERSION    "1.32"
+#define IN2000_DATE       "28/March/1998"
 
 /*
  * Note - the following defines have been moved to 'in2000.h':
@@ -2031,18 +2031,12 @@
          continue;
          }
 
-/* Let's expect only known legal hardware version here. There
- * can't be THAT many of them, and it's easy to add new ones
- * as we hear about them.
+/* Let's assume any hardware version will work, although the driver
+ * has only been tested on 0x21, 0x22, 0x25, 0x26, and 0x27. We'll
+ * print out the rev number for reference later, but accept them all.
  */
 
       hrev = inb(base + IO_HARDWARE);
-      if ((hrev != 0x27) && (hrev != 0x26) && (hrev != 0x25)) {
-         printk("The IN-2000 SCSI card at IOport 0x%03x ",base);
-         printk("has unknown version %02x hardware - ",hrev);
-         printk("Sorry, cancelling detection.\n");
-         continue;
-         }
 
   /* Bit 2 tells us if interrupts are disabled */
       if (switches & SW_DISINT) {
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- v2.1.92/linux/drivers/scsi/in2000.h	Fri Feb  6 15:33:40 1998
+++ linux/drivers/scsi/in2000.h	Mon Apr  6 11:51:22 1998
@@ -2,7 +2,7 @@
  *    in2000.h -  Linux device driver definitions for the
  *                Always IN2000 ISA SCSI card.
  *
- *    IMPORTANT: This file is for version 1.31 - 06/Jul/1997
+ *    IMPORTANT: This file is for version 1.32 - 28/Mar/1998
  *
  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
  *    john@geolog.com
@@ -404,8 +404,8 @@
                   this_id:         IN2000_HOST_ID,      /* host-adapter scsi id */ \
                   sg_tablesize:    IN2000_SG,           /* scatter-gather table size */ \
                   cmd_per_lun:     IN2000_CPL,          /* commands per lun */ \
-                  use_clustering:  DISABLE_CLUSTERING, \
-		  use_new_eh_code: 0			/* Enable new error code */ \
+                  use_clustering:  DISABLE_CLUSTERING,  /* ENABLE_CLUSTERING may speed things up */ \
+                  use_new_eh_code: 0                    /* new error code - not using it yet */ \
                 }
 
 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.92/linux/drivers/scsi/ncr53c8xx.c	Wed Apr  1 20:11:53 1998
+++ linux/drivers/scsi/ncr53c8xx.c	Thu Apr  2 09:12:25 1998
@@ -116,7 +116,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
@@ -136,6 +135,7 @@
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35)
 #include <linux/init.h>
 #else
+#include <linux/bios32.h>
 #ifndef	__initdata
 #define	__initdata
 #endif
@@ -275,8 +275,12 @@
 typedef	u_long		vm_offset_t;
 typedef	int		vm_size_t;
 
+#ifndef bcopy
 #define bcopy(s, d, n)	memcpy((d), (s), (n))
+#endif
+#ifndef bzero
 #define bzero(d, n)	memset((d), 0, (n))
+#endif
 
 #ifndef offsetof
 #define offsetof(t, m)	((size_t) (&((t *)0)->m))
@@ -309,6 +313,12 @@
 **	architecture.
 */
 
+#ifdef __sparc__
+#define remap_pci_mem(base, size)	((vm_offset_t) __va(base))
+#define unmap_pci_mem(vaddr, size)
+#define pcivtophys(p)			((p) & pci_dvma_mask)
+#else	/* __sparc__ */
+#define pcivtophys(p)			(p)
 #ifndef NCR_IOMAPPED
 __initfunc(
 static vm_offset_t remap_pci_mem(u_long base, u_long size)
@@ -337,6 +347,7 @@
 #endif
 }
 #endif	/* !NCR_IOMAPPED */
+#endif	/* __sparc__ */
 
 #else /* linux-1.2.13 */
 
@@ -1795,8 +1806,8 @@
 	**	Profiling data
 	*/
 	struct profile	profile;
-	u_long		disc_phys;
-	u_long		disc_ref;
+	u_int		disc_phys;
+	u_int		disc_ref;
 
 	/*
 	**	The global control block.
@@ -1839,7 +1850,7 @@
 	/*
 	**	irq level
 	*/
-	u_short		irq;
+	u_int		irq;
 };
 
 #define NCB_SCRIPT_PHYS(np,lbl)	 (np->p_script  + offsetof (struct script, lbl))
@@ -3795,7 +3806,8 @@
 
 				switch (old & RELOC_MASK) {
 				case RELOC_REGISTER:
-					new = (old & ~RELOC_MASK) + np->paddr;
+					new = (old & ~RELOC_MASK)
+							+ pcivtophys(np->paddr);
 					break;
 				case RELOC_LABEL:
 					new = (old & ~RELOC_MASK) + np->p_script;
@@ -4388,9 +4400,15 @@
 	u_long flags = 0;
 	ncr_nvram *nvram = device->nvram;
 
+#ifdef __sparc__
+printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=0x%x\n",
+	device->chip.name, unit, device->chip.revision_id, device->slot.base,
+	device->slot.io_port, device->slot.irq);
+#else
 printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
 	device->chip.name, unit, device->chip.revision_id, device->slot.base,
 	device->slot.io_port, device->slot.irq);
+#endif
 
 	/*
 	**	Allocate host_data structure
@@ -4543,7 +4561,7 @@
 	np->p_scripth	= vtophys(np->scripth);
 
 	np->script	= (np->vaddr2) ? (struct script *) np->vaddr2 : np->script0;
-	np->p_script	= (np->vaddr2) ? np->paddr2 : vtophys(np->script0);
+	np->p_script	= (np->vaddr2) ? pcivtophys(np->paddr2) : vtophys(np->script0);
 
 	ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script));
 	ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth));
@@ -4618,7 +4636,7 @@
 	**	Then enable disconnects.
 	*/
 	save_flags(flags); cli();
-	if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) {
+	if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) {
 		printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np));
 		restore_flags(flags);
 		goto attach_error;
@@ -5504,8 +5522,12 @@
 */
 
 #ifdef DEBUG_NCR53C8XX
+#ifdef __sparc__
+	printf("%s: freeing irq 0x%x\n", ncr_name(np), np->irq);
+#else
 	printf("%s: freeing irq %d\n", ncr_name(np), np->irq);
 #endif
+#endif
 #if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
 	free_irq(np->irq, np);
 #else
@@ -5812,8 +5834,14 @@
 		**  Announce changes to the generic driver.
 		*/
 		if (tp->numtags) {
+			/*
+			 * Decrease tp->maxtags (ecd, 980110)
+			 */
+			tp->maxtags = tp->numtags - 1;
+
 			PRINT_ADDR(cmd);
-			printf("QUEUE FULL! suspending tagged command queueing\n");
+			printf("QUEUE FULL! suspending tagged command queueing (setting maxtags to %d)\n", tp->maxtags);
+
 			tp->numtags	= 0;
 			tp->num_good	= 0;
 			if (lp) {
@@ -7317,10 +7345,10 @@
 
 	if (dsp == vtophys (&cp->patch[2])) {
 		vdsp = &cp->patch[0];
-		nxtdsp = vdsp[3];
+		nxtdsp = scr_to_cpu(vdsp[3]);
 	} else if (dsp == vtophys (&cp->patch[6])) {
 		vdsp = &cp->patch[4];
-		nxtdsp = vdsp[3];
+		nxtdsp = scr_to_cpu(vdsp[3]);
 	} else if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) {
 		vdsp = (u_int32 *) ((char*)np->script - np->p_script + dsp -8);
 		nxtdsp = dsp;
@@ -8233,13 +8261,13 @@
 			cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1));
 		tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval));
 		tp->getscr[2] =
-		cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer));
+		cpu_to_scr(pcivtophys(np->paddr) + offsetof (struct ncr_reg, nc_sxfer));
 
 		tp->getscr[3] =	(np->features & FE_PFEN) ?
 			cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1));
 		tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval));
 		tp->getscr[5] =
-		cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3));
+		cpu_to_scr(pcivtophys(np->paddr) + offsetof (struct ncr_reg, nc_scntl3));
 
 		assert (( (offsetof(struct ncr_reg, nc_sxfer) ^
 			offsetof(struct tcb    , sval    )) &3) == 0);
@@ -8635,8 +8663,8 @@
 #define PROFILE  cp->phys.header.stamp
 static	void ncb_profile (ncb_p np, ccb_p cp)
 {
-	int co, st, en, di, se, post,work,disc;
-	u_long diff;
+	long co, st, en, di, se, post, work, disc;
+	u_int diff;
 
 	PROFILE.end = jiffies;
 
@@ -8659,7 +8687,7 @@
 
 	work = (st - co) - disc;
 
-	diff = (np->disc_phys - np->disc_ref) & 0xff;
+	diff = (scr_to_cpu(np->disc_phys) - np->disc_ref) & 0xff;
 	np->disc_ref += diff;
 
 	np->profile.num_trans	+= 1;
@@ -9085,7 +9113,7 @@
 	int i, j;
 	int attach_count = 0;
 	ncr_nvram  *nvram;
-	ncr_device *devp;
+	ncr_device *devp = 0;	/* to shut up gcc */
 
 	if (!nvram_index)
 		return 0;
@@ -9211,7 +9239,7 @@
 	** the order they are detected.
 	*/
 
-	if (!pcibios_present())
+	if (!pci_present())
 		return 0;
 
 	chips	= sizeof(ncr_chip_ids)	/ sizeof(ncr_chip_ids[0]);
@@ -9295,14 +9323,17 @@
 {
 	ushort vendor_id, device_id, command;
 	uchar cache_line_size, latency_timer;
-	uchar irq, revision;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
-	ulong base, base_2, io_port;
+	uchar revision;
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
 	struct pci_dev *pdev;
-#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
+	ulong base, base_2, io_port; 
+	uint irq;
+#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) 
+	uchar irq;
 	uint base, base_2, io_port; 
 #else
-	ulong base, base_2; 
+	uchar irq;
+	ulong base, base_2, io_port; 
 #endif
 	int i;
 
@@ -9312,7 +9343,7 @@
 	ncr_chip *chip;
 
 	printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
-		bus, PCI_SLOT(device_fn), PCI_FUNC(device_fn));
+		bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
 	/*
 	 * Read info from the PCI config space.
 	 * pcibios_read_config_xxx() functions are assumed to be used for 
@@ -9326,12 +9357,12 @@
 					PCI_DEVICE_ID, &device_id);
 	(void) pcibios_read_config_word(bus, device_fn,
 					PCI_COMMAND, &command);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
-	pdev = pci_find_dev(bus, device_fn);
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
+	pdev = pci_find_slot(bus, device_fn);
 	io_port = pdev->base_address[0];
-	base    = pdev->base_address[1];
-	base_2  = pdev->base_address[2];
-	irq     = pdev->irq;
+	base = pdev->base_address[1];
+	base_2 = pdev->base_address[2];
+	irq = pdev->irq;
 #else
 	(void) pcibios_read_config_dword(bus, device_fn,
 					PCI_BASE_ADDRESS_0, &io_port);	
@@ -9343,7 +9374,7 @@
 					PCI_INTERRUPT_LINE, &irq);
 #endif
 	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_CLASS_REVISION, &revision);	
+					PCI_CLASS_REVISION,&revision);	
 	(void) pcibios_read_config_byte(bus, device_fn,
 					PCI_CACHE_LINE_SIZE, &cache_line_size);
 	(void) pcibios_read_config_byte(bus, device_fn,
@@ -9369,24 +9400,105 @@
 	}
 
 #ifdef __powerpc__
+	if (!(command & PCI_COMMAND_MASTER)) {
+		printk("ncr53c8xx: attempting to force PCI_COMMAND_MASTER...");
+		command |= PCI_COMMAND_MASTER;
+		pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+		pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+		if (!(command & PCI_COMMAND_MASTER)) {
+			printk("failed!\n");
+		} else {
+			printk("succeeded.\n");
+		}
+	}
+
+	if (!(command & PCI_COMMAND_IO)) {
+		printk("ncr53c8xx: attempting to force PCI_COMMAND_IO...");
+		command |= PCI_COMMAND_IO;
+		pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+		pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+		if (!(command & PCI_COMMAND_IO)) {
+			printk("failed!\n");
+		} else {
+			printk("succeeded.\n");
+		}
+	}
+
+	if (!(command & PCI_COMMAND_MEMORY)) {
+		printk("ncr53c8xx: attempting to force PCI_COMMAND_MEMORY...");
+		command |= PCI_COMMAND_MEMORY;
+		pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+		pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+		if (!(command & PCI_COMMAND_MEMORY)) {
+			printk("failed!\n");
+		} else {
+			printk("succeeded.\n");
+		}
+	}
+	
+	if ( is_prep ) {
+		if (io_port >= 0x10000000) {
+			printk("ncr53c8xx: reallocating io_port (Wacky IBM)");
+			io_port = (io_port & 0x00FFFFFF) | 0x01000000;
+			pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
+		}
+		if (base >= 0x10000000) {
+			printk("ncr53c8xx: reallocating base (Wacky IBM)");
+			base = (base & 0x00FFFFFF) | 0x01000000;
+			pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base);
+		}
+		if (base_2 >= 0x10000000) {
+			printk("ncr53c8xx: reallocating base2 (Wacky IBM)");
+			base_2 = (base_2 & 0x00FFFFFF) | 0x01000000;
+			pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, base_2);
+		}
+	}
+#endif
+#ifdef __sparc__
 	/*
-	 *	Severall fix-up for power/pc.
-	 *	Should not be performed by the driver.
+	 *	Severall fix-ups for sparc.
+	 *
+	 *	Should not be performed by the driver, but how can OBP know
+	 *	each and every PCI card, if they don't use Fcode?
 	 */
-	if ((command &
-		(PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) !=
-		(PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
-		printk("ncr53c8xx : setting PCI master/io/command bit\n");
-		command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY;
+
+	base = __pa(base);
+	base_2 = __pa(base_2);
+
+	if (!(command & PCI_COMMAND_MASTER)) {
+		if (initverbose >= 2)
+			printk("ncr53c8xx: setting PCI_COMMAND_MASTER bit (fixup)\n");
+		command |= PCI_COMMAND_MASTER;
 		pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+		pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
 	}
-	if (io_port >= 0x10000000) {
-		io_port = (io_port & 0x00FFFFFF) | 0x01000000;
-		pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port);
-	}
-	if (base >= 0x10000000) {
-		base = (base & 0x00FFFFFF) | 0x01000000;
-		pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base);
+
+	if ((chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
+		if (initverbose >= 2)
+			printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fixup)\n");
+		command |= PCI_COMMAND_INVALIDATE;
+		pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command);
+		pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+	}
+
+	if ((chip->features & FE_CLSE) && !cache_line_size) {
+		cache_line_size = 16;
+		if (initverbose >= 2)
+			printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
+		pcibios_write_config_byte(bus, device_fn,
+					  PCI_CACHE_LINE_SIZE, cache_line_size);
+		pcibios_read_config_byte(bus, device_fn,
+					 PCI_CACHE_LINE_SIZE, &cache_line_size);
+	}
+
+	if (!latency_timer) {
+		latency_timer = 248;
+		if (initverbose >= 2)
+			printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
+		pcibios_write_config_byte(bus, device_fn,
+					  PCI_LATENCY_TIMER, latency_timer);
+		pcibios_read_config_byte(bus, device_fn,
+					 PCI_LATENCY_TIMER, &latency_timer);
 	}
 #endif
 
@@ -9425,8 +9537,13 @@
 	base_2 &= PCI_BASE_ADDRESS_MEM_MASK;
 
 	if (io_port && check_region (io_port, 128)) {
+#ifdef __sparc__
+		printk("ncr53c8xx: IO region 0x%lx to 0x%lx is in use\n",
+			io_port, (io_port + 127));
+#else
 		printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n",
 			(int) io_port, (int) (io_port + 127));
+#endif
 		return -1;
 	}
 	
@@ -9459,7 +9576,7 @@
 	/*
 	 * Try to fix up PCI config according to wished features.
 	 */
-#if defined(__i386) && !defined(MODULE)
+#if defined(__i386__) && !defined(MODULE)
 	if ((driver_setup.pci_fix_up & 1) &&
 	    (chip->features & FE_CLSE) && cache_line_size == 0) {
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75)
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.1.92/linux/drivers/scsi/ncr53c8xx.h	Fri Feb  6 15:33:40 1998
+++ linux/drivers/scsi/ncr53c8xx.h	Mon Apr  6 11:51:23 1998
@@ -161,6 +161,8 @@
 #define	SCSI_NCR_IOMAPPED
 #elif defined(__alpha__) || defined(__powerpc__)
 #define	SCSI_NCR_IOMAPPED
+#elif defined(__sparc__)
+#undef SCSI_NCR_IOMAPPED
 #endif
 
 /*
@@ -347,13 +349,18 @@
 #error	"BIG ENDIAN byte ordering needs kernel version >= 2.1.0"
 #endif
 
-#ifdef	__powerpc__
+#if defined(__powerpc__)
 #define	inw_l2b		inw
 #define	inl_l2b		inl
 #define	outw_b2l	outw
 #define	outl_b2l	outl
+#elif defined(__sparc__)
+#define	readw_l2b	readw
+#define	readl_l2b	readl
+#define	writew_b2l	writew
+#define	writel_b2l	writel
 #else
-#error	"Support for BIG ENDIAN is only available for the PowerPC"
+#error	"Support for BIG ENDIAN is only available for PowerPC and SPARC"
 #endif
 
 #else	/* Assumed x86 or alpha */
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c
--- v2.1.92/linux/drivers/scsi/pci2000.c	Tue Feb 17 13:12:47 1998
+++ linux/drivers/scsi/pci2000.c	Thu Apr  2 09:12:25 1998
@@ -28,7 +28,6 @@
 #include <linux/head.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -519,21 +518,15 @@
 	PADAPTER2000	    padapter;
 	int					z;
 	int					setirq;
+	struct pci_dev	   *pdev = NULL;
 
-	if ( pcibios_present () )
-		{
-		for ( pci_index = 0;  pci_index <= MAXADAPTER;  ++pci_index )
+	if ( pci_present () )
+		while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_ROY_1, pdev)))
 			{
-			UCHAR	pci_bus, pci_device_fn;
-
-			if ( pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
-				break;
-
 			pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
 			padapter = HOSTDATA(pshost);
 
-			pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
-			padapter->basePort &= 0xFFFE;
+			padapter->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
 			DEB (printk ("\nBase Regs = %#04X", padapter->basePort));			// get the base I/O port address
 			padapter->mb0	= padapter->basePort + RTR_MAILBOX;		   			// get the 32 bit mail boxes
 			padapter->mb1	= padapter->basePort + RTR_MAILBOX + 4;
@@ -550,7 +543,7 @@
 			if ( WaitReady (padapter) )
 				goto unregister;
 
-			pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+			pshost->irq = pdev->irq;
 			setirq = 1;
 			for ( z = 0;  z < pci_index;  z++ )											// scan for shared interrupts
 				{
@@ -573,13 +566,12 @@
 
 			printk("\nPSI-2000 EIDE CONTROLLER: at I/O = %X  IRQ = %d\n", padapter->basePort, pshost->irq);
 			printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
+			NumAdapters++;
 			continue;
 unregister:;
 			scsi_unregister (pshost);
 			}
-		}
-	NumAdapters = pci_index;
-	return pci_index;
+	return NumAdapters;
 	}
 /****************************************************************
  *	Name:	Pci2220i_Abort
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- v2.1.92/linux/drivers/scsi/pci2220i.c	Wed Nov  5 13:18:17 1997
+++ linux/drivers/scsi/pci2220i.c	Thu Apr  2 09:12:25 1998
@@ -30,7 +30,6 @@
 #include <linux/head.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -632,7 +631,7 @@
  ****************************************************************/
 int Pci2220i_Detect (Scsi_Host_Template *tpnt)
 	{
-	int					pci_index = 0;
+	struct pci_dev	   *pdev = NULL;
 	struct Scsi_Host   *pshost;
 	PADAPTER2220I	    hostdata;
 	ULONG				modearray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
@@ -640,20 +639,13 @@
 	int					z;
 	int					setirq;
 
-	if ( pcibios_present () )
-		{
-		for ( pci_index = 0;  pci_index <= MAXADAPTER;  ++pci_index )
+	if ( pci_present () )
+		while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_DALE_1, pdev)))
 			{
-			UCHAR	pci_bus, pci_device_fn;
-
-			if ( pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
-				break;
-
 			pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
 			hostdata = HOSTDATA(pshost);
 
-			pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &hostdata->basePort);
-			hostdata->basePort &= 0xFFFE;
+			hostdata->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
 			DEB (printk ("\nBase Regs = %#04X", hostdata->basePort));
 			hostdata->regRemap		= hostdata->basePort + RTR_LOCAL_REMAP;				// 32 bit local space remap
 			DEB (printk (" %#04X", hostdata->regRemap));
@@ -666,8 +658,7 @@
 			hostdata->regScratchPad	= hostdata->basePort + RTR_MAILBOX;	  				// 16 byte scratchpad I/O base address
 			DEB (printk (" %#04X", hostdata->regScratchPad));
 
-			pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &hostdata->regBase);
-			hostdata->regBase &= 0xFFFE;
+			hostdata->regBase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
 			for ( z = 0;  z < 9;  z++ )													// build regester address array
 				hostdata->ports[z] = hostdata->regBase + 0x80 + (z * 4);
 			hostdata->ports[PORT_FAIL] = hostdata->regBase + REG_FAIL;
@@ -691,11 +682,11 @@
 			if ( !inb_p (hostdata->regScratchPad + DALE_NUM_DRIVES) )					// if no devices on this board
 				goto unregister;
 
-			pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+			pshost->irq = pdev->irq;
 			setirq = 1;
-			for ( z = 0;  z < pci_index;  z++ )											// scan for shared interrupts
+			for ( z = 0;  z < NumAdapters;  z++ )										// scan for shared interrupts
 				{
-				if ( PsiHost[z]->irq == pshost->irq )						// if shared then, don't posses
+				if ( PsiHost[z]->irq == pshost->irq )									// if shared then, don't posses
 					setirq = 0;
 				}
 			if ( setirq )																// if not shared, posses
@@ -706,7 +697,7 @@
 					goto unregister;
 					}
 				}
-			PsiHost[pci_index]	= pshost;												// save SCSI_HOST pointer
+			PsiHost[NumAdapters]	= pshost;											// save SCSI_HOST pointer
 
 			pshost->unique_id	= hostdata->regBase;
 			pshost->max_id		= 4;
@@ -743,7 +734,6 @@
 			scsi_unregister (pshost);
 			NumAdapters++;
 			}
-		}
 	return NumAdapters;
 	}
 /****************************************************************
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.1.92/linux/drivers/scsi/qlogicisp.c	Wed Apr  1 20:11:53 1998
+++ linux/drivers/scsi/qlogicisp.c	Thu Apr  2 09:12:25 1998
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/types.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/unistd.h>
@@ -55,8 +54,6 @@
 
 #define DEFAULT_LOOP_COUNT	1000000
 
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
 /* End Configuration section *************************************************/
 
 #include <linux/module.h>
@@ -488,11 +485,10 @@
 #define QUEUE_ENTRY_LEN		64
 
 struct isp1020_hostdata {
-	u_char	bus;
 	u_char	revision;
-	u_char	device_fn;
 	struct	host_param host_param;
 	struct	dev_param dev_param[MAX_TARGETS];
+	struct	pci_dev *pci_dev;
 	
 	/* result and request queues (shared with isp1020): */
 	u_int	req_in_ptr;		/* index of next request slot */
@@ -511,8 +507,6 @@
 						    QLOGICISP_REQ_QUEUE_LEN)
 #define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
 
-static struct Scsi_Host *irq2host[NR_IRQS];
-
 static void	isp1020_enable_irqs(struct Scsi_Host *);
 static void	isp1020_disable_irqs(struct Scsi_Host *);
 static int	isp1020_init(struct Scsi_Host *);
@@ -557,33 +551,26 @@
 int isp1020_detect(Scsi_Host_Template *tmpt)
 {
 	int hosts = 0;
-	u_short index;
-	u_char bus, device_fn;
 	struct Scsi_Host *host;
 	struct isp1020_hostdata *hostdata;
+	struct pci_dev *pdev = NULL;
 
 	ENTER("isp1020_detect");
 
 	tmpt->proc_dir = &proc_scsi_isp1020;
 
-	if (pcibios_present() == 0) {
-		printk("qlogicisp : PCI bios not present\n");
+	if (pci_present() == 0) {
+		printk("qlogicisp : PCI not present\n");
 		return 0;
 	}
 
-	memset(irq2host, 0, sizeof(irq2host));
-
-	for (index = 0; pcibios_find_device(PCI_VENDOR_ID_QLOGIC,
-					    PCI_DEVICE_ID_QLOGIC_ISP1020,
-					    index, &bus, &device_fn) == 0;
-	     index++)
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, pdev)))
 	{
 		host = scsi_register(tmpt, sizeof(struct isp1020_hostdata));
 		hostdata = (struct isp1020_hostdata *) host->hostdata;
 
 		memset(hostdata, 0, sizeof(struct isp1020_hostdata));
-		hostdata->bus = bus;
-		hostdata->device_fn = device_fn;
+		hostdata->pci_dev = pdev;
 
 		if (isp1020_init(host) || isp1020_reset_hardware(host)
 #if USE_NVRAM_DEFAULTS
@@ -598,8 +585,8 @@
 
 		host->this_id = hostdata->host_param.initiator_scsi_id;
 
-		if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT,
-				"qlogicisp", NULL))
+		if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT | SA_SHIRQ,
+				"qlogicisp", host))
 		{
 			printk("qlogicisp : interrupt %d already in use\n",
 			       host->irq);
@@ -611,13 +598,12 @@
 			printk("qlogicisp : i/o region 0x%lx-0x%lx already "
 			       "in use\n",
 			       host->io_port, host->io_port + 0xff);
-			free_irq(host->irq, NULL);
+			free_irq(host->irq, host);
 			scsi_unregister(host);
 			continue;
 		}
 
 		request_region(host->io_port, 0xff, "qlogicisp");
-		irq2host[host->irq] = host;
 
 		outw(0x0, host->io_port + PCI_SEMAPHORE);
 		outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
@@ -641,7 +627,7 @@
 	hostdata = (struct isp1020_hostdata *) host->hostdata;
 
 	outw(0x0, host->io_port + PCI_INTF_CTL);
-	free_irq(host->irq, NULL);
+	free_irq(host->irq, host);
 
 	release_region(host->io_port, 0xff);
 
@@ -660,8 +646,8 @@
 
 	hostdata = (struct isp1020_hostdata *) host->hostdata;
 	sprintf(buf,
-		"QLogic ISP1020 SCSI on PCI bus %d device %d irq %d base 0x%lx",
-		hostdata->bus, (hostdata->device_fn & 0xf8) >> 3, host->irq,
+		"QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
+		hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
 		host->io_port);
 
 	LEAVE("isp1020_info");
@@ -819,18 +805,13 @@
 {
 	Scsi_Cmnd *Cmnd;
 	struct Status_Entry *sts;
-	struct Scsi_Host *host;
+	struct Scsi_Host *host = dev_id;
 	struct isp1020_hostdata *hostdata;
 	u_int in_ptr, out_ptr;
 	u_short status;
 
 	ENTER_INTR("isp1020_intr_handler");
 
-	host = irq2host[irq];
-	if (!host) {
-		printk("qlogicisp : unexpected interrupt on line %d\n", irq);
-		return;
-	}
 	hostdata = (struct isp1020_hostdata *) host->hostdata;
 
 	DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq));
@@ -1168,53 +1149,36 @@
 
 static int isp1020_init(struct Scsi_Host *sh)
 {
-	u_long io_base = 0;
+	u_int io_base;
 	struct isp1020_hostdata *hostdata;
-	u_char bus, device_fn, revision, irq;
-	u_short vendor_id, device_id, command;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
+	u_char revision;
+	u_int irq;
+	u_short command;
 	struct pci_dev *pdev;
-#endif
 
 	ENTER("isp1020_init");
 
 	hostdata = (struct isp1020_hostdata *) sh->hostdata;
-	bus = hostdata->bus;
-	device_fn = hostdata->device_fn;
+	pdev = hostdata->pci_dev;
 
-	if (pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id)
-            || pcibios_read_config_word(bus, device_fn,
-					PCI_DEVICE_ID, &device_id)
-            || pcibios_read_config_word(bus, device_fn,
-					PCI_COMMAND, &command)
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,90)
-            || pcibios_read_config_dword(bus, device_fn,
-					 PCI_BASE_ADDRESS_0, &io_base)
-	    || pcibios_read_config_byte(bus, device_fn,
-					PCI_INTERRUPT_LINE, &irq)
-#endif
-            || pcibios_read_config_byte(bus, device_fn,
-					PCI_CLASS_REVISION, &revision))
+	if (pci_read_config_word(pdev, PCI_COMMAND, &command)
+	    || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision))
 	{
 		printk("qlogicisp : error reading PCI configuration\n");
 		return 1;
 	}
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,90)
-	pdev = pci_find_dev(bus, device_fn);
 	io_base = pdev->base_address[0];
-	irq     = pdev->irq;
-#endif
+	irq = pdev->irq;
 
-	if (vendor_id != PCI_VENDOR_ID_QLOGIC) {
+	if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
 		printk("qlogicisp : 0x%04x is not QLogic vendor ID\n",
-		       vendor_id);
+		       pdev->vendor);
 		return 1;
 	}
 
-	if (device_id != PCI_DEVICE_ID_QLOGIC_ISP1020) {
+	if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP1020) {
 		printk("qlogicisp : 0x%04x does not match ISP1020 device id\n",
-		       device_id);
+		       pdev->device);
 		return 1;
 	}
 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.92/linux/drivers/scsi/scsi.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/scsi/scsi.c	Wed Apr  1 20:14:32 1998
@@ -141,7 +141,7 @@
  */
 unsigned int              scsi_logging_level = 0;
 
-static volatile struct Scsi_Host * host_active = NULL;
+volatile struct Scsi_Host * host_active = NULL;
 
 #if CONFIG_PROC_FS
 /* 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.1.92/linux/drivers/scsi/scsi_obsolete.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/scsi/scsi_obsolete.c	Wed Apr  1 20:14:32 1998
@@ -83,7 +83,7 @@
 extern void scsi_old_times_out (Scsi_Cmnd * SCpnt);
 extern void internal_cmnd (Scsi_Cmnd * SCpnt);
 
-static volatile struct Scsi_Host * host_active = NULL;
+extern volatile struct Scsi_Host * host_active;
 #define SCSI_BLOCK(HOST) ((HOST->block && host_active && HOST != host_active) \
 			  || (HOST->can_queue && HOST->host_busy >= HOST->can_queue))
 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c
--- v2.1.92/linux/drivers/scsi/tmscsim.c	Tue Mar 10 10:03:33 1998
+++ linux/drivers/scsi/tmscsim.c	Thu Apr  2 09:12:25 1998
@@ -26,7 +26,7 @@
  *				pending interrupt in DC390_detect()	*
  * 	1.11  02/05/97	KG/CLH	Fixeds problem with partitions greater	*
  * 				than 1GB				*
- * 	1.12  25/02/98	KG	Cleaned up ifdefs for 2.1 kernel	*
+ *      1.12  15/02/98  MJ      Rewritten PCI probing			*
  ***********************************************************************/
 
 
@@ -47,7 +47,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
@@ -118,8 +117,6 @@
 static USHORT	adapterCnt = 0;
 static USHORT	InitialTime = 0;
 static USHORT	CurrSyncOffset = 0;
-static ULONG	mech1addr;
-static UCHAR	mech2bus, mech2Agent, mech2CfgSPenR;
 
 static PVOID DC390_phase0[]={
        DC390_DataOut_0,
@@ -1200,147 +1197,7 @@
 
 
 void
-DC390_EnableCfg( USHORT mechnum, UCHAR regval )
-{
-    ULONG wlval;
-
-    if(mechnum == 2)
-    {
-	outb(mech2bus, PCI_CFG2_FORWARD_REG);
-	outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG);
-    }
-    else
-    {
-	regval &= 0xFC;
-	wlval = mech1addr;
-	wlval |= (((ULONG)regval) & 0xff);
-	outl(wlval, PCI_CFG1_ADDRESS_REG);
-    }
-}
-
-
-void
-DC390_DisableCfg( USHORT mechnum )
-{
-
-    if(mechnum == 2)
-	outb(0, PCI_CFG2_ENABLE_REG);
-    else
-	outl(0, PCI_CFG1_ADDRESS_REG);
-}
-
-
-UCHAR
-DC390_inByte( USHORT mechnum, UCHAR regval )
-{
-    UCHAR bval;
-    ULONG wval;
-    ULONG flags;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg( mechnum, regval );
-    if(mechnum == 2)
-    {
-	wval = mech2Agent;
-	wval <<= 8;
-	wval |= ((USHORT) regval) & 0xff;
-	bval = inb(wval);
-    }
-    else
-    {
-	regval &= 3;
-	bval = inb(PCI_CFG1_DATA_REG | regval);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-    return(bval);
-}
-
-
-USHORT
-DC390_inWord( USHORT mechnum, UCHAR regval )
-{
-    USHORT wval;
-    ULONG flags;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg(mechnum,regval);
-    if(mechnum == 2)
-    {
-	wval = mech2Agent;
-	wval <<= 8;
-	wval |= regval;
-	wval = inw(wval);
-    }
-    else
-    {
-	regval &= 3;
-	wval = inw(PCI_CFG1_DATA_REG | regval);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-    return(wval);
-}
-
-
-ULONG
-DC390_inDword(USHORT mechnum, UCHAR regval )
-{
-    ULONG wlval;
-    ULONG flags;
-    USHORT wval;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg(mechnum,regval);
-    if(mechnum == 2)
-    {
-	wval = mech2Agent;
-	wval <<= 8;
-	wval |= regval;
-	wlval = inl(wval);
-    }
-    else
-    {
-	wlval = inl(PCI_CFG1_DATA_REG);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-    return(wlval);
-}
-
-
-void
-DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
-{
-
-    USHORT wval;
-    ULONG  flags;
-
-    save_flags(flags);
-    cli();
-    DC390_EnableCfg(mechnum,regval);
-    if(mechnum == 2)
-    {
-	wval = mech2Agent;
-	wval <<= 8;
-	wval |= regval;
-	outb(bval, wval);
-    }
-    else
-    {
-	regval &= 3;
-	outb(bval, PCI_CFG1_DATA_REG | regval);
-    }
-    DC390_DisableCfg(mechnum);
-    restore_flags(flags);
-}
-
-
-void
-DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
+DC390_EnDisableCE( UCHAR mode, struct pci_dev *pdev, PUCHAR regval )
 {
 
     UCHAR bval;
@@ -1350,15 +1207,15 @@
 	*regval = 0xc0;
     else
 	*regval = 0x80;
-    DC390_OutB(mechnum,*regval,bval);
+    pci_write_config_byte(pdev, *regval, bval);
     if(mode == DISABLE_CE)
-	DC390_OutB(mechnum,*regval,bval);
+	pci_write_config_byte(pdev, *regval, bval);
     udelay(160);
 }
 
 
 void
-DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
+DC390_EEpromOutDI( struct pci_dev *pdev, PUCHAR regval, USHORT Carry )
 {
     UCHAR bval;
 
@@ -1367,32 +1224,28 @@
     {
 	bval = 0x40;
 	*regval = 0x80;
-	DC390_OutB(mechnum,*regval,bval);
+	pci_write_config_byte(pdev, *regval, bval);
     }
     udelay(160);
     bval |= 0x80;
-    DC390_OutB(mechnum,*regval,bval);
+    pci_write_config_byte(pdev, *regval, bval);
     udelay(160);
     bval = 0;
-    DC390_OutB(mechnum,*regval,bval);
+    pci_write_config_byte(pdev, *regval, bval);
     udelay(160);
 }
 
 
 UCHAR
-DC390_EEpromInDO( USHORT mechnum )
+DC390_EEpromInDO( struct pci_dev *pdev )
 {
-    UCHAR bval,regval;
+    UCHAR bval;
 
-    regval = 0x80;
-    bval = 0x80;
-    DC390_OutB(mechnum,regval,bval);
+    pci_write_config_byte(pdev, 0x80, 0x80);
     udelay(160);
-    bval = 0x40;
-    DC390_OutB(mechnum,regval,bval);
+    pci_write_config_byte(pdev, 0x80, 0x40);
     udelay(160);
-    regval = 0x0;
-    bval = DC390_inByte(mechnum,regval);
+    pci_read_config_byte(pdev, 0x00, &bval);
     if(bval == 0x22)
 	return(1);
     else
@@ -1401,7 +1254,7 @@
 
 
 USHORT
-EEpromGetData1( USHORT mechnum )
+EEpromGetData1( struct pci_dev *pdev )
 {
     UCHAR i;
     UCHAR carryFlag;
@@ -1411,7 +1264,7 @@
     for(i=0; i<16; i++)
     {
 	wval <<= 1;
-	carryFlag = DC390_EEpromInDO(mechnum);
+	carryFlag = DC390_EEpromInDO(pdev);
 	wval |= carryFlag;
     }
     return(wval);
@@ -1419,7 +1272,7 @@
 
 
 void
-DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
+DC390_Prepare( struct pci_dev *pdev, PUCHAR regval, UCHAR EEpromCmd )
 {
     UCHAR i,j;
     USHORT carryFlag;
@@ -1428,7 +1281,7 @@
     j = 0x80;
     for(i=0; i<9; i++)
     {
-	DC390_EEpromOutDI(mechnum,regval,carryFlag);
+	DC390_EEpromOutDI(pdev,regval,carryFlag);
 	carryFlag = (EEpromCmd & j) ? 1 : 0;
 	j >>= 1;
     }
@@ -1436,7 +1289,7 @@
 
 
 void
-DC390_ReadEEprom( USHORT mechnum, USHORT index )
+DC390_ReadEEprom( struct pci_dev *pdev, int index )
 {
     UCHAR   regval,cmd;
     PUSHORT ptr;
@@ -1446,23 +1299,23 @@
     cmd = EEPROM_READ;
     for(i=0; i<0x40; i++)
     {
-	DC390_EnDisableCE(ENABLE_CE, mechnum, &regval);
-	DC390_Prepare(mechnum, &regval, cmd);
-	*ptr = EEpromGetData1(mechnum);
+	DC390_EnDisableCE(ENABLE_CE, pdev, &regval);
+	DC390_Prepare(pdev, &regval, cmd);
+	*ptr = EEpromGetData1(pdev);
 	ptr++;
 	cmd++;
-	DC390_EnDisableCE(DISABLE_CE,mechnum,&regval);
+	DC390_EnDisableCE(DISABLE_CE, pdev, &regval);
     }
 }
 
 
 USHORT
-DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index )
+DC390_CheckEEpromCheckSum( struct pci_dev *pdev, int index )
 {
     USHORT wval, rc, *ptr;
     UCHAR  i;
 
-    DC390_ReadEEprom( MechNum, index );
+    DC390_ReadEEprom( pdev, index );
     wval = 0;
     ptr = (PUSHORT) &eepromBuf[index][0];
     for(i=0; i<128 ;i+=2, ptr++)
@@ -1475,30 +1328,6 @@
 }
 
 
-USHORT
-DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum )
-{
-    USHORT devnum;
-
-    devnum = BusDevFunNum;
-
-    if(Mechnum == 2)
-    {
-	if(devnum & 0x80)
-	     return(-1);
-	mech2bus = (UCHAR)((devnum & 0xff00) >> 8);	  /* Bus num */
-	mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3;	  /* Dev num */
-	mech2Agent |= 0xc0;
-	mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07;  /* Fun num */
-	mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20;
-    }
-    else	/* use mech #1 method */
-    {
-	mech1addr = 0x80000000 | ((ULONG)devnum << 8);
-    }
-    return(0);
-}
-
 /***********************************************************************
  * Function : static int DC390_init (struct Scsi_Host *host)
  *
@@ -1511,12 +1340,12 @@
  ***********************************************************************/
 
 __initfunc(static int
-DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum))
+DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, int index))
 {
     PSH   psh;
     PACB  pACB;
 
-    if( !DC390_CheckEEpromCheckSum( MechNum, index) )
+    if( !DC390_CheckEEpromCheckSum( pdev, index ) )
     {
 	psh = scsi_register( psht, sizeof(DC390_ACB) );
 	if( !psh )
@@ -1594,20 +1423,10 @@
 __initfunc(int
 DC390_detect(Scsi_Host_Template *psht))
 {
-#ifdef FOR_PCI_OK
-    UCHAR   pci_bus, pci_device_fn;
-    int     error = 0;
-    USHORT  chipType = 0;
-    USHORT  i;
-#endif
-
-    UCHAR   irq;
-    UCHAR   istatus;
+    struct pci_dev *pdev = NULL;
+    UINT    irq;
     UINT    io_port;
     USHORT  adaptCnt = 0;	/* Number of boards detected */
-    USHORT  pci_index = 0;	/* Device index to PCI BIOS calls */
-    USHORT  MechNum, BusDevFunNum;
-    ULONG   wlval;
 
     psht->proc_dir = &proc_scsi_tmscsim;
 
@@ -1615,81 +1434,17 @@
     pSHT_start = psht;
     pACB_start = NULL;
 
-    MechNum = 1;
-    for( ; (MechNum < 3) && (!adaptCnt); MechNum++)
-    {
-	BusDevFunNum = 0;
-	for (; adaptCnt < MAX_ADAPTER_NUM ;)
+    if ( pci_present() )
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pdev)))
 	{
-	    if( !DC390_ToMech( MechNum, BusDevFunNum) )
-	    {
-		 wlval = DC390_inDword( MechNum, PCI_VENDOR_ID);
-		 if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+
-				PCI_VENDOR_ID_AMD) )
-		 {
-		    io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE;
-		    irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE);
+	    io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+	    irq = pdev->irq;
 #ifdef DC390_DEBUG0
-		printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
+	    printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
 #endif
-		    if( !DC390_init(psht, io_port, irq, pci_index, MechNum) )
-		    {
-			adaptCnt++;
-			pci_index++;
-			istatus = inb( (USHORT)io_port+INT_Status );	/* Reset Pending INT */
-#ifdef DC390_DEBUG0
-		printk("DC390: Mech=%2x,\n",(UCHAR) MechNum);
-#endif
-		    }
-		 }
-	    }
-	    if( BusDevFunNum != 0xfff8 )
-		BusDevFunNum += 8;	    /* next device # */
-	    else
-		break;
+	    if( !DC390_init(psht, io_port, irq, pdev, adaptCnt))
+		adaptCnt++;
 	}
-    }
-
-#ifdef FOR_PCI_OK
-    if ( pcibios_present() )
-    {
-	for (i = 0; i < MAX_ADAPTER_NUM; ++i)
-	{
-	    if( !pcibios_find_device( PCI_VENDOR_ID_AMD,
-				PCI_DEVICE_ID_AMD53C974,
-				pci_index, &pci_bus, &pci_device_fn) )
-	    {
-		chipType = PCI_DEVICE_ID_AMD53C974;
-		pci_index++;
-	    }
-
-	    if( chipType )
-	    {
-
-		error = pcibios_read_config_dword(pci_bus, pci_device_fn,
-						  PCI_BASE_ADDRESS_0, &io_port);
-		error |= pcibios_read_config_byte(pci_bus, pci_device_fn,
-						  PCI_INTERRUPT_LINE, &irq);
-		if( error )
-		{
-		    printk("DC390_detect: reading configuration registers error!\n");
-		    InitialTime = 0;
-		    return( 0 );
-		}
-
-		(USHORT) io_port = (USHORT) io_port & 0xFFFE;
-#ifdef DC390_DEBUG0
-		printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
-#endif
-		if( !DC390_init(psht, io_port, irq, i) )
-		    adaptCnt++;
-		chipType = 0;
-	    }
-	    else
-		break;
-	}
-    }
-#endif
 
     InitialTime = 0;
     adapterCnt = adaptCnt;
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/tmscsim.h linux/drivers/scsi/tmscsim.h
--- v2.1.92/linux/drivers/scsi/tmscsim.h	Tue Mar 10 10:03:33 1998
+++ linux/drivers/scsi/tmscsim.h	Thu Apr  2 09:12:25 1998
@@ -660,21 +660,4 @@
 	outl((value), DC390_ioport + (address)))
 
 
-/* Configuration method #1 */
-#define PCI_CFG1_ADDRESS_REG		0xcf8
-#define PCI_CFG1_DATA_REG		0xcfc
-#define PCI_CFG1_ENABLE 		0x80000000
-#define PCI_CFG1_TUPPLE(bus, device, function, register)		\
-	(PCI_CFG1_ENABLE | (((bus) << 16) & 0xff0000) | 		\
-	(((device) << 11) & 0xf800) | (((function) << 8) & 0x700)|	\
-	(((register) << 2) & 0xfc))
-
-/* Configuration method #2 */
-#define PCI_CFG2_ENABLE_REG		0xcf8
-#define PCI_CFG2_FORWARD_REG		0xcfa
-#define PCI_CFG2_ENABLE 		0x0f0
-#define PCI_CFG2_TUPPLE(function)					\
-	(PCI_CFG2_ENABLE | (((function) << 1) & 0xe))
-
-
 #endif /* _TMSCSIM_H */
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.1.92/linux/drivers/scsi/u14-34f.c	Mon Sep 15 09:41:09 1997
+++ linux/drivers/scsi/u14-34f.c	Sun Apr  5 11:26:29 1998
@@ -1,6 +1,13 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
+ *          io_port is now unsigned long.
+ *
+ *      17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88
+ *          Use new scsi error handling code (if linux version >= 2.1.88).
+ *          Use new interrupt code.
+ *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
@@ -113,7 +120,7 @@
  * 
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -329,9 +336,7 @@
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
-#undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
-#undef  DEBUG_SMP
 
 #define MAX_ISA 3
 #define MAX_VESA 1 
@@ -341,7 +346,6 @@
 #define MAX_CHANNEL 1
 #define MAX_LUN 8
 #define MAX_TARGET 8
-#define MAX_IRQ 16
 #define MAX_MAILBOXES 16
 #define MAX_SGLIST 32
 #define MAX_SAFE_SGLIST 16
@@ -349,7 +353,7 @@
 #define MAX_CMD_PER_LUN 2
 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)
 
-#define SKIP UINT_MAX
+#define SKIP ULONG_MAX
 #define FALSE 0
 #define TRUE 1
 #define FREE 0
@@ -424,7 +428,6 @@
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
    unsigned int last_cp_used;           /* Index of last mailbox used */
    unsigned int iocount;                /* Total i/o done for this board */
-   unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
@@ -443,9 +446,12 @@
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "Ux4F";
-static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
+static char sha[MAX_BOARDS];
 
-static unsigned int io_port[] __initdata = { 
+/* Initialize num_boards so that ihdlr can work while detect is in progress */
+static unsigned int num_boards = MAX_BOARDS;
+
+static unsigned long io_port[] __initdata = { 
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -462,10 +468,10 @@
 #define BN(board) (HD(board)->board_name)
 
 #define SWAP_BYTE(x) ((unsigned long)( \
-	(((unsigned long)(x) & 0x000000ffU) << 24) | \
-	(((unsigned long)(x) & 0x0000ff00U) <<  8) | \
-	(((unsigned long)(x) & 0x00ff0000U) >>  8) | \
-	(((unsigned long)(x) & 0xff000000U) >> 24)))
+        (((unsigned long)(x) & 0x000000ffU) << 24) | \
+        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
+        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
+        (((unsigned long)(x) & 0xff000000U) >> 24)))
 
 #if defined(__BIG_ENDIAN)
 #define H2DEV(x) SWAP_BYTE(x)
@@ -560,7 +566,7 @@
    return;
 }
 
-static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
+static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {
 
    while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {
       udelay(1L);
@@ -614,7 +620,7 @@
 }
 
 __initfunc (static inline int port_detect \
-      (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char in_byte;
    char *bus_type, dma_name[16];
@@ -637,8 +643,8 @@
       unsigned char heads;
       unsigned char sectors;
       } mapping_table[4] = { 
-	   { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
-	   };
+           { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
+           };
 
    struct config_1 {
       unsigned char bios_segment: 3;
@@ -659,7 +665,7 @@
    sprintf(name, "%s%d", driver_name, j);
 
    if(check_region(port_base, REGION_SIZE)) {
-      printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base);
+      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
       return FALSE;
       }
 
@@ -676,17 +682,18 @@
    dma_channel = dma_channel_table[config_1.dma_channel];
    subversion = (in_byte & 0x0f);
 
-   /* Board detected, allocate its IRQ if not already done */
-   if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq,
-              u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
+   /* Board detected, allocate its IRQ */
+   if (request_irq(irq, u14_34f_interrupt_handler,
+             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
+             driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
       return FALSE;
       }
 
    if (subversion == ISA && request_dma(dma_channel, driver_name)) {
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
-	     name, dma_channel);
-      free_irq(irq, NULL);
+             name, dma_channel);
+      free_irq(irq, &sha[j]);
       return FALSE;
       }
 
@@ -695,7 +702,7 @@
    if (sh[j] == NULL) {
       printk("%s: unable to register host, detaching.\n", name);
 
-      if (!irqlist[irq]) free_irq(irq, NULL);
+      free_irq(irq, &sha[j]);
 
       if (subversion == ISA) free_dma(dma_channel);
 
@@ -734,7 +741,6 @@
    HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
    HD(j)->subversion = subversion;
    HD(j)->board_number = j;
-   irqlist[irq]++;
 
    if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
 
@@ -767,12 +773,12 @@
       HD(j)->board_id[40] = 0;
 
       if (strcmp(&HD(j)->board_id[32], "06000600")) {
-	 printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
-	 printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",
-		BN(j), &HD(j)->board_id[32]);
-	 sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
-	 sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
-	 }
+         printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
+         printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",
+                BN(j), &HD(j)->board_id[32]);
+         sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+         sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
+         }
       }
 
    if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST");
@@ -792,10 +798,11 @@
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
 
-   printk("%s: %s 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\
-          "lc:%c, mq:%d.\n", BN(j), bus_type, sh[j]->io_port, (int)sh[j]->base,
-          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
-          YESNO(have_old_firmware), YESNO(linked_comm), max_queue_depth);
+   printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\
+          "lc:%c, mq:%d.\n", BN(j), bus_type, (unsigned long)sh[j]->io_port,
+          (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
+          sh[j]->can_queue, YESNO(have_old_firmware), YESNO(linked_comm),
+          max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -857,11 +864,6 @@
       }
 #endif
 
-   for (k = 0; k < MAX_IRQ; k++) {
-      irqlist[k] = 0;
-      calls[k] = 0;
-      }
-
    for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL;
 
    for (k = 0; io_port[k]; k++) {
@@ -872,8 +874,9 @@
       }
 
    if (j > 0) 
-      printk("UltraStor 14F/34F: Copyright (C) 1994-1997 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
+   num_boards = j;
    restore_flags(flags);
    return j;
 }
@@ -938,26 +941,26 @@
       if (i >= sh[j]->can_queue) i = 0;
 
       if (HD(j)->cp_stat[i] == FREE) {
-	 HD(j)->last_cp_used = i;
-	 break;
-	 }
+         HD(j)->last_cp_used = i;
+         break;
+         }
       }
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
       if (HD(j)->in_reset) 
-	 printk("%s: qcomm, already in reset.\n", BN(j));
+         printk("%s: qcomm, already in reset.\n", BN(j));
       else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) 
                == SCSI_RESET_SUCCESS) 
-	 panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
+         panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    /* Set pointer to control packet structure */
@@ -969,16 +972,16 @@
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-			BN(j), i, SCpnt->channel, SCpnt->target, 
+                        BN(j), i, SCpnt->channel, SCpnt->target, 
                         SCpnt->lun, SCpnt->pid);
 
    cpp->xdir = DTD_IN;
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
       if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-	 cpp->xdir = DTD_OUT;
-	 break;
-	 }
+         cpp->xdir = DTD_OUT;
+         break;
+         }
 
    if (cpp->xdir == DTD_IN)
       for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
@@ -1023,7 +1026,7 @@
              SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);
-      return 0;
+      return 1;
       }
 
    /* Store pointer in OGM address bytes */
@@ -1048,14 +1051,14 @@
    if (SCarg->host_scribble == NULL
        || SCarg->serial_number != SCarg->serial_number_at_timeout) {
       printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
-	     BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+             BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
    printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
-	  BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+          BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -1076,8 +1079,8 @@
       printk("%s: abort, mbox %d is in use.\n", BN(j), i);
 
       if (SCarg != HD(j)->cp[i].SCpnt)
-	 panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
-	       BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
+         panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
+               BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
 
       if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED)
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
@@ -1103,7 +1106,7 @@
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
       printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-	     BN(j), i, SCarg->pid);
+             BN(j), i, SCarg->pid);
       SCarg->scsi_done(SCarg);
       restore_flags(flags);
       return SCSI_ABORT_SUCCESS;
@@ -1123,7 +1126,7 @@
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
    printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
-	  BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
    if (SCarg->host_scribble == NULL)
@@ -1160,13 +1163,13 @@
       if (HD(j)->cp_stat[i] == FREE) continue;
 
       if (HD(j)->cp_stat[i] == LOCKED) {
-	 HD(j)->cp_stat[i] = FREE;
-	 printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
-	 continue;
-	 }
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
+         continue;
+         }
 
       if (!(SCpnt = HD(j)->cp[i].SCpnt))
-	 panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
       if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
          HD(j)->cp_stat[i] = ABORTING;
@@ -1181,13 +1184,13 @@
          }
 
       if (SCpnt->host_scribble == NULL)
-	 panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
+         panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
       if (*(unsigned int *)SCpnt->host_scribble != i) 
-	 panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
+         panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
       if (SCpnt->scsi_done == NULL) 
-	 panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
       }
@@ -1223,7 +1226,7 @@
          HD(j)->cp_stat[i] = LOCKED;
 
          printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-	        BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
@@ -1235,7 +1238,7 @@
          HD(j)->cp_stat[i] = FREE;
 
          printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-	        BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else
@@ -1428,224 +1431,182 @@
       }
 }
 
-static void u14_34f_interrupt_handler(int irq, void *dev_id,
-                                      struct pt_regs *regs) {
+static void u14_34f_interrupt_handler(int irq, void *shap,
+                                               struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned long flags;
-   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, reg, ret;
+   unsigned int i, j, k, c, status, tstatus, reg, ret;
    struct mscp *spp;
 
-   save_flags(flags);
-   cli();
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
 
-   if (!irqlist[irq]) {
-      printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq);
-      restore_flags(flags);
+   if (sh[j]->irq != irq)
+       panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
+
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
+
+   /* Check if this board need to be serviced */
+   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+
+   spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
+
+   /* Clear interrupt pending flag */
+   outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
+
+   i = spp - HD(j)->cp;
+
+   if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+                                     || i >= sh[j]->can_queue)
+      panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
+            (void *)ret, HD(j)->cp);
+
+   if (HD(j)->cp_stat[i] == IGNORE) {
+      HD(j)->cp_stat[i] = FREE;
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == LOCKED) {
+      HD(j)->cp_stat[i] = FREE;
+      printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == FREE) {
+      printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+             HD(j)->iocount);
       return;
       }
+   else if (HD(j)->cp_stat[i] == IN_RESET)
+      printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+   else if (HD(j)->cp_stat[i] != IN_USE) 
+      panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
+
+   HD(j)->cp_stat[i] = FREE;
+   SCpnt = spp->SCpnt;
+
+   if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
+
+   if (SCpnt->host_scribble == NULL) 
+      panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+            SCpnt->pid, SCpnt);
+
+   if (*(unsigned int *)SCpnt->host_scribble != i) 
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", 
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
 
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", 
-			driver_name, irq, calls[irq]);
+   if (linked_comm && SCpnt->device->queue_depth > 2
+                                     && TLDEV(SCpnt->device->type))
+      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
 
-   /* Service all the boards configured on this irq */
-   for (j = 0; sh[j] != NULL; j++) {
+   tstatus = status_byte(spp->target_status);
 
-      if (sh[j]->irq != irq) continue;
+   switch (spp->adapter_status) {
+      case ASOK:     /* status OK */
 
-      loops = 0;
-
-      /* Loop until all interrupts for a board are serviced */
-      while ((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED) {
-	 total_loops++;
-	 loops++;
-
-	 if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
-			      BN(j), HD(j)->iocount);
-
-	 spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
-
-	 /* Clear interrupt pending flag */
-	 outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
-
-	 i = spp - HD(j)->cp;
-
-	 if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
-                                            || i >= sh[j]->can_queue)
-	    panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n",
-                  BN(j), (void *)ret, HD(j)->cp);
-
-	 if (HD(j)->cp_stat[i] == IGNORE) {
-	    HD(j)->cp_stat[i] = FREE;
-	    continue;
-	    }
-	 else if (HD(j)->cp_stat[i] == LOCKED) {
-	    HD(j)->cp_stat[i] = FREE;
-	    printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
-		   BN(j), i, HD(j)->iocount);
-	    continue;
-	    }
-	 else if (HD(j)->cp_stat[i] == FREE) {
-	    printk("%s: ihdlr, mbox %d is free, count %d.\n", 
-		   BN(j), i, HD(j)->iocount);
-	    continue;
-	    }
-	 else if (HD(j)->cp_stat[i] == IN_RESET)
-	    printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-	 else if (HD(j)->cp_stat[i] != IN_USE) 
-	    panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
-
-	 HD(j)->cp_stat[i] = FREE;
-	 SCpnt = spp->SCpnt;
-
-	 if (SCpnt == NULL) 
-	    panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
-
-	 if (SCpnt->host_scribble == NULL) 
-	    panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n",
-		  BN(j), i, SCpnt->pid, SCpnt);
-
-	 if (*(unsigned int *)SCpnt->host_scribble != i) 
-	    panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\
-		  " irq %d.\n", BN(j), i, SCpnt->pid, 
-		  *(unsigned int *)SCpnt->host_scribble, irq);
-
-         if (linked_comm && SCpnt->device->queue_depth > 2
-                                           && TLDEV(SCpnt->device->type))
-            flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
-
-	 tstatus = status_byte(spp->target_status);
-
-	 switch (spp->adapter_status) {
-	    case ASOK:     /* status OK */
-
-	       /* Forces a reset if a disk drive keeps returning BUSY */
-	       if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-		  status = DID_ERROR << 16;
-
-	       /* If there was a bus reset, redo operation on each target */
-	       else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-		        && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-		  status = DID_BUS_BUSY << 16;
-
-	       /* Works around a flaw in scsi.c */
-	       else if (tstatus == CHECK_CONDITION
-			&& SCpnt->device->type == TYPE_DISK
-			&& (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-		  status = DID_BUS_BUSY << 16;
-
-	       else
-		  status = DID_OK << 16;
-
-	       if (tstatus == GOOD)
-		  HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-
-	       if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-		  printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                         "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-			 SCpnt->channel, SCpnt->target, SCpnt->lun,
-                         SCpnt->pid, spp->target_status,
-                         SCpnt->sense_buffer[2]);
-
-	       HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-
-               if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
-
-	       break;
-	    case ASST:     /* Selection Time Out */
-
-	       if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-		  status = DID_ERROR << 16;
-	       else {
-		  status = DID_TIME_OUT << 16;
-		  HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-		  }
-
-	       break;
-
-            /* Perform a limited number of internal retries */
-	    case 0x93:     /* Unexpected bus free */
-	    case 0x94:     /* Target bus phase sequence failure */
-	    case 0x96:     /* Illegal SCSI command */
-	    case 0xa3:     /* SCSI bus reset error */
-
-	       for (c = 0; c <= sh[j]->max_channel; c++) 
-	          for (k = 0; k < sh[j]->max_id; k++) 
-	             HD(j)->target_redo[k][c] = TRUE;
-   
+         /* Forces a reset if a disk drive keeps returning BUSY */
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+            status = DID_ERROR << 16;
+
+         /* If there was a bus reset, redo operation on each target */
+         else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                  && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+            status = DID_BUS_BUSY << 16;
+
+         /* Works around a flaw in scsi.c */
+         else if (tstatus == CHECK_CONDITION
+                  && SCpnt->device->type == TYPE_DISK
+                  && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+            status = DID_BUS_BUSY << 16;
 
-	    case 0x92:     /* Data over/under-run */
+         else
+            status = DID_OK << 16;
 
-	       if (SCpnt->device->type != TYPE_TAPE
-                   && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-		  status = DID_BUS_BUSY << 16;
-		  HD(j)->retries++;
-                  HD(j)->last_retried_pid = SCpnt->pid;
-                  }
-	       else 
-		  status = DID_ERROR << 16;
-
-	       break;
-	    case 0x01:     /* Invalid command */
-	    case 0x02:     /* Invalid parameters */
-	    case 0x03:     /* Invalid data list */
-	    case 0x84:     /* SCSI bus abort error */
-	    case 0x9b:     /* Auto request sense error */
-	    case 0x9f:     /* Unexpected command complete message error */
-	    case 0xff:     /* Invalid parameter in the S/G list */
-	    default:
-	       status = DID_ERROR << 16;
-	       break;
-	    }
+         if (tstatus == GOOD)
+            HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
 
-	 SCpnt->result = status | spp->target_status;
-	 HD(j)->iocount++;
+         if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+            printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                   SCpnt->channel, SCpnt->target, SCpnt->lun,
+                   SCpnt->pid, spp->target_status,
+                   SCpnt->sense_buffer[2]);
 
-	 if (loops > 1) HD(j)->multicount++;
+         HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
 
-#if defined (DEBUG_INTERRUPT)
-	 if (SCpnt->result || do_trace) 
-#else
-	 if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-	     (spp->adapter_status != ASOK && 
-	      spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-              do_trace || msg_byte(spp->target_status))
-#endif
-	    printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-		   " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-		   BN(j), i, spp->adapter_status, spp->target_status,
-		   SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                   reg, HD(j)->iocount);
+         if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
 
-	 /* Set the command state to inactive */
-	 SCpnt->host_scribble = NULL;
+         break;
+      case ASST:     /* Selection Time Out */
 
-	 restore_flags(flags);
-	 SCpnt->scsi_done(SCpnt);
-	 cli();
+         if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
+            status = DID_ERROR << 16;
+         else {
+            status = DID_TIME_OUT << 16;
+            HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+            }
 
-	 }   /* Multiple command loop */
+         break;
 
-      }   /* Boards loop */
+      /* Perform a limited number of internal retries */
+      case 0x93:     /* Unexpected bus free */
+      case 0x94:     /* Target bus phase sequence failure */
+      case 0x96:     /* Illegal SCSI command */
+      case 0xa3:     /* SCSI bus reset error */
+
+         for (c = 0; c <= sh[j]->max_channel; c++) 
+            for (k = 0; k < sh[j]->max_id; k++) 
+               HD(j)->target_redo[k][c] = TRUE;
+   
 
-   calls[irq]++;
+      case 0x92:     /* Data over/under-run */
 
-#if defined (DEBUG_SMP)
-   if (total_loops == 0) 
-     printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
-	    driver_name, irq, calls[irq]);
-#endif
+         if (SCpnt->device->type != TYPE_TAPE
+             && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+            status = DID_BUS_BUSY << 16;
+            HD(j)->retries++;
+            HD(j)->last_retried_pid = SCpnt->pid;
+            }
+         else 
+            status = DID_ERROR << 16;
+
+         break;
+      case 0x01:     /* Invalid command */
+      case 0x02:     /* Invalid parameters */
+      case 0x03:     /* Invalid data list */
+      case 0x84:     /* SCSI bus abort error */
+      case 0x9b:     /* Auto request sense error */
+      case 0x9f:     /* Unexpected command complete message error */
+      case 0xff:     /* Invalid parameter in the S/G list */
+      default:
+         status = DID_ERROR << 16;
+         break;
+      }
 
-   if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n",
-			driver_name, irq, calls[irq]);
+   SCpnt->result = status | spp->target_status;
+   HD(j)->iocount++;
 
-#if defined (DEBUG_STATISTICS)
-   if ((calls[irq] % 100000) == 10000)
-      for (j = 0; sh[j] != NULL; j++)
-	 printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j),
-		calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount);
+#if defined (DEBUG_INTERRUPT)
+   if (SCpnt->result || do_trace) 
+#else
+   if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+       (spp->adapter_status != ASOK && 
+        spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+        do_trace || msg_byte(spp->target_status))
 #endif
+      printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+             " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+             BN(j), i, spp->adapter_status, spp->target_status,
+             SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+             reg, HD(j)->iocount);
+
+   /* Set the command state to inactive */
+   SCpnt->host_scribble = NULL;
+
+   SCpnt->scsi_done(SCpnt);
+
+   if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-   restore_flags(flags);
    return;
 }
 
@@ -1664,7 +1625,7 @@
    for (i = 0; i < sh[j]->can_queue; i++) 
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
-   if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL);
+   free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
 
diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v2.1.92/linux/drivers/scsi/u14-34f.h	Sun Dec 21 17:04:49 1997
+++ linux/drivers/scsi/u14-34f.h	Sun Apr  5 11:26:29 1998
@@ -11,18 +11,41 @@
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "3.11.00"
+#define U14_34F_VERSION "4.02.00"
+
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,88)
+
+#define ULTRASTOR_14_34F {                                                   \
+                name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
+                detect:       u14_34f_detect,                                \
+                release:      u14_34f_release,                               \
+                queuecommand: u14_34f_queuecommand,                          \
+                abort:        u14_34f_abort,                                 \
+                reset:        u14_34f_reset,                                 \
+                bios_param:   u14_34f_biosparam,                             \
+                this_id:      7,                                             \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering: ENABLE_CLUSTERING,                           \
+                use_new_eh_code: 1    /* Enable new error code */            \
+                }
+
+#else /* Use old scsi code */
+
+#define ULTRASTOR_14_34F {                                                   \
+                name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
+                detect:       u14_34f_detect,                                \
+                release:      u14_34f_release,                               \
+                queuecommand: u14_34f_queuecommand,                          \
+                abort:        u14_34f_abort,                                 \
+                reset:        u14_34f_reset,                                 \
+                bios_param:   u14_34f_biosparam,                             \
+                this_id:      7,                                             \
+                unchecked_isa_dma: 1,                                        \
+                use_clustering: ENABLE_CLUSTERING,                           \
+                }
+
+#endif
 
-#define ULTRASTOR_14_34F {							   \
-		name:              "UltraStor 14F/34F rev. " U14_34F_VERSION " ",  \
-		detect:            u14_34f_detect,                                 \
-		release:           u14_34f_release,                                \
-		queuecommand:      u14_34f_queuecommand,                           \
-		abort:             u14_34f_abort,                                  \
-		reset:             u14_34f_reset,                                  \
-		bios_param:        u14_34f_biosparam,                              \
-		this_id:           7,   /* this_id, reset by detect */             \
-		unchecked_isa_dma: 1,   /* unchecked isa dma, reset by detect */   \
-		use_clustering:    ENABLE_CLUSTERING                               \
-		}
 #endif
diff -u --recursive --new-file v2.1.92/linux/fs/Config.in linux/fs/Config.in
--- v2.1.92/linux/fs/Config.in	Tue Mar 10 10:03:33 1998
+++ linux/fs/Config.in	Sat Apr  4 09:45:14 1998
@@ -62,7 +62,7 @@
 tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS
 tristate 'Apple Macintosh filesystem support (experimental)' CONFIG_HFS_FS
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
-tristate 'Kernel automounter support (experimental)' CONFIG_AUTOFS_FS
+tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
 if [ "$CONFIG_AFFS_FS" != "n" ]; then
   define_bool CONFIG_AMIGA_PARTITION y
 fi
@@ -74,6 +74,7 @@
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS
+  tristate '/dev/pts filesystem support (EXPERIMENTAL)' CONFIG_DEVPTS_FS
 fi
 bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
 endmenu
diff -u --recursive --new-file v2.1.92/linux/fs/Makefile linux/fs/Makefile
--- v2.1.92/linux/fs/Makefile	Tue Jan 20 16:44:57 1998
+++ linux/fs/Makefile	Sat Apr  4 09:45:14 1998
@@ -17,7 +17,8 @@
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
-		hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd nls
+		hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \
+		nls devpts
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
@@ -223,6 +224,14 @@
 else
   ifeq ($(CONFIG_ADFS_FS),m)
   MOD_SUB_DIRS += adfs
+  endif
+endif
+
+ifeq ($(CONFIG_DEVPTS_FS),y)
+SUB_DIRS += devpts
+else
+  ifeq ($(CONFIG_DEVPTS_FS),m)
+  MOD_SUB_DIRS += devpts
   endif
 endif
 
diff -u --recursive --new-file v2.1.92/linux/fs/adfs/super.c linux/fs/adfs/super.c
--- v2.1.92/linux/fs/adfs/super.c	Mon Feb 23 18:12:10 1998
+++ linux/fs/adfs/super.c	Sat Apr  4 09:45:14 1998
@@ -98,13 +98,11 @@
 static void adfs_put_super (struct super_block *sb)
 {
 	int i;
-	lock_super (sb);
-	sb->s_dev = 0;
+
 	for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
 		brelse (sb->u.adfs_sb.s_map[i]);
 	kfree (sb->u.adfs_sb.s_map);
 	brelse (sb->u.adfs_sb.s_sbh);
-	unlock_super (sb);
 	MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.1.92/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.1.92/linux/fs/affs/super.c	Tue Mar 10 10:03:33 1998
+++ linux/fs/affs/super.c	Sat Apr  4 09:45:14 1998
@@ -46,7 +46,6 @@
 
 	pr_debug("affs_put_super()\n");
 
-	lock_super(sb);
 	for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
 		affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
 	if (!(sb->s_flags & MS_RDONLY)) {
@@ -67,8 +66,6 @@
 	 */
 	set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize);
 
-	sb->s_dev = 0;
-	unlock_super(sb);
 	MOD_DEC_USE_COUNT;
 	return;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.1.92/linux/fs/autofs/inode.c	Fri Aug 15 10:01:29 1997
+++ linux/fs/autofs/inode.c	Sat Apr  4 09:45:14 1998
@@ -41,16 +41,13 @@
 	if ( !sbi->catatonic )
 		autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
-	lock_super(sb);
 	autofs_hash_nuke(&sbi->dirhash);
 	for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
 		if ( test_bit(n, sbi->symlink_bitmap) )
 			kfree(sbi->symlink[n].data);
 	}
 
-	sb->s_dev = 0;
 	kfree(sb->u.generic_sbp);
-	unlock_super(sb);
 
 	DPRINTK(("autofs: shutting down\n"));
 	
diff -u --recursive --new-file v2.1.92/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.1.92/linux/fs/autofs/root.c	Tue Feb  3 18:26:29 1998
+++ linux/fs/autofs/root.c	Sat Apr  4 09:45:14 1998
@@ -109,8 +109,7 @@
 	if ( !(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ) {
 		do {
 			if ( status && dentry->d_inode ) {
-				printk("autofs: lookup failure on existing dentry, status = %d, name = %s\n", status, dentry->d_name.name);
-				printk("autofs: trying to recover, but prepare for Armageddon\n");
+				printk("autofs warning: lookup failure on existing dentry, status = %d, name = %s\n", status, dentry->d_name.name);
 				break;
 			}
 
@@ -146,7 +145,10 @@
 		return !autofs_wait(sbi, &dentry->d_name);
 	}
 
-	autofs_update_usage(&sbi->dirhash,ent);
+	/* We don't update the usages for the autofs daemon itself, this
+	   is necessary for recursive autofs mounts */
+	if ( !autofs_oz_mode(sbi) )
+		autofs_update_usage(&sbi->dirhash,ent);
 
 	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
 	return 1;
@@ -188,8 +190,10 @@
 	}
 
 	/* Update the usage list */
-	ent = (struct autofs_dir_ent *) dentry->d_time;
-	autofs_update_usage(&sbi->dirhash,ent);
+	if ( !autofs_oz_mode(sbi) ) {
+		ent = (struct autofs_dir_ent *) dentry->d_time;
+		autofs_update_usage(&sbi->dirhash,ent);
+	}
 	return 1;
 }
 
diff -u --recursive --new-file v2.1.92/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.1.92/linux/fs/coda/inode.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/coda/inode.c	Sat Apr  4 09:45:14 1998
@@ -161,9 +161,6 @@
 
         ENTRY;
 
-        lock_super(sb);
-
-        sb->s_dev = 0;
 	coda_cache_clear_all(sb);
 	sb_info = coda_sbp(sb);
 	sb_info->sbi_vcomm->vc_inuse = 0;
@@ -171,7 +168,6 @@
 	printk("Coda: Bye bye.\n");
 	memset(sb_info, 0, sizeof(* sb_info));
 
-        unlock_super(sb);
         MOD_DEC_USE_COUNT;
 	EXIT;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.92/linux/fs/dcache.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/dcache.c	Thu Apr  2 21:23:19 1998
@@ -780,16 +780,26 @@
 asmlinkage int sys_getcwd(char *buf, unsigned long size)
 {
 	int error;
-	unsigned long len;
-	char * page = (char *) __get_free_page(GFP_USER);
-	char * cwd = d_path(current->fs->pwd, page, PAGE_SIZE);
+	struct dentry *pwd = current->fs->pwd; 
 
-	error = -ERANGE;
-	len = PAGE_SIZE + page - cwd;
-	if (len <= size) {
-		error = len;
-		if (copy_to_user(buf, cwd, len))
-			error = -EFAULT;
+	error = -ENOENT;
+	/* Has the current directory has been unlinked? */
+	if (pwd->d_parent != pwd && list_empty(&pwd->d_hash)) {
+		char *page = (char *) __get_free_page(GFP_USER);
+		error = -ENOMEM;
+		if (page) {
+			unsigned long len;
+			char * cwd = d_path(pwd, page, PAGE_SIZE);
+
+			error = -ERANGE;
+			len = PAGE_SIZE + page - cwd;
+			if (len <= size) {
+				error = len;
+				if (copy_to_user(buf, cwd, len))
+					error = -EFAULT;
+			}
+			free_page((unsigned long) page);
+		}
 	}
 	return error;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/devpts/Makefile linux/fs/devpts/Makefile
--- v2.1.92/linux/fs/devpts/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/devpts/Makefile	Sat Apr  4 09:45:15 1998
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux /dev/pts virtual filesystem.
+#
+
+O_TARGET := devpts.o
+O_OBJS   := root.o inode.o
+
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.92/linux/fs/devpts/devpts_i.h linux/fs/devpts/devpts_i.h
--- v2.1.92/linux/fs/devpts/devpts_i.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/devpts/devpts_i.h	Sat Apr  4 09:45:15 1998
@@ -0,0 +1,42 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/fs/devpts/devpts_i.h
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#define BUILDING_DEVPTS 1
+#include <linux/devpts_fs.h>
+
+struct devpts_sb_info {
+	u32 magic;
+	struct super_block *next;
+	struct super_block **back;
+	int setuid;
+	int setgid;
+	uid_t   uid;
+	gid_t   gid;
+	umode_t mode;
+
+	struct inode *inodes[NR_PTYS];
+};
+
+#define DEVPTS_SUPER_MAGIC 0x1cd1
+#define DEVPTS_SBI_MAGIC   0x01da1d02
+
+extern inline struct devpts_sb_info *SBI(struct super_block *sb)
+{
+	return (struct devpts_sb_info *)(sb->u.generic_sbp);
+}
+
+extern struct inode_operations devpts_root_inode_operations;
+extern struct inode_operations devpts_device_inode_operations;
diff -u --recursive --new-file v2.1.92/linux/fs/devpts/inode.c linux/fs/devpts/inode.c
--- v2.1.92/linux/fs/devpts/inode.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/devpts/inode.c	Sat Apr  4 09:45:15 1998
@@ -0,0 +1,374 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/fs/devpts/inode.c
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kdev_t.h>
+#include <linux/kernel.h>
+#include <linux/locks.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/stat.h>
+#include <linux/tty.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#include "devpts_i.h"
+
+static struct super_block *mounts = NULL;
+
+static void devpts_put_inode(struct inode *inode)
+{
+}
+
+static void devpts_delete_inode(struct inode *inode)
+{
+	inode->i_size = 0;
+}
+
+static void devpts_put_super(struct super_block *sb)
+{
+	struct devpts_sb_info *sbi = SBI(sb);
+	struct inode *inode;
+	int i;
+
+	for ( i = 0 ; i < NR_PTYS ; i++ ) {
+		if ( (inode = sbi->inodes[i]) ) {
+			if ( inode->i_count != 1 )
+				printk("devpts_put_super: badness: entry %d count %d\n",
+				       i, inode->i_count);
+			iput(inode);
+		}
+	}
+
+	*sbi->back = sbi->next;
+	if ( sbi->next )
+		SBI(sbi->next)->back = sbi->back;
+
+	kfree(sbi);
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+}
+
+static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static void devpts_read_inode(struct inode *inode);
+static void devpts_write_inode(struct inode *inode);
+
+static struct super_operations devpts_sops = {
+	devpts_read_inode,
+	devpts_write_inode,
+	devpts_put_inode,
+	devpts_delete_inode,
+	NULL,			/* notify_change */
+	devpts_put_super,
+	NULL,			/* write_super */
+	devpts_statfs,
+	NULL,			/* remount_fs */
+	NULL,			/* clear_inode */
+};
+
+static int devpts_parse_options(char *options, struct devpts_sb_info *sbi)
+{
+	int setuid = 0;
+	int setgid = 0;
+	uid_t uid = 0;		/* To shut up gcc */
+	gid_t gid = 0;
+	umode_t mode = 0600;
+	char *this_char, *value;
+
+	if ( !options ) return 1;
+	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+		if ((value = strchr(this_char,'=')) != NULL)
+			*value++ = 0;
+		if (!strcmp(this_char,"uid")) {
+			if (!value || !*value)
+				return 1;
+			uid = simple_strtoul(value,&value,0);
+			if (*value)
+				return 1;
+			setuid = 1;
+		}
+		else if (!strcmp(this_char,"gid")) {
+			if (!value || !*value)
+				return 1;
+			gid = simple_strtoul(value,&value,0);
+			if (*value)
+				return 1;
+			setgid = 1;
+		}
+		else if (!strcmp(this_char,"mode")) {
+			if (!value || !*value)
+				return 1;
+			mode = simple_strtoul(value,&value,8);
+			if (*value)
+				return 1;
+		}
+		else
+			return 1;
+	}
+	sbi->setuid  = setuid;
+	sbi->setgid  = setgid;
+	sbi->uid     = uid;
+	sbi->gid     = gid;
+	sbi->mode    = mode & ~S_IFMT;
+
+	return 0;
+}
+
+struct super_block *devpts_read_super(struct super_block *s, void *data,
+				      int silent)
+{
+	struct inode * root_inode;
+	struct dentry * root;
+	struct devpts_sb_info *sbi;
+
+	MOD_INC_USE_COUNT;
+
+	lock_super(s);
+	/* Super block already completed? */
+	if (s->s_root)
+		goto out_unlock;
+
+	sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info), GFP_KERNEL);
+	if ( !sbi )
+		goto fail_unlock;
+
+	sbi->magic = DEVPTS_SBI_MAGIC;
+	memset(sbi->inodes, 0, sizeof sbi->inodes);
+
+	s->u.generic_sbp = (void *) sbi;
+	s->s_blocksize = 1024;
+	s->s_blocksize_bits = 10;
+	s->s_magic = DEVPTS_SUPER_MAGIC;
+	s->s_op = &devpts_sops;
+	s->s_root = NULL;
+	unlock_super(s); /* shouldn't we keep it locked a while longer? */
+
+	/*
+	 * Get the root inode and dentry, but defer checking for errors.
+	 */
+	root_inode = iget(s, 1); /* inode 1 == root directory */
+	root = d_alloc_root(root_inode, NULL);
+
+	/*
+	 * Check whether somebody else completed the super block.
+	 */
+	if (s->s_root)
+		goto out_dput;
+
+	if (!root)
+		goto fail_iput;
+
+	/* Can this call block?  (It shouldn't) */
+	if ( devpts_parse_options(data,sbi) ) {
+		printk("devpts: called with bogus options\n");
+		goto fail_dput;
+	}
+
+	/*
+	 * Check whether somebody else completed the super block.
+	 */
+	if (s->s_root)
+		goto out_dec;
+	
+	/*
+	 * Success! Install the root dentry now to indicate completion.
+	 */
+	lock_super(s);
+	s->s_root = root;
+
+	sbi->next = mounts;
+	if ( sbi->next )
+		SBI(sbi->next)->back = &(sbi->next);
+	sbi->back = &mounts;
+	mounts = s;
+
+	unlock_super(s);
+	return s;
+
+	/*
+	 * Success ... somebody else completed the super block for us. 
+	 */ 
+out_unlock:
+	unlock_super(s);
+	goto out_dec;
+out_dput:
+	if (root)
+		dput(root);
+	else
+		iput(root_inode);
+out_dec:
+	MOD_DEC_USE_COUNT;
+	return s;
+	
+	/*
+	 * Failure ... clear the s_dev slot and clean up.
+	 */
+fail_dput:
+	/*
+	 * dput() can block, so we clear the super block first.
+	 */
+	s->s_dev = 0;
+	dput(root);
+	goto fail_free;
+fail_iput:
+	printk("devpts: get root dentry failed\n");
+	/*
+	 * iput() can block, so we clear the super block first.
+	 */
+	s->s_dev = 0;
+	iput(root_inode);
+fail_free:
+	kfree(sbi);
+	goto fail_dec;
+fail_unlock:
+	unlock_super(s);
+fail_dec:
+	s->s_dev = 0;
+	MOD_DEC_USE_COUNT;
+	return NULL;
+}
+
+static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+	struct statfs tmp;
+
+	tmp.f_type = DEVPTS_SUPER_MAGIC;
+	tmp.f_bsize = 1024;
+	tmp.f_blocks = 0;
+	tmp.f_bfree = 0;
+	tmp.f_bavail = 0;
+	tmp.f_files = 0;
+	tmp.f_ffree = 0;
+	tmp.f_namelen = NAME_MAX;
+	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static void devpts_read_inode(struct inode *inode)
+{
+	ino_t ino = inode->i_ino;
+
+	inode->i_op = NULL;
+	inode->i_mode = 0;
+	inode->i_nlink = 0;
+	inode->i_size = 0;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_blocks = 0;
+	inode->i_blksize = 1024;
+	inode->i_uid = inode->i_gid = 0;
+
+	if ( ino == 1 ) {
+		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+		inode->i_op = &devpts_root_inode_operations;
+		inode->i_nlink = 2;
+		return;
+	} 
+
+	ino -= 2;
+	if ( ino >= NR_PTYS )
+		return;		/* Bogus */
+	
+	inode->i_nlink = 1;
+
+	inode->i_mode = S_IFCHR;
+	inode->i_rdev = MKDEV(0,0); /* Gets filled in by devpts_pty_new() */
+
+	inode->i_op = &chrdev_inode_operations;
+
+	return;
+}
+
+static void devpts_write_inode(struct inode *inode)
+{
+}
+
+static struct file_system_type devpts_fs_type = {
+	"devpts",
+	0,
+	devpts_read_super,
+	NULL
+};
+
+void devpts_pty_new(int number, kdev_t device)
+{
+	struct super_block *sb;
+	struct devpts_sb_info *sbi;
+	struct inode *inode;
+		
+	for ( sb = mounts ; sb ; sb = sbi->next ) {
+		sbi = SBI(sb);
+
+		if ( sbi->inodes[number] ) {
+			continue; /* Already registered, this does happen */
+		}
+		
+		/* Yes, this looks backwards, but it is correct */
+		inode = iget(sb, number+2);
+		if ( inode ) {
+			inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
+			inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
+			inode->i_mode = sbi->mode | S_IFCHR;
+			inode->i_rdev = device;
+			sbi->inodes[number] = inode;
+		}
+	}
+}
+
+void devpts_pty_kill(int number)
+{
+	struct super_block *sb;
+	struct devpts_sb_info *sbi;
+	struct inode *inode;
+		
+	for ( sb = mounts ; sb ; sb = sbi->next ) {
+		sbi = SBI(sb);
+
+		inode = sbi->inodes[number];
+
+		if ( inode ) {
+			sbi->inodes[number] = NULL;
+			inode->i_nlink = 0; /* Is this right? */
+			iput(inode);
+		}
+	}
+}
+
+__initfunc(int init_devpts_fs(void))
+{
+	return register_filesystem(&devpts_fs_type);
+
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	int err = init_devpts_fs();
+	if ( !err ) {
+		devpts_upcall_new  = devpts_pty_new;
+		devpts_upcall_kill = devpts_pty_kill;
+	}
+	return err;
+}
+
+void cleanup_module(void)
+{
+	devpts_upcall_new  = NULL;
+	devpts_upcall_kill = NULL;
+	unregister_filesystem(&devpts_fs_type);
+}
+
+#endif
diff -u --recursive --new-file v2.1.92/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.1.92/linux/fs/devpts/root.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/devpts/root.c	Sat Apr  4 09:45:15 1998
@@ -0,0 +1,169 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/fs/devpts/root.c
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <linux/param.h>
+#include "devpts_i.h"
+
+static int devpts_root_readdir(struct file *,void *,filldir_t);
+static int devpts_root_lookup(struct inode *,struct dentry *);
+static int devpts_revalidate(struct dentry *);
+
+static struct file_operations devpts_root_operations = {
+	NULL,                   /* llseek */
+	NULL,                   /* read */
+	NULL,                   /* write */
+	devpts_root_readdir,    /* readdir */
+	NULL,                   /* poll */
+	NULL,			/* ioctl */
+	NULL,                   /* mmap */
+	NULL,                   /* open */
+	NULL,                   /* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL,			/* revalidate */
+	NULL			/* lock */
+};
+
+struct inode_operations devpts_root_inode_operations = {
+	&devpts_root_operations, /* file operations */
+	NULL,                   /* create */
+	devpts_root_lookup,     /* lookup */
+	NULL,                   /* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,                   /* mknod */
+	NULL,                   /* rename */
+	NULL,                   /* readlink */
+	NULL,                   /* follow_link */
+	NULL,                   /* readpage */
+	NULL,                   /* writepage */
+	NULL,                   /* bmap */
+	NULL,                   /* truncate */
+	NULL,			/* permission */
+	NULL,			/* smap */
+	NULL,			/* updatepage */
+	NULL			/* revalidate */
+};
+
+static struct dentry_operations devpts_dentry_operations = {
+	devpts_revalidate,	/* d_revalidate */
+	NULL,			/* d_hash */
+	NULL,			/* d_compare */
+};
+
+/*
+ * The normal naming convention is simply /dev/pts/<number>; this conforms
+ * to the System V naming convention
+ */
+
+#define genptsname(buf,num) sprintf(buf, "%d", num)
+
+static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct inode * inode = filp->f_dentry->d_inode;
+	struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
+	off_t nr;
+	char numbuf[16];
+
+	if (!inode || !S_ISDIR(inode->i_mode))
+		return -ENOTDIR;
+
+	nr = filp->f_pos;
+
+	switch(nr)
+	{
+	case 0:
+		if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
+			return 0;
+		filp->f_pos = ++nr;
+		/* fall through */
+	case 1:
+		if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
+			return 0;
+		filp->f_pos = ++nr;
+		/* fall through */
+	default:
+		while ( nr < NR_PTYS+2 ) {
+			int ptynr = nr - 2;
+			if ( sbi->inodes[ptynr] ) {
+				genptsname(numbuf, ptynr);
+				if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
+					return 0;
+			}
+			filp->f_pos = ++nr;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * Revalidate is called on every cache lookup.  We use it to check that
+ * the pty really does still exist.  Never revalidate negative dentries;
+ * for simplicity (fix later?)
+ */
+static int devpts_revalidate(struct dentry * dentry)
+{
+	struct devpts_sb_info *sbi;
+
+	if ( !dentry->d_inode )
+		return 0;
+
+	sbi = SBI(dentry->d_inode->i_sb);
+
+	return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
+}
+
+static int devpts_root_lookup(struct inode * dir, struct dentry * dentry)
+{
+	struct devpts_sb_info *sbi = SBI(dir->i_sb);
+	int entry, i;
+	const char *p;
+
+	if (!S_ISDIR(dir->i_mode))
+		return -ENOTDIR;
+
+	dentry->d_inode = NULL;	/* Assume failure */
+	dentry->d_op    = &devpts_dentry_operations;
+
+	if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
+		entry = 0;
+	} else if ( dentry->d_name.len < 1 ) {
+		return 0;
+	} else {
+		p = dentry->d_name.name;
+		if ( *p < '1' || *p > '9' )
+			return 0;
+		entry = *p++ - '0';
+
+		for ( i = dentry->d_name.len-1 ; i ; i-- ) {
+			if ( *p < '0' || *p > '9' )
+				return 0;
+			entry *= 10;
+			entry += (*p++ - '0');
+		}
+	}
+	
+	dentry->d_inode = sbi->inodes[entry];
+	if ( dentry->d_inode )
+		dentry->d_inode->i_count++;
+
+	d_add(dentry, dentry->d_inode);
+
+	return 0;
+}
diff -u --recursive --new-file v2.1.92/linux/fs/exec.c linux/fs/exec.c
--- v2.1.92/linux/fs/exec.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/exec.c	Thu Apr  2 09:04:00 1998
@@ -684,15 +684,8 @@
 	current->cap_permitted.cap = new_permitted;
 	current->cap_effective.cap = new_permitted & bprm->cap_effective.cap;
 	
-        /* XXX - Audit candidate */
-        if (!cap_isclear(current->cap_effective)) {
-                printk(KERN_NOTICE
-		       "raising capabilities on `%s'(pid=%d) [%04x]:%lu\n",
-		       current->comm, current->pid,
-		       kdev_t_to_nr(bprm->dentry->d_inode->i_dev), 
-		       bprm->dentry->d_inode->i_ino);
-        }
-	
+        /* AUD: Audit candidate if current->cap_effective is set */
+
         current->suid = current->euid = current->fsuid = bprm->e_uid;
         current->sgid = current->egid = current->fsgid = bprm->e_gid;
         if (current->euid != current->uid || current->egid != current->gid ||
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.1.92/linux/fs/ext2/balloc.c	Sun Dec 21 17:41:24 1997
+++ linux/fs/ext2/balloc.c	Thu Apr  2 13:39:52 1998
@@ -38,27 +38,33 @@
 
 #define in_range(b, first, len)		((b) >= (first) && (b) <= (first) + (len) - 1)
 
-static struct ext2_group_desc * get_group_desc (struct super_block * sb,
-						unsigned int block_group,
-						struct buffer_head ** bh)
+struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+					     unsigned int block_group,
+					     struct buffer_head ** bh)
 {
 	unsigned long group_desc;
 	unsigned long desc;
 	struct ext2_group_desc * gdp;
 
-	if (block_group >= sb->u.ext2_sb.s_groups_count)
-		ext2_panic (sb, "get_group_desc",
+	if (block_group >= sb->u.ext2_sb.s_groups_count) {
+		ext2_error (sb, "ext2_get_group_desc",
 			    "block_group >= groups_count - "
 			    "block_group = %d, groups_count = %lu",
 			    block_group, sb->u.ext2_sb.s_groups_count);
 
+		return NULL;
+	}
+	
 	group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
 	desc = block_group % EXT2_DESC_PER_BLOCK(sb);
-	if (!sb->u.ext2_sb.s_group_desc[group_desc])
-		ext2_panic (sb, "get_group_desc",
+	if (!sb->u.ext2_sb.s_group_desc[group_desc]) {
+		ext2_error (sb, "ext2_get_group_desc",
 			    "Group descriptor not loaded - "
 			    "block_group = %d, group_desc = %lu, desc = %lu",
 			     block_group, group_desc, desc);
+		return NULL;
+	}
+	
 	gdp = (struct ext2_group_desc *) 
 	      sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
 	if (bh)
@@ -66,22 +72,40 @@
 	return gdp + desc;
 }
 
-static void read_block_bitmap (struct super_block * sb,
+/*
+ * Read the bitmap for a given block_group, reading into the specified 
+ * slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+
+static int read_block_bitmap (struct super_block * sb,
 			       unsigned int block_group,
 			       unsigned long bitmap_nr)
 {
 	struct ext2_group_desc * gdp;
-	struct buffer_head * bh;
+	struct buffer_head * bh = NULL;
+	int retval = 0;
 	
-	gdp = get_group_desc (sb, block_group, NULL);
+	gdp = ext2_get_group_desc (sb, block_group, NULL);
+	if (!gdp)
+		goto error_out;
 	bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize);
-	if (!bh)
-		ext2_panic (sb, "read_block_bitmap",
+	if (!bh) {
+		ext2_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %lu",
-			    block_group, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
+			    block_group, (unsigned long) gdp->bg_block_bitmap);
+		retval = -EIO;
+	}
+	/*
+	 * On IO error, just leave a zero in the superblock's block pointer for
+	 * this group.  The IO will be retried next time.
+	 */
+error_out:
 	sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
 	sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
+	return retval;
 }
 
 /*
@@ -94,11 +118,13 @@
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ * 
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load__block_bitmap (struct super_block * sb,
 			       unsigned int block_group)
 {
-	int i, j;
+	int i, j, retval = 0;
 	unsigned long block_bitmap_number;
 	struct buffer_head * block_bitmap;
 
@@ -110,16 +136,16 @@
 
 	if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
 		if (sb->u.ext2_sb.s_block_bitmap[block_group]) {
-			if (sb->u.ext2_sb.s_block_bitmap_number[block_group] !=
+			if (sb->u.ext2_sb.s_block_bitmap_number[block_group] ==
 			    block_group)
-				ext2_panic (sb, "load_block_bitmap",
-					    "block_group != block_bitmap_number");
-			else
 				return block_group;
-		} else {
-			read_block_bitmap (sb, block_group, block_group);
-			return block_group;
+			ext2_error (sb, "load_block_bitmap",
+				    "block_group != block_bitmap_number");
 		}
+		retval = read_block_bitmap (sb, block_group, block_group);
+		if (retval < 0)
+			return retval;
+		return block_group;
 	}
 
 	for (i = 0; i < sb->u.ext2_sb.s_loaded_block_bitmaps &&
@@ -137,6 +163,14 @@
 		}
 		sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number;
 		sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap;
+
+		/*
+		 * There's still one special case here --- if block_bitmap == 0
+		 * then our last attempt to read the bitmap failed and we have
+		 * just ended up caching that failure.  Try again to read it.
+		 */
+		if (!block_bitmap)
+			retval = read_block_bitmap (sb, block_group, 0);
 	} else {
 		if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
 			sb->u.ext2_sb.s_loaded_block_bitmaps++;
@@ -148,24 +182,71 @@
 			sb->u.ext2_sb.s_block_bitmap[j] =
 				sb->u.ext2_sb.s_block_bitmap[j - 1];
 		}
-		read_block_bitmap (sb, block_group, 0);
+		retval = read_block_bitmap (sb, block_group, 0);
 	}
-	return 0;
+	return retval;
 }
 
+/*
+ * Load the block bitmap for a given block group.  First of all do a couple
+ * of fast lookups for common cases and then pass the request onto the guts
+ * of the bitmap loader.
+ *
+ * Return the slot number of the group in the superblock bitmap cache's on
+ * success, or a -ve error code.
+ *
+ * There is still one inconsistancy here --- if the number of groups in this
+ * filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of 
+ * differentiating between a group for which we have never performed a bitmap
+ * IO request, and a group for which the last bitmap read request failed.
+ */
 static inline int load_block_bitmap (struct super_block * sb,
 				     unsigned int block_group)
 {
-	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
-	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group)
-		return 0;
+	int slot;
 	
-	if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
-	    sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
-	    sb->u.ext2_sb.s_block_bitmap[block_group]) 
-		return block_group;
+	/*
+	 * Do the lookup for the slot.  First of all, check if we're asking
+	 * for the same slot as last time, and did we succeed that last time?
+	 */
+	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
+	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
+	    sb->u.ext2_sb.s_block_bitmap[block_group]) {
+		slot = 0;
+	}
+	/*
+	 * Or can we do a fast lookup based on a loaded group on a filesystem
+	 * small enough to be mapped directly into the superblock?
+	 */
+	else if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED && 
+		 sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
+		 sb->u.ext2_sb.s_block_bitmap[block_group]) {
+		slot = block_group;
+	}
+	/*
+	 * If not, then do a full lookup for this block group.
+	 */
+	else {
+		slot = load__block_bitmap (sb, block_group);
+	}
 
-	return load__block_bitmap (sb, block_group);
+	/*
+	 * <0 means we just got an error
+	 */
+	if (slot < 0)
+		return slot;
+	
+	/*
+	 * If it's a valid slot, we may still have cached a previous IO error,
+	 * in which case the bh in the superblock cache will be zero.
+	 */
+	if (!sb->u.ext2_sb.s_block_bitmap[slot])
+		return -EIO;
+	
+	/*
+	 * Must have been read in OK to get this far.
+	 */
+	return slot;
 }
 
 void ext2_free_blocks (const struct inode * inode, unsigned long block,
@@ -194,8 +275,7 @@
 		ext2_error (sb, "ext2_free_blocks",
 			    "Freeing blocks not in datazone - "
 			    "block = %lu, count = %lu", block, count);
-		unlock_super (sb);
-		return;
+		goto error_return;
 	}
 
 	ext2_debug ("freeing block %lu\n", block);
@@ -215,8 +295,13 @@
 		count -= overflow;
 	}
 	bitmap_nr = load_block_bitmap (sb, block_group);
+	if (bitmap_nr < 0)
+		goto error_return;
+	
 	bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
-	gdp = get_group_desc (sb, block_group, &bh2);
+	gdp = ext2_get_group_desc (sb, block_group, &bh2);
+	if (!gdp)
+		goto error_return;
 
 	if (test_opt (sb, CHECK_STRICT) &&
 	    (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
@@ -259,6 +344,7 @@
 		goto do_more;
 	}
 	sb->s_dirt = 1;
+error_return:
 	unlock_super (sb);
 	return;
 }
@@ -312,7 +398,10 @@
 	    goal >= le32_to_cpu(es->s_blocks_count))
 		goal = le32_to_cpu(es->s_first_data_block);
 	i = (goal - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb);
-	gdp = get_group_desc (sb, i, &bh2);
+	gdp = ext2_get_group_desc (sb, i, &bh2);
+	if (!gdp)
+		goto io_error;
+
 	if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
 		j = ((goal - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb));
 #ifdef EXT2FS_DEBUG
@@ -320,6 +409,9 @@
 			goal_attempts++;
 #endif
 		bitmap_nr = load_block_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			goto io_error;
+		
 		bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
 		ext2_debug ("goal is at %d:%d.\n", i, j);
@@ -384,7 +476,12 @@
 		i++;
 		if (i >= sb->u.ext2_sb.s_groups_count)
 			i = 0;
-		gdp = get_group_desc (sb, i, &bh2);
+		gdp = ext2_get_group_desc (sb, i, &bh2);
+		if (!gdp) {
+			*err = -EIO;
+			unlock_super (sb);
+			return 0;
+		}
 		if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
 			break;
 	}
@@ -393,6 +490,9 @@
 		return 0;
 	}
 	bitmap_nr = load_block_bitmap (sb, i);
+	if (bitmap_nr < 0)
+		goto io_error;
+	
 	bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 	r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
 	j = (r - bh->b_data) << 3;
@@ -455,10 +555,16 @@
 	 */
 #ifdef EXT2_PREALLOCATE
 	if (prealloc_block) {
+		int	prealloc_goal;
+
+		prealloc_goal = es->s_prealloc_blocks ?
+			es->s_prealloc_blocks : EXT2_DEFAULT_PREALLOC_BLOCKS;
+
 		*prealloc_count = 0;
 		*prealloc_block = tmp + 1;
 		for (k = 1;
-		     k < 8 && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) {
+		     k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb);
+		     k++) {
 			if (sb->dq_op)
 				if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)))
 					break;
@@ -516,6 +622,12 @@
 	unlock_super (sb);
 	*err = 0;
 	return j;
+	
+io_error:
+	*err = -EIO;
+	unlock_super (sb);
+	return 0;
+	
 }
 
 unsigned long ext2_count_free_blocks (struct super_block * sb)
@@ -533,9 +645,14 @@
 	bitmap_count = 0;
 	gdp = NULL;
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-		gdp = get_group_desc (sb, i, NULL);
+		gdp = ext2_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
 		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
 		bitmap_nr = load_block_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+		
 		x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
 				     sb->s_blocksize);
 		printk ("group %d: stored = %d, counted = %lu\n",
@@ -590,12 +707,17 @@
 	desc_blocks = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
 		      EXT2_DESC_PER_BLOCK(sb);
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-		gdp = get_group_desc (sb, i, NULL);
+		gdp = ext2_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
 		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
 		bitmap_nr = load_block_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+		
 		bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
-		if (!(sb->u.ext2_sb.s_feature_ro_compat &
+		if (!(le32_to_cpu(sb->u.ext2_sb.s_feature_ro_compat) &
 		     EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
 		    (test_root(i, 3) || test_root(i, 5) || test_root(i, 7))) {
 			if (!ext2_test_bit (0, bh->b_data))
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.1.92/linux/fs/ext2/dir.c	Tue Oct 21 08:57:29 1997
+++ linux/fs/ext2/dir.c	Thu Apr  2 13:39:51 1998
@@ -75,7 +75,8 @@
 };
 
 int ext2_check_dir_entry (const char * function, struct inode * dir,
-			  struct ext2_dir_entry * de, struct buffer_head * bh,
+			  struct ext2_dir_entry_2 * de,
+			  struct buffer_head * bh,
 			  unsigned long offset)
 {
 	const char * error_msg = NULL;
@@ -84,7 +85,7 @@
 		error_msg = "rec_len is smaller than minimal";
 	else if (le16_to_cpu(de->rec_len) % 4 != 0)
 		error_msg = "rec_len % 4 != 0";
-	else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)))
+	else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len))
 		error_msg = "rec_len is too small for name_len";
 	else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) >
 		 dir->i_sb->s_blocksize)
@@ -97,7 +98,7 @@
 			    "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
 			    dir->i_ino, error_msg, offset,
 			    (unsigned long) le32_to_cpu(de->inode),
-			    le16_to_cpu(de->rec_len), le16_to_cpu(de->name_len));
+			    le16_to_cpu(de->rec_len), de->name_len);
 	return error_msg == NULL ? 1 : 0;
 }
 
@@ -108,7 +109,7 @@
 	unsigned long offset, blk;
 	int i, num, stored;
 	struct buffer_head * bh, * tmp, * bha[16];
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	struct super_block * sb;
 	int err;
 	struct inode *inode = filp->f_dentry->d_inode;
@@ -158,7 +159,7 @@
 		 * to make sure. */
 		if (filp->f_version != inode->i_version) {
 			for (i = 0; i < sb->s_blocksize && i < offset; ) {
-				de = (struct ext2_dir_entry *) 
+				de = (struct ext2_dir_entry_2 *) 
 					(bh->b_data + i);
 				/* It's too expensive to do a full
 				 * dirent test each time round this
@@ -178,7 +179,7 @@
 		
 		while (!error && filp->f_pos < inode->i_size 
 		       && offset < sb->s_blocksize) {
-			de = (struct ext2_dir_entry *) (bh->b_data + offset);
+			de = (struct ext2_dir_entry_2 *) (bh->b_data + offset);
 			if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
 						   bh, offset)) {
 				/* On error, skip the f_pos to the
@@ -200,7 +201,7 @@
 				unsigned long version = inode->i_version;
 
 				error = filldir(dirent, de->name,
-						le16_to_cpu(de->name_len),
+						de->name_len,
 						filp->f_pos, le32_to_cpu(de->inode));
 				if (error)
 					break;
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.1.92/linux/fs/ext2/file.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/ext2/file.c	Thu Apr  2 13:39:51 1998
@@ -13,6 +13,9 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  ext2 fs regular file handling primitives
+ *
+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
+ * 	(jj@sunsite.ms.mff.cuni.cz)
  */
 
 #include <asm/uaccess.h>
@@ -36,6 +39,23 @@
 static long long ext2_file_lseek(struct file *, long long, int);
 static ssize_t ext2_file_write (struct file *, const char *, size_t, loff_t *);
 static int ext2_release_file (struct inode *, struct file *);
+#if BITS_PER_LONG < 64
+static int ext2_open_file (struct inode *, struct file *);
+
+#else
+
+#define EXT2_MAX_SIZE(bits)							\
+	(((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + 				\
+	   (1LL << (bits - 2)) * (1LL << (bits - 2)) + 				\
+	   (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * 	\
+	  (1LL << bits)) - 1)
+
+static long long ext2_max_sizes[] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13)
+};
+
+#endif
 
 /*
  * We have mostly NULL's here: the current defaults are ok for
@@ -49,7 +69,11 @@
 	NULL,			/* poll - default */
 	ext2_ioctl,		/* ioctl */
 	generic_file_mmap,	/* mmap */
+#if BITS_PER_LONG == 64	
 	NULL,			/* no special open is needed */
+#else
+	ext2_open_file,
+#endif
 	ext2_release_file,	/* release */
 	ext2_sync_file,		/* fsync */
 	NULL,			/* fasync */
@@ -86,7 +110,6 @@
 	long long offset,
 	int origin)
 {
-	long long retval;
 	struct inode *inode = file->f_dentry->d_inode;
 
 	switch (origin) {
@@ -96,17 +119,20 @@
 		case 1:
 			offset += file->f_pos;
 	}
-	retval = -EINVAL;
-	/* make sure the offset fits in 32 bits */
-	if (((unsigned long long) offset >> 32) == 0) {
-		if (offset != file->f_pos) {
-			file->f_pos = offset;
-			file->f_reada = 0;
-			file->f_version = ++event;
-		}
-		retval = offset;
+	if (((unsigned long long) offset >> 32) != 0) {
+#if BITS_PER_LONG < 64
+		return -EINVAL;
+#else
+		if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
+			return -EINVAL;
+#endif
+	} 
+	if (offset != file->f_pos) {
+		file->f_pos = offset;
+		file->f_reada = 0;
+		file->f_version = ++event;
 	}
-	return retval;
+	return offset;
 }
 
 static inline void remove_suid(struct inode *inode)
@@ -128,7 +154,7 @@
 				size_t count, loff_t *ppos)
 {
 	struct inode * inode = filp->f_dentry->d_inode;
-	__u32 pos;
+	off_t pos;
 	long block;
 	int offset;
 	int written, c;
@@ -165,14 +191,37 @@
 		pos = *ppos;
 		if (pos != *ppos)
 			return -EINVAL;
+#if BITS_PER_LONG >= 64
+		if (pos > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)])
+			return -EINVAL;
+#endif
 	}
 
 	/* Check for overflow.. */
+#if BITS_PER_LONG < 64
 	if (pos > (__u32) (pos + count)) {
 		count = ~pos; /* == 0xFFFFFFFF - pos */
 		if (!count)
 			return -EFBIG;
 	}
+#else
+	off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)];
+
+	if (pos + count > max) {
+		count = max - pos;
+		if (!count)
+			return -EFBIG;
+	}
+	if (((pos + count) >> 32) && 
+	    !(sb->u.ext2_sb.s_es->s_feature_ro_compat &
+	      cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+		/* If this is the first large file created, add a flag
+		   to the superblock */
+		sb->u.ext2_sb.s_es->s_feature_ro_compat |=
+			cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+		mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+	}
+#endif
 
 	/*
 	 * If a file has been opened in synchronous mode, we have to ensure
@@ -265,12 +314,25 @@
 
 /*
  * Called when an inode is released. Note that this is different
- * from ext2_open: open gets called at every open, but release
+ * from ext2_file_open: open gets called at every open, but release
  * gets called only when /all/ the files are closed.
  */
 static int ext2_release_file (struct inode * inode, struct file * filp)
 {
-	if (filp->f_mode & 2)
+	if (filp->f_mode & FMODE_WRITE)
 		ext2_discard_prealloc (inode);
 	return 0;
 }
+
+#if BITS_PER_LONG < 64
+/*
+ * Called when an inode is about to be open.
+ * We use this to disallow opening RW large files on 32bit systems.
+ */
+static int ext2_open_file (struct inode * inode, struct file * filp)
+{
+	if (inode->u.ext2_i.i_high_size && (filp->f_mode & FMODE_WRITE))
+		return -EFBIG;
+	return 0;
+}
+#endif
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.1.92/linux/fs/ext2/ialloc.c	Mon Sep  8 21:24:51 1997
+++ linux/fs/ext2/ialloc.c	Thu Apr  2 13:39:52 1998
@@ -37,50 +37,41 @@
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 
-static struct ext2_group_desc * get_group_desc (struct super_block * sb,
-						unsigned int block_group,
-						struct buffer_head ** bh)
-{
-	unsigned long group_desc;
-	unsigned long desc;
-	struct ext2_group_desc * gdp;
-
-	if (block_group >= sb->u.ext2_sb.s_groups_count)
-		ext2_panic (sb, "get_group_desc",
-			    "block_group >= groups_count - "
-			    "block_group = %d, groups_count = %lu",
-			    block_group, sb->u.ext2_sb.s_groups_count);
-
-	group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
-	desc = block_group % EXT2_DESC_PER_BLOCK(sb);
-	if (!sb->u.ext2_sb.s_group_desc[group_desc])
-		ext2_panic (sb, "get_group_desc",
-			    "Group descriptor not loaded - "
-			    "block_group = %d, group_desc = %lu, desc = %lu",
-			     block_group, group_desc, desc);
-	gdp = (struct ext2_group_desc *) 
-		sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
-	if (bh)
-		*bh = sb->u.ext2_sb.s_group_desc[group_desc];
-	return gdp + desc;
-}
-
-static void read_inode_bitmap (struct super_block * sb,
+/*
+ * Read the inode allocation bitmap for a given block_group, reading
+ * into the specified slot in the superblock's bitmap cache.
+ *
+ * Return >=0 on success or a -ve error code.
+ */
+static int read_inode_bitmap (struct super_block * sb,
 			       unsigned long block_group,
 			       unsigned int bitmap_nr)
 {
 	struct ext2_group_desc * gdp;
-	struct buffer_head * bh;
+	struct buffer_head * bh = NULL;
+	int retval = 0;
 
-	gdp = get_group_desc (sb, block_group, NULL);
+	gdp = ext2_get_group_desc (sb, block_group, NULL);
+	if (!gdp) {
+		retval = -EIO;
+		goto error_out;
+	}
 	bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
-	if (!bh)
-		ext2_panic (sb, "read_inode_bitmap",
+	if (!bh) {
+		ext2_error (sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
 			    "block_group = %lu, inode_bitmap = %lu",
-			    block_group, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
+			    block_group, (unsigned long) gdp->bg_inode_bitmap);
+		retval = -EIO;
+	}
+	/*
+	 * On IO error, just leave a zero in the superblock's block pointer for
+	 * this group.  The IO will be retried next time.
+	 */
+error_out:
 	sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
 	sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
+	return retval;
 }
 
 /*
@@ -93,11 +84,13 @@
  * 1/ There is one cache per mounted file system.
  * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
  *    this function reads the bitmap without maintaining a LRU cache.
+ * 
+ * Return the slot used to store the bitmap, or a -ve error code.
  */
 static int load_inode_bitmap (struct super_block * sb,
 			      unsigned int block_group)
 {
-	int i, j;
+	int i, j, retval = 0;
 	unsigned long inode_bitmap_number;
 	struct buffer_head * inode_bitmap;
 
@@ -117,7 +110,10 @@
 			else
 				return block_group;
 		} else {
-			read_inode_bitmap (sb, block_group, block_group);
+			retval = read_inode_bitmap (sb, block_group,
+						    block_group);
+			if (retval < 0)
+				return retval;
 			return block_group;
 		}
 	}
@@ -138,6 +134,15 @@
 		}
 		sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
 		sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap;
+
+		/*
+		 * There's still one special case here --- if inode_bitmap == 0
+		 * then our last attempt to read the bitmap failed and we have
+		 * just ended up caching that failure.  Try again to read it.
+		 */
+		if (!inode_bitmap)
+			retval = read_inode_bitmap (sb, block_group, 0);
+		
 	} else {
 		if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
 			sb->u.ext2_sb.s_loaded_inode_bitmaps++;
@@ -149,9 +154,9 @@
 			sb->u.ext2_sb.s_inode_bitmap[j] =
 				sb->u.ext2_sb.s_inode_bitmap[j - 1];
 		}
-		read_inode_bitmap (sb, block_group, 0);
+		retval = read_inode_bitmap (sb, block_group, 0);
 	}
-	return 0;
+	return retval;
 }
 
 /*
@@ -212,13 +217,15 @@
 	    ino > le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count)) {
 		ext2_error (sb, "free_inode",
 			    "reserved inode or nonexistent inode");
-		unlock_super (sb);
-		return;
+		goto error_return;
 	}
 	es = sb->u.ext2_sb.s_es;
 	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
 	bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
 	bitmap_nr = load_inode_bitmap (sb, block_group);
+	if (bitmap_nr < 0)
+		goto error_return;
+	
 	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
 
 	is_directory = S_ISDIR(inode->i_mode);
@@ -233,12 +240,14 @@
 		ext2_warning (sb, "ext2_free_inode",
 			      "bit already cleared for inode %lu", ino);
 	else {
-		gdp = get_group_desc (sb, block_group, &bh2);
-		gdp->bg_free_inodes_count =
-			cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
-		if (is_directory)
-			gdp->bg_used_dirs_count =
-				cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+		gdp = ext2_get_group_desc (sb, block_group, &bh2);
+		if (gdp) {
+			gdp->bg_free_inodes_count =
+				cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
+			if (is_directory)
+				gdp->bg_used_dirs_count =
+					cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+		}
 		mark_buffer_dirty(bh2, 1);
 		es->s_free_inodes_count =
 			cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
@@ -250,6 +259,7 @@
 		wait_on_buffer (bh);
 	}
 	sb->s_dirt = 1;
+error_return:
 	unlock_super (sb);
 }
 
@@ -317,9 +327,10 @@
 /* I am not yet convinced that this next bit is necessary.
 		i = dir->u.ext2_i.i_block_group;
 		for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
-			tmp = get_group_desc (sb, i, &bh2);
-			if ((le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
-			    le16_to_cpu(tmp->bg_free_inodes_count)) {
+			tmp = ext2_get_group_desc (sb, i, &bh2);
+			if (tmp &&
+			    (le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
+			     le16_to_cpu(tmp->bg_free_inodes_count)) {
 				gdp = tmp;
 				break;
 			}
@@ -329,9 +340,10 @@
 */
 		if (!gdp) {
 			for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
-				tmp = get_group_desc (sb, j, &bh2);
-				if (le16_to_cpu(tmp->bg_free_inodes_count) &&
-					le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
+				tmp = ext2_get_group_desc (sb, j, &bh2);
+				if (tmp &&
+				    le16_to_cpu(tmp->bg_free_inodes_count) &&
+				    le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
 					if (!gdp || 
 					    (le16_to_cpu(tmp->bg_free_blocks_count) >
 					     le16_to_cpu(gdp->bg_free_blocks_count))) {
@@ -348,8 +360,8 @@
 		 * Try to place the inode in its parent directory
 		 */
 		i = dir->u.ext2_i.i_block_group;
-		tmp = get_group_desc (sb, i, &bh2);
-		if (le16_to_cpu(tmp->bg_free_inodes_count))
+		tmp = ext2_get_group_desc (sb, i, &bh2);
+		if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
 			gdp = tmp;
 		else
 		{
@@ -361,8 +373,9 @@
 				i += j;
 				if (i >= sb->u.ext2_sb.s_groups_count)
 					i -= sb->u.ext2_sb.s_groups_count;
-				tmp = get_group_desc (sb, i, &bh2);
-				if (le16_to_cpu(tmp->bg_free_inodes_count)) {
+				tmp = ext2_get_group_desc (sb, i, &bh2);
+				if (tmp &&
+				    le16_to_cpu(tmp->bg_free_inodes_count)) {
 					gdp = tmp;
 					break;
 				}
@@ -376,8 +389,9 @@
 			for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
 				if (++i >= sb->u.ext2_sb.s_groups_count)
 					i = 0;
-				tmp = get_group_desc (sb, i, &bh2);
-				if (le16_to_cpu(tmp->bg_free_inodes_count)) {
+				tmp = ext2_get_group_desc (sb, i, &bh2);
+				if (tmp &&
+				    le16_to_cpu(tmp->bg_free_inodes_count)) {
 					gdp = tmp;
 					break;
 				}
@@ -391,6 +405,13 @@
 		return NULL;
 	}
 	bitmap_nr = load_inode_bitmap (sb, i);
+		if (bitmap_nr < 0) {
+		unlock_super (sb);
+		iput(inode);
+		*err = -EIO;
+		return NULL;
+	}
+
 	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
 	if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
 				      EXT2_INODES_PER_GROUP(sb))) <
@@ -504,9 +525,14 @@
 	bitmap_count = 0;
 	gdp = NULL;
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-		gdp = get_group_desc (sb, i, NULL);
+		gdp = ext2_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
 		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
 		bitmap_nr = load_inode_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+
 		x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
 				     EXT2_INODES_PER_GROUP(sb) / 8);
 		printk ("group %d: stored = %d, counted = %lu\n",
@@ -536,9 +562,14 @@
 	bitmap_count = 0;
 	gdp = NULL;
 	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
-		gdp = get_group_desc (sb, i, NULL);
+		gdp = ext2_get_group_desc (sb, i, NULL);
+		if (!gdp)
+			continue;
 		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
 		bitmap_nr = load_inode_bitmap (sb, i);
+		if (bitmap_nr < 0)
+			continue;
+		
 		x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
 				     EXT2_INODES_PER_GROUP(sb) / 8);
 		if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.1.92/linux/fs/ext2/inode.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/ext2/inode.c	Thu Apr  2 13:39:52 1998
@@ -12,9 +12,12 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
+ *  Goal-directed block allocation by Stephen Tweedie
+ * 	(sct@dcs.ed.ac.uk), 1993, 1998
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
+ * 	(jj@sunsite.ms.mff.cuni.cz)
  */
 
 #include <asm/uaccess.h>
@@ -417,9 +420,44 @@
 				 int create, int *err)
 {
 	struct buffer_head * bh;
-
+	int prev_blocks;
+	
+	prev_blocks = inode->i_blocks;
+	
 	bh = ext2_getblk (inode, block, create, err);
-	if (!bh || buffer_uptodate(bh))
+	if (!bh)
+		return bh;
+	
+	/*
+	 * If the inode has grown, and this is a directory, then perform
+	 * preallocation of a few more blocks to try to keep directory
+	 * fragmentation down.
+	 */
+	if (create && 
+	    S_ISDIR(inode->i_mode) && 
+	    inode->i_blocks > prev_blocks &&
+	    EXT2_HAS_COMPAT_FEATURE(inode->i_sb,
+				    EXT2_FEATURE_COMPAT_DIR_PREALLOC)) {
+		int i;
+		struct buffer_head *tmp_bh;
+		
+		for (i = 1;
+		     i < EXT2_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
+		     i++) {
+			/* 
+			 * ext2_getblk will zero out the contents of the
+			 * directory for us
+			 */
+			tmp_bh = ext2_getblk(inode, block+i, create, err);
+			if (!tmp_bh) {
+				brelse (bh);
+				return 0;
+			}
+			brelse (tmp_bh);
+		}
+	}
+	
+	if (buffer_uptodate(bh))
 		return bh;
 	ll_rw_block (READ, 1, &bh);
 	wait_on_buffer (bh);
@@ -447,18 +485,23 @@
 	    inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
 		ext2_error (inode->i_sb, "ext2_read_inode",
 			    "bad inode number: %lu", inode->i_ino);
-		return;
+		goto bad_inode;
 	}
 	block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
-	if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
-		ext2_panic (inode->i_sb, "ext2_read_inode",
+	if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+		ext2_error (inode->i_sb, "ext2_read_inode",
 			    "group >= groups count");
+		goto bad_inode;
+	}
 	group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
 	desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
 	bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
-	if (!bh)
-		ext2_panic (inode->i_sb, "ext2_read_inode",
+	if (!bh) {
+		ext2_error (inode->i_sb, "ext2_read_inode",
 			    "Descriptor not loaded");
+		goto bad_inode;
+	}
+
 	gdp = (struct ext2_group_desc *) bh->b_data;
 	/*
 	 * Figure out the offset within the block group inode table
@@ -467,10 +510,12 @@
 		EXT2_INODE_SIZE(inode->i_sb);
 	block = le32_to_cpu(gdp[desc].bg_inode_table) +
 		(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-		ext2_panic (inode->i_sb, "ext2_read_inode",
-			    "unable to read i-node block - "
+	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+		ext2_error (inode->i_sb, "ext2_read_inode",
+			    "unable to read inode block - "
 			    "inode=%lu, block=%lu", inode->i_ino, block);
+		goto bad_inode;
+	}
 	offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
 	raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -493,7 +538,20 @@
 	inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
 	inode->u.ext2_i.i_osync = 0;
 	inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-	inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+	if (S_ISDIR(inode->i_mode))
+		inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+	else {
+		inode->u.ext2_i.i_dir_acl = 0;
+		inode->u.ext2_i.i_high_size =
+			le32_to_cpu(raw_inode->i_size_high);
+#if BITS_PER_LONG < 64
+		if (raw_inode->i_size_high)
+			inode->i_size = (__u32)-1;
+#else
+		inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high))
+			<< 32;
+#endif
+	}
 	inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);
 	inode->u.ext2_i.i_block_group = block_group;
 	inode->u.ext2_i.i_next_alloc_block = 0;
@@ -542,6 +600,11 @@
 		inode->i_attr_flags |= ATTR_FLAG_NOATIME;
 		inode->i_flags |= MS_NOATIME;
 	}
+	return;
+	
+bad_inode:
+	make_bad_inode(inode);
+	return;
 }
 
 static int ext2_update_inode(struct inode * inode, int do_sync)
@@ -561,18 +624,22 @@
 	    inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
 		ext2_error (inode->i_sb, "ext2_write_inode",
 			    "bad inode number: %lu", inode->i_ino);
-		return 0;
+		return -EIO;
 	}
 	block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
-	if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
-		ext2_panic (inode->i_sb, "ext2_write_inode",
+	if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+		ext2_error (inode->i_sb, "ext2_write_inode",
 			    "group >= groups count");
+		return -EIO;
+	}
 	group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
 	desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
 	bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
-	if (!bh)
-		ext2_panic (inode->i_sb, "ext2_write_inode",
+	if (!bh) {
+		ext2_error (inode->i_sb, "ext2_write_inode",
 			    "Descriptor not loaded");
+		return -EIO;
+	}
 	gdp = (struct ext2_group_desc *) bh->b_data;
 	/*
 	 * Figure out the offset within the block group inode table
@@ -581,10 +648,12 @@
 		EXT2_INODE_SIZE(inode->i_sb);
 	block = le32_to_cpu(gdp[desc].bg_inode_table) +
 		(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
-		ext2_panic (inode->i_sb, "ext2_write_inode",
-			    "unable to read i-node block - "
+	if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+		ext2_error (inode->i_sb, "ext2_write_inode",
+			    "unable to read inode block - "
 			    "inode=%lu, block=%lu", inode->i_ino, block);
+		return -EIO;
+	}
 	offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;
 	raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
@@ -603,7 +672,16 @@
 	raw_inode->i_frag = inode->u.ext2_i.i_frag_no;
 	raw_inode->i_fsize = inode->u.ext2_i.i_frag_size;
 	raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);
-	raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+	if (S_ISDIR(inode->i_mode))
+		raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+	else { 
+#if BITS_PER_LONG < 64
+		raw_inode->i_size_high =
+			cpu_to_le32(inode->u.ext2_i.i_high_size);
+#else
+		raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
+#endif
+	}
 	raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version);
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
@@ -620,7 +698,7 @@
 			printk ("IO error syncing ext2 inode ["
 				"%s:%08lx]\n",
 				kdevname(inode->i_dev), inode->i_ino);
-			err = -1;
+			err = -EIO;
 		}
 	}
 	brelse (bh);
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c
--- v2.1.92/linux/fs/ext2/ioctl.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/ext2/ioctl.c	Thu Apr  2 13:39:52 1998
@@ -19,16 +19,18 @@
 int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		unsigned long arg)
 {
-	unsigned long flags;
+	unsigned int flags;
 
 	ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
 
 	switch (cmd) {
 	case EXT2_IOC_GETFLAGS:
+		flags = inode->u.ext2_i.i_flags & EXT2_FL_USER_VISIBLE;
 		return put_user(inode->u.ext2_i.i_flags, (int *) arg);
 	case EXT2_IOC_SETFLAGS:
 		if (get_user(flags, (int *) arg))
-			return -EFAULT;	
+			return -EFAULT;
+		flags = flags & EXT2_FL_USER_MODIFIABLE;
 		/*
 		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
 		 * the super user when the security level is zero.
@@ -44,7 +46,8 @@
 				return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
-		inode->u.ext2_i.i_flags = flags;
+		inode->u.ext2_i.i_flags = (inode->u.ext2_i.i_flags &
+					   ~EXT2_FL_USER_MODIFIABLE) | flags;
 		if (flags & EXT2_SYNC_FL)
 			inode->i_flags |= MS_SYNCHRONOUS;
 		else
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.1.92/linux/fs/ext2/namei.c	Mon Feb 23 18:12:10 1998
+++ linux/fs/ext2/namei.c	Thu Apr  2 13:39:51 1998
@@ -14,6 +14,8 @@
  *
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *  Directory entry file type support and forward compatibility hooks
+ *  	for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
  */
 
 #include <asm/uaccess.h>
@@ -39,18 +41,12 @@
 /*
  * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
  */
-static int ext2_match (int len, const char * const name,
-		       struct ext2_dir_entry * de)
+static inline int ext2_match (int len, const char * const name,
+		       struct ext2_dir_entry_2 * de)
 {
 	if (!de || !le32_to_cpu(de->inode) || len > EXT2_NAME_LEN)
 		return 0;
-	/*
-	 * "" means "." ---> so paths like "/usr/lib//libc.a" work
-	 */
-	if (!len && le16_to_cpu(de->name_len) == 1 && (de->name[0] == '.') &&
-	   (de->name[1] == '\0'))
-		return 1;
-	if (len != le16_to_cpu(de->name_len))
+	if (len != de->name_len)
 		return 0;
 	return !memcmp(name, de->name, len);
 }
@@ -65,7 +61,7 @@
  */
 static struct buffer_head * ext2_find_entry (struct inode * dir,
 					     const char * const name, int namelen,
-					     struct ext2_dir_entry ** res_dir)
+					     struct ext2_dir_entry_2 ** res_dir)
 {
 	struct super_block * sb;
 	struct buffer_head * bh_use[NAMEI_RA_SIZE];
@@ -96,7 +92,7 @@
 
 	for (block = 0, offset = 0; offset < dir->i_size; block++) {
 		struct buffer_head * bh;
-		struct ext2_dir_entry * de;
+		struct ext2_dir_entry_2 * de;
 		char * dlimit;
 
 		if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
@@ -105,9 +101,11 @@
 		}
 		bh = bh_use[block % NAMEI_RA_SIZE];
 		if (!bh) {
+#if 0
 			ext2_error (sb, "ext2_find_entry",
 				    "directory #%lu contains a hole at offset %lu",
 				    dir->i_ino, offset);
+#endif
 			offset += sb->s_blocksize;
 			continue;
 		}
@@ -119,13 +117,13 @@
 			break;
 		}
 
-		de = (struct ext2_dir_entry *) bh->b_data;
+		de = (struct ext2_dir_entry_2 *) bh->b_data;
 		dlimit = bh->b_data + sb->s_blocksize;
 		while ((char *) de < dlimit) {
 			if (!ext2_check_dir_entry ("ext2_find_entry", dir,
 						   de, bh, offset))
 				goto failure;
-			if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) {
+			if (ext2_match (namelen, name, de)) {
 				for (i = 0; i < NAMEI_RA_SIZE; ++i) {
 					if (bh_use[i] != bh)
 						brelse (bh_use[i]);
@@ -134,7 +132,7 @@
 				return bh;
 			}
 			offset += le16_to_cpu(de->rec_len);
-			de = (struct ext2_dir_entry *)
+			de = (struct ext2_dir_entry_2 *)
 				((char *) de + le16_to_cpu(de->rec_len));
 		}
 
@@ -158,7 +156,7 @@
 int ext2_lookup(struct inode * dir, struct dentry *dentry)
 {
 	struct inode * inode;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	struct buffer_head * bh;
 
 	if (dentry->d_name.len > EXT2_NAME_LEN)
@@ -190,13 +188,13 @@
  */
 static struct buffer_head * ext2_add_entry (struct inode * dir,
 					    const char * name, int namelen,
-					    struct ext2_dir_entry ** res_dir,
+					    struct ext2_dir_entry_2 ** res_dir,
 					    int *err)
 {
 	unsigned long offset;
 	unsigned short rec_len;
 	struct buffer_head * bh;
-	struct ext2_dir_entry * de, * de1;
+	struct ext2_dir_entry_2 * de, * de1;
 	struct super_block * sb;
 
 	*err = -EINVAL;
@@ -226,7 +224,7 @@
 		return NULL;
 	rec_len = EXT2_DIR_REC_LEN(namelen);
 	offset = 0;
-	de = (struct ext2_dir_entry *) bh->b_data;
+	de = (struct ext2_dir_entry_2 *) bh->b_data;
 	*err = -ENOSPC;
 	while (1) {
 		if ((char *)de >= sb->s_blocksize + bh->b_data) {
@@ -243,16 +241,17 @@
 
 				ext2_debug ("creating next block\n");
 
-				de = (struct ext2_dir_entry *) bh->b_data;
+				de = (struct ext2_dir_entry_2 *) bh->b_data;
 				de->inode = le32_to_cpu(0);
 				de->rec_len = le16_to_cpu(sb->s_blocksize);
 				dir->i_size = offset + sb->s_blocksize;
+				dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 				mark_inode_dirty(dir);
 			} else {
 
 				ext2_debug ("skipping to next block\n");
 
-				de = (struct ext2_dir_entry *) bh->b_data;
+				de = (struct ext2_dir_entry_2 *) bh->b_data;
 			}
 		}
 		if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
@@ -261,24 +260,25 @@
 			brelse (bh);
 			return NULL;
 		}
-		if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) {
+		if (ext2_match (namelen, name, de)) {
 				*err = -EEXIST;
 				brelse (bh);
 				return NULL;
 		}
 		if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
-		    (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)) + rec_len)) {
+		    (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
 			offset += le16_to_cpu(de->rec_len);
 			if (le32_to_cpu(de->inode)) {
-				de1 = (struct ext2_dir_entry *) ((char *) de +
-					EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+				de1 = (struct ext2_dir_entry_2 *) ((char *) de +
+					EXT2_DIR_REC_LEN(de->name_len));
 				de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) -
-					EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
-				de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+					EXT2_DIR_REC_LEN(de->name_len));
+				de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
 				de = de1;
 			}
 			de->inode = cpu_to_le32(0);
-			de->name_len = cpu_to_le16(namelen);
+			de->name_len = namelen;
+			de->file_type = 0;
 			memcpy (de->name, name, namelen);
 			/*
 			 * XXX shouldn't update any times until successful
@@ -292,6 +292,7 @@
 			 * and/or different from the directory change time.
 			 */
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+			dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 			mark_inode_dirty(dir);
 			dir->i_version = ++event;
 			mark_buffer_dirty(bh, 1);
@@ -300,7 +301,7 @@
 			return bh;
 		}
 		offset += le16_to_cpu(de->rec_len);
-		de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+		de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
 	}
 	brelse (bh);
 	return NULL;
@@ -310,15 +311,15 @@
  * ext2_delete_entry deletes a directory entry by merging it with the
  * previous entry
  */
-static int ext2_delete_entry (struct ext2_dir_entry * dir,
+static int ext2_delete_entry (struct ext2_dir_entry_2 * dir,
 			      struct buffer_head * bh)
 {
-	struct ext2_dir_entry * de, * pde;
+	struct ext2_dir_entry_2 * de, * pde;
 	int i;
 
 	i = 0;
 	pde = NULL;
-	de = (struct ext2_dir_entry *) bh->b_data;
+	de = (struct ext2_dir_entry_2 *) bh->b_data;
 	while (i < bh->b_size) {
 		if (!ext2_check_dir_entry ("ext2_delete_entry", NULL, 
 					   de, bh, i))
@@ -333,7 +334,7 @@
 		}
 		i += le16_to_cpu(de->rec_len);
 		pde = de;
-		de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+		de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
 	}
 	return -ENOENT;
 }
@@ -350,7 +351,7 @@
 {
 	struct inode * inode;
 	struct buffer_head * bh;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	int err = -EIO;
 
 	/*
@@ -371,6 +372,9 @@
 		return err;
 	}
 	de->inode = cpu_to_le32(inode->i_ino);
+	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		de->file_type = EXT2_FT_REG_FILE;
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -386,7 +390,7 @@
 {
 	struct inode * inode;
 	struct buffer_head * bh;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	int err = -EIO;
 
 	err = -ENAMETOOLONG;
@@ -400,29 +404,48 @@
 	inode->i_uid = current->fsuid;
 	inode->i_mode = mode;
 	inode->i_op = NULL;
-	if (S_ISREG(inode->i_mode))
+	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+	if (!bh)
+		goto out_no_entry;
+	de->inode = cpu_to_le32(inode->i_ino);
+	dir->i_version = ++event;
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext2_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode)) {
+		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+					      EXT2_FEATURE_INCOMPAT_FILETYPE))
+			de->file_type = EXT2_FT_REG_FILE;
+	} else if (S_ISDIR(inode->i_mode)) {
 		inode->i_op = &ext2_dir_inode_operations;
 		if (dir->i_mode & S_ISGID)
 			inode->i_mode |= S_ISGID;
+		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+					      EXT2_FEATURE_INCOMPAT_FILETYPE))
+			de->file_type = EXT2_FT_DIR;
 	}
-	else if (S_ISLNK(inode->i_mode))
+	else if (S_ISLNK(inode->i_mode)) {
 		inode->i_op = &ext2_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
+		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+					      EXT2_FEATURE_INCOMPAT_FILETYPE))
+			de->file_type = EXT2_FT_SYMLINK;
+	} else if (S_ISCHR(inode->i_mode)) {
 		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
+		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+					      EXT2_FEATURE_INCOMPAT_FILETYPE))
+			de->file_type = EXT2_FT_CHRDEV;
+	} else if (S_ISBLK(inode->i_mode)) {
 		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode)) 
+		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+					      EXT2_FEATURE_INCOMPAT_FILETYPE))
+			de->file_type = EXT2_FT_BLKDEV;
+	} else if (S_ISFIFO(inode->i_mode))  {
 		init_fifo(inode);
+		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+					      EXT2_FEATURE_INCOMPAT_FILETYPE))
+			de->file_type = EXT2_FT_FIFO;
+	}
 	if (S_ISBLK(mode) || S_ISCHR(mode))
 		inode->i_rdev = to_kdev_t(rdev);
 	mark_inode_dirty(inode);
-	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-	if (!bh)
-		goto out_no_entry;
-	de->inode = cpu_to_le32(inode->i_ino);
-	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
@@ -445,7 +468,7 @@
 {
 	struct inode * inode;
 	struct buffer_head * bh, * dir_block;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	int err;
 
 	err = -ENAMETOOLONG;
@@ -463,6 +486,7 @@
 
 	inode->i_op = &ext2_dir_inode_operations;
 	inode->i_size = inode->i_sb->s_blocksize;
+	inode->i_blocks = 0;	
 	dir_block = ext2_bread (inode, 0, 1, &err);
 	if (!dir_block) {
 		inode->i_nlink--; /* is this nlink == 0? */
@@ -470,17 +494,22 @@
 		iput (inode);
 		return err;
 	}
-	inode->i_blocks = inode->i_sb->s_blocksize / 512;
-	de = (struct ext2_dir_entry *) dir_block->b_data;
+	de = (struct ext2_dir_entry_2 *) dir_block->b_data;
 	de->inode = cpu_to_le32(inode->i_ino);
-	de->name_len = cpu_to_le16(1);
-	de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+	de->name_len = 1;
+	de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
 	strcpy (de->name, ".");
-	de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		de->file_type = EXT2_FT_DIR;
+	de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
 	de->inode = cpu_to_le32(dir->i_ino);
 	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
-	de->name_len = cpu_to_le16(2);
+	de->name_len = 2;
 	strcpy (de->name, "..");
+	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		de->file_type = EXT2_FT_DIR;
 	inode->i_nlink = 2;
 	mark_buffer_dirty(dir_block, 1);
 	brelse (dir_block);
@@ -492,6 +521,9 @@
 	if (!bh)
 		goto out_no_entry;
 	de->inode = cpu_to_le32(inode->i_ino);
+	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		de->file_type = EXT2_FT_DIR;
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -499,6 +531,7 @@
 		wait_on_buffer (bh);
 	}
 	dir->i_nlink++;
+	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 	mark_inode_dirty(dir);
 	d_instantiate(dentry, inode);
 	brelse (bh);
@@ -520,7 +553,7 @@
 {
 	unsigned long offset;
 	struct buffer_head * bh;
-	struct ext2_dir_entry * de, * de1;
+	struct ext2_dir_entry_2 * de, * de1;
 	struct super_block * sb;
 	int err;
 
@@ -532,8 +565,8 @@
 			      inode->i_ino);
 		return 1;
 	}
-	de = (struct ext2_dir_entry *) bh->b_data;
-	de1 = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+	de = (struct ext2_dir_entry_2 *) bh->b_data;
+	de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
 	if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || 
 	    strcmp (".", de->name) || strcmp ("..", de1->name)) {
 	    	ext2_warning (inode->i_sb, "empty_dir",
@@ -542,19 +575,21 @@
 		return 1;
 	}
 	offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
-	de = (struct ext2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len));
+	de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len));
 	while (offset < inode->i_size ) {
 		if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
 			brelse (bh);
 			bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err);
 			if (!bh) {
+#if 0
 				ext2_error (sb, "empty_dir",
 					    "directory #%lu contains a hole at offset %lu",
 					    inode->i_ino, offset);
+#endif
 				offset += sb->s_blocksize;
 				continue;
 			}
-			de = (struct ext2_dir_entry *) bh->b_data;
+			de = (struct ext2_dir_entry_2 *) bh->b_data;
 		}
 		if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,
 					   offset)) {
@@ -566,7 +601,7 @@
 			return 0;
 		}
 		offset += le16_to_cpu(de->rec_len);
-		de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+		de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
 	}
 	brelse (bh);
 	return 1;
@@ -577,7 +612,7 @@
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 
 	retval = -ENAMETOOLONG;
 	if (dentry->d_name.len > EXT2_NAME_LEN)
@@ -652,6 +687,7 @@
 	mark_inode_dirty(inode);
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 	mark_inode_dirty(dir);
 	d_delete(dentry);
 
@@ -666,7 +702,7 @@
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 
 	retval = -ENAMETOOLONG;
 	if (dentry->d_name.len > EXT2_NAME_LEN)
@@ -711,6 +747,7 @@
 		wait_on_buffer (bh);
 	}
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 	mark_inode_dirty(dir);
 	inode->i_nlink--;
 	mark_inode_dirty(inode);
@@ -726,7 +763,7 @@
 
 int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
 {
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	struct inode * inode;
 	struct buffer_head * bh = NULL, * name_block = NULL;
 	char * link;
@@ -774,6 +811,9 @@
 	if (!bh)
 		goto out_no_entry;
 	de->inode = cpu_to_le32(inode->i_ino);
+	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		de->file_type = EXT2_FT_SYMLINK;
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -797,7 +837,7 @@
 		struct inode * dir, struct dentry *dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
-	struct ext2_dir_entry * de;
+	struct ext2_dir_entry_2 * de;
 	struct buffer_head * bh;
 	int err;
 
@@ -815,6 +855,21 @@
 		return err;
 
 	de->inode = cpu_to_le32(inode->i_ino);
+	if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+		if (S_ISREG(inode->i_mode))
+			de->file_type = EXT2_FT_REG_FILE;
+		else if (S_ISDIR(inode->i_mode))
+			de->file_type = EXT2_FT_DIR;
+		else if (S_ISLNK(inode->i_mode))
+			de->file_type = EXT2_FT_SYMLINK;
+		else if (S_ISCHR(inode->i_mode))
+			de->file_type = EXT2_FT_CHRDEV;
+		else if (S_ISBLK(inode->i_mode))
+			de->file_type = EXT2_FT_BLKDEV;
+		else if (S_ISFIFO(inode->i_mode))  
+			de->file_type = EXT2_FT_FIFO;
+	}
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -831,8 +886,8 @@
 }
 
 #define PARENT_INO(buffer) \
-	((struct ext2_dir_entry *) ((char *) buffer + \
-	le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
+	((struct ext2_dir_entry_2 *) ((char *) buffer + \
+	le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode
 
 /*
  * rename uses retrying to avoid race-conditions: at least they should be
@@ -850,7 +905,7 @@
 {
 	struct inode * old_inode, * new_inode;
 	struct buffer_head * old_bh, * new_bh, * dir_bh;
-	struct ext2_dir_entry * old_de, * new_de;
+	struct ext2_dir_entry_2 * old_de, * new_de;
 	int retval;
 
 	old_bh = new_bh = dir_bh = NULL;
@@ -942,6 +997,10 @@
 	 * ok, that's it
 	 */
 	new_de->inode = le32_to_cpu(old_inode->i_ino);
+	if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
+				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		new_de->file_type = old_de->file_type;
+	
 	ext2_delete_entry (old_de, old_bh);
 
 	old_dir->i_version = ++event;
@@ -951,6 +1010,7 @@
 		mark_inode_dirty(new_inode);
 	}
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+	old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 	mark_inode_dirty(old_dir);
 	if (dir_bh) {
 		PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
@@ -962,6 +1022,7 @@
 			mark_inode_dirty(new_inode);
 		} else {
 			new_dir->i_nlink++;
+			new_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 			mark_inode_dirty(new_dir);
 		}
 	}
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.1.92/linux/fs/ext2/super.c	Wed Jul 16 10:26:21 1997
+++ linux/fs/ext2/super.c	Sat Apr  4 09:45:15 1998
@@ -107,12 +107,10 @@
 	int db_count;
 	int i;
 
-	lock_super (sb);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
 		mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
 	}
-	sb->s_dev = 0;
 	db_count = sb->u.ext2_sb.s_db_per_group;
 	for (i = 0; i < db_count; i++)
 		if (sb->u.ext2_sb.s_group_desc[i])
@@ -126,7 +124,7 @@
 		if (sb->u.ext2_sb.s_block_bitmap[i])
 			brelse (sb->u.ext2_sb.s_block_bitmap[i]);
 	brelse (sb->u.ext2_sb.s_sbh);
-	unlock_super (sb);
+
 	MOD_DEC_USE_COUNT;
 	return;
 }
@@ -516,11 +514,11 @@
 			goto failed_mount;
 		}
 	}
-	sb->u.ext2_sb.s_feature_compat = es->s_feature_compat;
-	sb->u.ext2_sb.s_feature_incompat = es->s_feature_incompat;
-	sb->u.ext2_sb.s_feature_ro_compat = es->s_feature_ro_compat;
+	sb->u.ext2_sb.s_feature_compat = le32_to_cpu(es->s_feature_compat);
+	sb->u.ext2_sb.s_feature_incompat = le32_to_cpu(es->s_feature_incompat);
+	sb->u.ext2_sb.s_feature_ro_compat = le32_to_cpu(es->s_feature_ro_compat);
 	sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
-				   (__s32) le32_to_cpu(es->s_log_frag_size);
+				   le32_to_cpu(es->s_log_frag_size);
 	if (sb->u.ext2_sb.s_frag_size)
 		sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
 						  sb->u.ext2_sb.s_frag_size;
diff -u --recursive --new-file v2.1.92/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.1.92/linux/fs/fat/inode.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/fat/inode.c	Sat Apr  4 09:45:15 1998
@@ -72,7 +72,6 @@
 
 void fat_put_super(struct super_block *sb)
 {
-	lock_super(sb);
 	if (MSDOS_SB(sb)->cvf_format) {
 		dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version);
 		MSDOS_SB(sb)->cvf_format->unmount_cvf(sb);
@@ -99,8 +98,7 @@
 		kfree(MSDOS_SB(sb)->options.iocharset);
 		MSDOS_SB(sb)->options.iocharset = NULL;
 	}
-	sb->s_dev = 0;
-	unlock_super(sb);
+
 	MOD_DEC_USE_COUNT;
 	return;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.1.92/linux/fs/filesystems.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/filesystems.c	Sat Apr  4 09:45:15 1998
@@ -26,6 +26,7 @@
 #include <linux/auto_fs.h>
 #include <linux/ntfs_fs.h>
 #include <linux/hfs_fs.h>
+#include <linux/devpts_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -137,6 +138,10 @@
 
 #ifdef CONFIG_ADFS_FS
 	init_adfs_fs();
+#endif
+
+#ifdef CONFIG_DEVPTS_FS
+	init_devpts_fs();
 #endif
 
 #ifdef CONFIG_NLS
diff -u --recursive --new-file v2.1.92/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.1.92/linux/fs/hfs/super.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/super.c	Sat Apr  4 09:45:15 1998
@@ -122,8 +122,6 @@
 {
 	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
  
-	lock_super(sb);
-
 	if (!(sb->s_flags & MS_RDONLY)) {
 		hfs_mdb_commit(mdb, 0);
 		sb->s_dirt = 0;
@@ -135,12 +133,8 @@
 	/* restore default blocksize for the device */
 	set_blocksize(sb->s_dev, BLOCK_SIZE);
 
-	/* invalidate the superblock */
-	sb->s_dev = 0;
-
 	MOD_DEC_USE_COUNT;
 
-	unlock_super(sb);
 	return;
 }
 
diff -u --recursive --new-file v2.1.92/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v2.1.92/linux/fs/hpfs/hpfs_fs.c	Tue Nov 18 10:36:45 1997
+++ linux/fs/hpfs/hpfs_fs.c	Sat Apr  4 09:45:16 1998
@@ -731,9 +731,6 @@
 
 static void hpfs_put_super(struct super_block *s)
 {
-	lock_super(s);
-	s->s_dev = 0;
-	unlock_super(s);
 	MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.1.92/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.1.92/linux/fs/isofs/inode.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/isofs/inode.c	Sat Apr  4 09:45:16 1998
@@ -49,14 +49,12 @@
 		sb->u.isofs_sb.s_nls_iocharset = NULL;
 	}
 #endif
-	lock_super(sb);
 
 #ifdef LEAK_CHECK
 	printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
 	       check_malloc, check_bread);
 #endif
-	sb->s_dev = 0;
-	unlock_super(sb);
+
 	MOD_DEC_USE_COUNT;
 	return;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.1.92/linux/fs/minix/inode.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/minix/inode.c	Sat Apr  4 09:45:16 1998
@@ -59,7 +59,6 @@
 {
 	int i;
 
-	lock_super(sb);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
 		mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
@@ -70,8 +69,7 @@
 		brelse(sb->u.minix_sb.s_zmap[i]);
 	brelse (sb->u.minix_sb.s_sbh);
 	kfree(sb->u.minix_sb.s_imap);
-	sb->s_dev = 0;
-	unlock_super(sb);
+
 	MOD_DEC_USE_COUNT;
 	return;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.92/linux/fs/ncpfs/inode.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/ncpfs/inode.c	Sat Apr  4 09:45:16 1998
@@ -407,8 +407,6 @@
 {
 	struct ncp_server *server = NCP_SBP(sb);
 
-	lock_super(sb);
-
 	ncp_lock_server(server);
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
@@ -423,9 +421,6 @@
 	ncp_kfree_s(server->packet, server->packet_size);
 
 	ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
-
-	sb->s_dev = 0;
-	unlock_super(sb);
 
 	MOD_DEC_USE_COUNT;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.92/linux/fs/nfs/inode.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/nfs/inode.c	Sat Apr  4 09:45:16 1998
@@ -126,10 +126,6 @@
 	struct nfs_server *server = &sb->u.nfs_sb.s_server;
 	struct rpc_clnt	*rpc;
 
-	/*
-	 * Lock the super block while we bring down the daemons.
-	 */
-	lock_super(sb);
 	if ((rpc = server->client) != NULL)
 		rpc_shutdown_client(rpc);
 
@@ -142,8 +138,7 @@
 	nfs_invalidate_dircache_sb(sb);
 
 	kfree(server->hostname);
-	sb->s_dev = 0;
-	unlock_super(sb);
+
 	MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.1.92/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.1.92/linux/fs/ntfs/fs.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/ntfs/fs.c	Sat Apr  4 09:45:17 1998
@@ -693,12 +693,9 @@
 	ntfs_volume *vol;
 
 	ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
-	/* Ensure that nobody uses the super block anymore */
-	lock_super(sb);
+
 	vol=NTFS_SB2VOL(sb);
-	/* Tell the kernel that the super block is no more used */
-	sb->s_dev = 0;
-	unlock_super(sb);
+
 	ntfs_release_volume(vol);
 	if(vol->nls_map)
 		unload_nls(vol->nls_map);
diff -u --recursive --new-file v2.1.92/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.1.92/linux/fs/proc/inode.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/proc/inode.c	Sat Apr  4 09:45:17 1998
@@ -80,20 +80,13 @@
 	}
 }
 
-static void proc_put_super(struct super_block *sb)
-{
-	lock_super(sb);
-	sb->s_dev = 0;
-	unlock_super(sb);
-}
-
 static struct super_operations proc_sops = { 
 	proc_read_inode,
 	proc_write_inode,
 	proc_put_inode,
 	proc_delete_inode,	/* delete_inode(struct inode *) */
 	NULL,
-	proc_put_super,
+	NULL,
 	NULL,
 	proc_statfs,
 	NULL
@@ -198,9 +191,9 @@
 	read_lock(&tasklist_lock);
 	p = find_task_by_pid(pid);
 
-	if (p != NULL)
+	if (p && p->fs)
 		de = p->fs->root;
-	read_unlock(&tasklist_lock);
+	read_unlock(&tasklist_lock);	/* FIXME! */
 
 	if (p == NULL)
 		return -EACCES;		/* ENOENT? */
diff -u --recursive --new-file v2.1.92/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.1.92/linux/fs/proc/link.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/proc/link.c	Wed Apr  1 20:16:52 1998
@@ -20,12 +20,6 @@
 static struct dentry * proc_follow_link(struct dentry *, struct dentry *);
 
 /*
- * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke 
- * when the files[] array was updated only after the open code
- */
-#undef PLAN9_SEMANTICS
-
-/*
  * links can't do much...
  */
 static struct file_operations proc_fd_link_operations = {
diff -u --recursive --new-file v2.1.92/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.1.92/linux/fs/romfs/inode.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/romfs/inode.c	Sat Apr  4 09:45:17 1998
@@ -157,9 +157,6 @@
 static void
 romfs_put_super(struct super_block *sb)
 {
-	lock_super(sb);
-	sb->s_dev = 0;
-	unlock_super(sb);
 	MOD_DEC_USE_COUNT;
 	return;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.92/linux/fs/smbfs/inode.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/smbfs/inode.c	Sat Apr  4 09:45:17 1998
@@ -322,8 +322,6 @@
 {
 	struct smb_sb_info *server = &(sb->u.smbfs_sb);
 
-	lock_super(sb);
-
 	if (server->sock_file) {
 		smb_proc_disconnect(server);
 		smb_dont_catch_keepalive(server);
@@ -337,9 +335,6 @@
 	kfree(sb->u.smbfs_sb.temp_buf);
 	if (server->packet)
 		smb_vfree(server->packet);
-	sb->s_dev = 0;
-
-	unlock_super(sb);
 
 	MOD_DEC_USE_COUNT;
 }
diff -u --recursive --new-file v2.1.92/linux/fs/super.c linux/fs/super.c
--- v2.1.92/linux/fs/super.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/super.c	Sat Apr  4 09:45:18 1998
@@ -668,18 +668,26 @@
 	if (retval)
 		goto out;
 
-	/* Forget any inodes */
-	if (invalidate_inodes(sb)) {
-		printk("VFS: Busy inodes after unmount. "
-			"Self-destruct in 5 seconds. Bye-bye..\n");
-	}
-
 	if (sb->s_op) {
 		if (sb->s_op->write_super && sb->s_dirt)
 			sb->s_op->write_super(sb);
+	}
+
+	lock_super(sb);
+	if (sb->s_op) {
 		if (sb->s_op->put_super)
 			sb->s_op->put_super(sb);
 	}
+
+	/* Forget any remaining inodes */
+	if (invalidate_inodes(sb)) {
+		printk("VFS: Busy inodes after unmount. "
+			"Self-destruct in 5 seconds.  Have a nice day...\n");
+	}
+
+	sb->s_dev = 0;		/* Free the superblock */
+	unlock_super(sb);
+
 	remove_vfsmnt(dev);
 out:
 	return retval;
diff -u --recursive --new-file v2.1.92/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.92/linux/fs/sysv/inode.c	Mon Feb 23 18:12:11 1998
+++ linux/fs/sysv/inode.c	Sat Apr  4 09:45:18 1998
@@ -492,12 +492,14 @@
 	sb->s_op = &sysv_sops;
 	root_inode = iget(sb,SYSV_ROOT_INO);
 	sb->s_root = d_alloc_root(root_inode, NULL);
-	unlock_super(sb);
 	if (!sb->s_root) {
 		printk("SysV FS: get root inode failed\n");
 		sysv_put_super(sb);
+		sb->sb_dev = 0;
+		unlock_super(sb);
 		return NULL;
 	}
+	unlock_super(sb);
 	sb->s_dirt = 1;
 	/* brelse(bh);  resp.  brelse(bh1); brelse(bh2);
 	   occurs when the disk is unmounted. */
@@ -530,15 +532,14 @@
 
 void sysv_put_super(struct super_block *sb)
 {
-	/* we can assume sysv_write_super() has already been called */
-	lock_super(sb);
+	/* we can assume sysv_write_super() has already been called, and
+	   and that the superblock is locked */
 	brelse(sb->sv_bh1);
 	if (sb->sv_bh1 != sb->sv_bh2) brelse(sb->sv_bh2);
 	/* switch back to default block size */
 	if (sb->s_blocksize != BLOCK_SIZE)
 		set_blocksize(sb->s_dev,BLOCK_SIZE);
-	sb->s_dev = 0;
-	unlock_super(sb);
+
 	MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.1.92/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.92/linux/fs/ufs/ufs_super.c	Mon Feb 23 18:12:11 1998
+++ linux/fs/ufs/ufs_super.c	Sat Apr  4 09:45:18 1998
@@ -335,15 +335,13 @@
 		printk("ufs_put_super\n"); /* XXX */
         }
 
-	lock_super (sb);
+
 	/* XXX - sync fs data, set state to ok, and flush buffers */
 	set_blocksize (sb->s_dev, BLOCK_SIZE);
-	sb->s_dev = 0;
 
 	/* XXX - free allocated kernel memory */
 	/* includes freeing usb page */
 
-	unlock_super (sb);
 	MOD_DEC_USE_COUNT;
 
 	return;
diff -u --recursive --new-file v2.1.92/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.1.92/linux/include/asm-i386/smp.h	Fri Jan 23 18:10:32 1998
+++ linux/include/asm-i386/smp.h	Sun Apr  5 12:08:41 1998
@@ -155,7 +155,6 @@
 extern int smp_found_config;
 extern int smp_scan_config(unsigned long, unsigned long);
 extern unsigned long smp_alloc_memory(unsigned long mem_base);
-extern unsigned char *apic_reg;
 extern unsigned char boot_cpu_id;
 extern unsigned long cpu_present_map;
 extern volatile int cpu_number_map[NR_CPUS];
@@ -192,24 +191,25 @@
  *	APIC handlers: Note according to the Intel specification update
  *	you should put reads between APIC writes.
  *	Intel Pentium processor specification update [11AP, pg 64]
- *		"Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle"
+ *	"Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle"
  */
 
+#define APIC_BASE ((char *)0xFEE00000)
+
 extern __inline void apic_write(unsigned long reg, unsigned long v)
 {
-	*((volatile unsigned long *)(apic_reg+reg))=v;
+	*((volatile unsigned long *)(APIC_BASE+reg))=v;
 }
 
 extern __inline unsigned long apic_read(unsigned long reg)
 {
-	return *((volatile unsigned long *)(apic_reg+reg));
+	return *((volatile unsigned long *)(APIC_BASE+reg));
 }
 
 /*
- *	This function is needed by all SMP systems. It must _always_ be valid from the initial
- *	startup. This may require magic on some systems (in the i86 case we dig out the boot 
- *	cpu id from the config and set up a fake apic_reg pointer so that before we activate
- *	the apic we get the right answer). Hopefully other processors are more sensible 8)
+ * This function is needed by all SMP systems. It must _always_ be valid
+ * from the initial startup. We map APIC_BASE very early in page_setup(),
+ * so this is correct in the x86 case.
  */
 
 #define smp_processor_id() (current->processor)
@@ -217,7 +217,7 @@
 extern __inline int hard_smp_processor_id(void)
 {
 	/* we don't want to mark this access volatile - bad code generation */
-	return GET_APIC_ID(*(unsigned long *)(apic_reg+APIC_ID));
+	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
 }
 
 #endif /* !ASSEMBLY */
diff -u --recursive --new-file v2.1.92/linux/include/asm-i386/string.h linux/include/asm-i386/string.h
--- v2.1.92/linux/include/asm-i386/string.h	Thu Mar 26 15:57:05 1998
+++ linux/include/asm-i386/string.h	Wed Apr  1 20:46:09 1998
@@ -442,7 +442,7 @@
 		case 0: COMMON(""); return to;
 		case 1: COMMON("\n\tmovsb"); return to;
 		case 2: COMMON("\n\tmovsw"); return to;
-		case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
+		default: COMMON("\n\tmovsw\n\tmovsb"); return to;
 	}
 #undef COMMON
 }
@@ -593,7 +593,7 @@
 		case 0: COMMON(""); return s;
 		case 1: COMMON("\n\tstosb"); return s;
 		case 2: COMMON("\n\tstosw"); return s;
-		case 3: COMMON("\n\tstosw\n\tstosb"); return s;
+		default: COMMON("\n\tstosw\n\tstosb"); return s;
 	}
 #undef COMMON
 }
diff -u --recursive --new-file v2.1.92/linux/include/linux/bios32.h linux/include/linux/bios32.h
--- v2.1.92/linux/include/linux/bios32.h	Tue Jan 14 16:46:07 1997
+++ linux/include/linux/bios32.h	Mon Apr  6 16:30:55 1998
@@ -1,61 +1,34 @@
 /*
- * BIOS32, PCI BIOS functions and defines
- * Copyright 1994, Drew Eckhardt
- * 
- * For more information, please consult 
- * 
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * P.O. Box 14070
- * Portland, OR 97214
- * U. S. A.
- * Phone: 800-433-5177 / +1-503-797-4207
- * Fax: +1-503-234-6762 
- * 
- * Manuals are $25 each or $50 for all three, plus $7 shipping 
- * within the United States, $35 abroad.
+ *	This is only a stub file to make drivers not yet converted to the new
+ *	PCI probing mechanism work. [mj]
  */
 
 #ifndef BIOS32_H
 #define BIOS32_H
 
-/*
- * Error values that may be returned by the PCI bios.  Use
- * pcibios_strerror() to convert to a printable string.
- */
-#define PCIBIOS_SUCCESSFUL		0x00
-#define PCIBIOS_FUNC_NOT_SUPPORTED	0x81
-#define PCIBIOS_BAD_VENDOR_ID		0x83
-#define PCIBIOS_DEVICE_NOT_FOUND	0x86
-#define PCIBIOS_BAD_REGISTER_NUMBER	0x87
-#define PCIBIOS_SET_FAILED		0x88
-#define PCIBIOS_BUFFER_TOO_SMALL	0x89
-
-extern int pcibios_present (void);
-extern unsigned long pcibios_init (unsigned long memory_start,
-				   unsigned long memory_end);
-extern unsigned long pcibios_fixup (unsigned long memory_start,
-				    unsigned long memory_end);
-extern int pcibios_find_class (unsigned int class_code, unsigned short index, 
-			       unsigned char *bus, unsigned char *dev_fn);
-extern int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
-				unsigned short index, unsigned char *bus,
-				unsigned char *dev_fn);
-extern int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
-				     unsigned char where, unsigned char *val);
-extern int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
-				     unsigned char where, unsigned short *val);
-extern int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
-				      unsigned char where, unsigned int *val);
-extern int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
-				      unsigned char where, unsigned char val);
-extern int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
-				      unsigned char where, unsigned short val);
-extern int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
-				       unsigned char where, unsigned int val);
-extern const char *pcibios_strerror (int error);
+#include <linux/pci.h>
+
+#warning This driver uses the old PCI interface, please fix it (see Documentation/pci.txt)
+
+extern inline int __pcibios_read_irq(unsigned char bus, unsigned char dev_fn, unsigned char *to)
+{
+	struct pci_dev *pdev = pci_find_slot(bus, dev_fn);
+	if (!pdev) {
+		*to = 0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	} else {
+		*to = pdev->irq;
+		return PCIBIOS_SUCCESSFUL;
+	}
+}
+
+extern inline int __pcibios_read_config_byte(unsigned char bus,
+	unsigned char dev_fn, unsigned char where, unsigned char *to)
+{
+	return pcibios_read_config_byte(bus, dev_fn, where, to);
+}
+
+#define pcibios_read_config_byte(b,d,w,p) \
+	(((w) == PCI_INTERRUPT_LINE) ? __pcibios_read_irq(b,d,p) : __pcibios_read_config_byte(b,d,w,p))
 
-#endif /* BIOS32_H */
+#endif
diff -u --recursive --new-file v2.1.92/linux/include/linux/devpts_fs.h linux/include/linux/devpts_fs.h
--- v2.1.92/linux/include/linux/devpts_fs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/devpts_fs.h	Sat Apr  4 09:45:19 1998
@@ -0,0 +1,69 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/include/linux/devpts_fs.h
+ *
+ *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * Prototypes for the pty driver <-> devpts filesystem interface.  Most
+ * of this is really just a hack so we can exclude it or build it as a
+ * module, and probably should go away eventually.
+ */
+
+#ifndef _LINUX_DEVPTS_FS_H
+#define _LINUX_DEVPTS_FS_H 1
+
+#include <linux/config.h>
+#include <linux/kdev_t.h>
+
+#ifdef CONFIG_DEVPTS_FS
+
+void devpts_pty_new(int, kdev_t);
+void devpts_pty_kill(int);
+
+#elif defined(CONFIG_DEVPTS_FS_MODULE)
+
+#ifdef BUILDING_PTY_C
+void (*devpts_upcall_new)(int,kdev_t) = NULL;
+void (*devpts_upcall_kill)(int)       = NULL;
+
+EXPORT_SYMBOL(devpts_upcall_new);
+EXPORT_SYMBOL(devpts_upcall_kill);
+#else
+extern void (*devpts_upcall_new)(int,kdev_t);
+extern void (*devpts_upcall_kill)(int);
+#endif
+
+#ifndef BUILDING_DEVPTS
+extern inline void
+devpts_pty_new(int line, kdev_t device)
+{
+	if ( devpts_upcall_new )
+		return devpts_upcall_new(line,device);
+}
+
+extern inline void
+devpts_pty_kill(int line)
+{
+	if ( devpts_upcall_kill )
+		return devpts_upcall_kill(line);
+}
+#endif
+
+#else  /* No /dev/pts filesystem at all */
+
+extern inline void
+devpts_pty_new(int line, kdev_t device) { }
+
+extern inline void
+devpts_pty_kill(int line) { }
+
+#endif
+
+#endif /* _LINUX_DEVPTS_FS_H */
diff -u --recursive --new-file v2.1.92/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- v2.1.92/linux/include/linux/ext2_fs.h	Fri Feb  6 15:32:54 1998
+++ linux/include/linux/ext2_fs.h	Thu Apr  2 13:39:51 1998
@@ -31,6 +31,7 @@
  * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
  */
 #define EXT2_PREALLOCATE
+#define EXT2_DEFAULT_PREALLOC_BLOCKS	8
 
 /*
  * The second extended file system version
@@ -190,8 +191,18 @@
 #define EXT2_APPEND_FL			0x00000020 /* writes to file may only append */
 #define EXT2_NODUMP_FL			0x00000040 /* do not dump file */
 #define EXT2_NOATIME_FL			0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL			0x00000100
+#define EXT2_COMPRBLK_FL		0x00000200 /* One or more compressed clusters */
+#define EXT2_NOCOMP_FL			0x00000400 /* Don't compress */
+#define EXT2_ECOMPR_FL			0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */	
+#define EXT2_BTREE_FL			0x00001000 /* btree format dir */
 #define EXT2_RESERVED_FL		0x80000000 /* reserved for ext2 lib */
-	
+
+#define EXT2_FL_USER_VISIBLE		0x00001FFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE		0x000000FF /* User modifiable flags */
+
 /*
  * ioctl commands
  */
@@ -255,6 +266,8 @@
 	} osd2;				/* OS dependent 2 */
 };
 
+#define i_size_high	i_dir_acl
+
 #if defined(__KERNEL__) || defined(__linux__)
 #define i_reserved1	osd1.linux1.l_i_reserved1
 #define i_frag		osd2.linux2.l_i_frag
@@ -367,9 +380,26 @@
 	__u8	s_uuid[16];		/* 128-bit uuid for volume */
 	char	s_volume_name[16]; 	/* volume name */
 	char	s_last_mounted[64]; 	/* directory where last mounted */
-	__u32	s_reserved[206];	/* Padding to the end of the block */
+	__u32	s_algorithm_usage_bitmap; /* For compression */
+	/*
+	 * Performance hints.  Directory preallocation should only
+	 * happen if the EXT2_COMPAT_PREALLOC flag is on.
+	 */
+	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
+	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
+	__u16	s_padding1;
+	__u32	s_reserved[204];	/* Padding to the end of the block */
 };
 
+#ifdef __KERNEL__
+#define EXT2_SB(sb)	(&((sb)->u.ext2_sb))
+#else
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block.  This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb)	(sb)
+#endif
+
 /*
  * Codes for operating systems
  */
@@ -394,11 +424,27 @@
  * Feature set definitions
  */
 
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_feature_compat & (mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_feature_incompat & (mask) )
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC	0x0001
+
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR	0x0004
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION	0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE		0x0002
 
 #define EXT2_FEATURE_COMPAT_SUPP	0
-#define EXT2_FEATURE_INCOMPAT_SUPP	0
-#define EXT2_FEATURE_RO_COMPAT_SUPP	EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+#define EXT2_FEATURE_INCOMPAT_SUPP	EXT2_FEATURE_INCOMPAT_FILETYPE
+#define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
 
 /*
  * Default values for user and/or group using reserved blocks
@@ -419,6 +465,35 @@
 };
 
 /*
+ * The new version of the directory entry.  Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+	__u32	inode;			/* Inode number */
+	__u16	rec_len;		/* Directory entry length */
+	__u8	name_len;		/* Name length */
+	__u8	file_type;
+	char	name[EXT2_NAME_LEN];	/* File name */
+};
+
+/*
+ * Ext2 directory file types.  Only the low 3 bits are used.  The
+ * other bits are reserved for now.
+ */
+#define EXT2_FT_UNKNOWN		0
+#define EXT2_FT_REG_FILE	1
+#define EXT2_FT_DIR		2
+#define EXT2_FT_CHRDEV		3
+#define EXT2_FT_BLKDEV 		4
+#define EXT2_FT_FIFO		5
+#define EXT2_FT_SOCK		6
+#define EXT2_FT_SYMLINK		7
+
+#define EXT2_FT_MAX		8
+
+/*
  * EXT2_DIR_PAD defines the directory entries boundaries
  *
  * NOTE: It must be a multiple of 4
@@ -451,13 +526,16 @@
 			      unsigned long);
 extern unsigned long ext2_count_free_blocks (struct super_block *);
 extern void ext2_check_blocks_bitmap (struct super_block *);
+extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+						    unsigned int block_group,
+						    struct buffer_head ** bh);
 
 /* bitmap.c */
 extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
 
 /* dir.c */
 extern int ext2_check_dir_entry (const char *, struct inode *,
-				 struct ext2_dir_entry *, struct buffer_head *,
+				 struct ext2_dir_entry_2 *, struct buffer_head *,
 				 unsigned long);
 
 /* file.c */
diff -u --recursive --new-file v2.1.92/linux/include/linux/ext2_fs_i.h linux/include/linux/ext2_fs_i.h
--- v2.1.92/linux/include/linux/ext2_fs_i.h	Sat May  4 00:06:18 1996
+++ linux/include/linux/ext2_fs_i.h	Thu Apr  2 13:39:51 1998
@@ -35,6 +35,7 @@
 	__u32	i_next_alloc_goal;
 	__u32	i_prealloc_block;
 	__u32	i_prealloc_count;
+	__u32	i_high_size;
 	int	i_new_inode:1;	/* Is a freshly allocated inode */
 };
 
diff -u --recursive --new-file v2.1.92/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.92/linux/include/linux/pci.h	Wed Apr  1 20:11:54 1998
+++ linux/include/linux/pci.h	Mon Apr  6 14:00:49 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: pci.h,v 1.51 1997/12/27 13:55:23 mj Exp $
+ *	$Id: pci.h,v 1.62 1998/03/15 13:50:05 ecd Exp $
  *
  *	PCI defines and function prototypes
  *	Copyright 1994, Drew Eckhardt
@@ -68,6 +68,10 @@
 #define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
 #define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
 #define PCI_HEADER_TYPE		0x0e	/* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL	0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
 #define PCI_BIST		0x0f	/* 8 bits */
 #define PCI_BIST_CODE_MASK	0x0f	/* Return result */
 #define PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
@@ -99,8 +103,8 @@
 
 /* Header type 0 (normal devices) */
 #define PCI_CARDBUS_CIS		0x28
-#define PCI_SUBSYSTEM_ID	0x2c
-#define PCI_SUBSYSTEM_VENDOR_ID	0x2e  
+#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
+#define PCI_SUBSYSTEM_ID	0x2e  
 #define PCI_ROM_ADDRESS		0x30	/* 32 bits */
 #define  PCI_ROM_ADDRESS_ENABLE	0x01	/* Write 1 to enable ROM,
 					   bits 31..11 are address,
@@ -149,6 +153,36 @@
 #define  PCI_BRIDGE_CTL_BUS_RESET 0x40	/* Secondary bus reset */
 #define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
 
+/* Header type 2 (CardBus bridges) -- detailed info welcome */
+#define PCI_CB_CARDBUS_BASE	0x10	/* CardBus Socket/ExCa base address */
+#define  PCI_CB_CARDBUS_BASE_TYPE_MASK 0xfff
+#define  PCI_CB_CARDBUS_BASE_MASK ~0xfff
+#define PCI_CB_CAPABILITIES	0x14	/* Offset of list of capabilities in cfg space */
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
+#define PCI_CB_BUS_NUMBER	0x18	/* PCI bus number */
+#define PCI_CB_CARDBUS_NUMBER	0x19	/* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
+#define PCI_CB_CARDBUS_LATENCY	0x1b	/* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0	0x1c
+#define PCI_CB_MEMORY_LIMIT_0	0x20
+#define PCI_CB_MEMORY_BASE_1	0x24
+#define PCI_CB_MEMORY_LIMIT_1	0x28
+#define PCI_CB_IO_BASE_0	0x2c
+#define PCI_CB_IO_BASE_0_HI	0x2e
+#define PCI_CB_IO_LIMIT_0	0x30
+#define PCI_CB_IO_LIMIT_0_HI	0x32
+#define PCI_CB_IO_BASE_1	0x34
+#define PCI_CB_IO_BASE_1_HI	0x36
+#define PCI_CB_IO_LIMIT_1	0x38
+#define PCI_CB_IO_LIMIT_1_HI	0x3a
+/* 0x3c-0x3d are same as for htype 0 */
+/* 0x3e-0x3f are same as for htype 1 */
+#define PCI_CB_SUBSYSTEM_ID	0x40
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
 /* Device classes and subclasses */
 
 #define PCI_CLASS_NOT_DEFINED		0x0000
@@ -236,7 +270,8 @@
 
 /*
  * Vendor and card ID's: sort these numerically according to vendor
- * (and according to card ID within vendor)
+ * (and according to card ID within vendor). Send all updates to
+ * <linux-pcisupport@cck.uni-kl.de>.
  */
 #define PCI_VENDOR_ID_COMPAQ		0x0e11
 #define PCI_DEVICE_ID_COMPAQ_1280	0x3033
@@ -518,7 +553,9 @@
 #define PCI_VENDOR_ID_SUN		0x108e
 #define PCI_DEVICE_ID_SUN_EBUS		0x1000
 #define PCI_DEVICE_ID_SUN_HAPPYMEAL	0x1001
+#define PCI_DEVICE_ID_SUN_SIMBA		0x5000
 #define PCI_DEVICE_ID_SUN_PBM		0x8000
+#define PCI_DEVICE_ID_SUN_SABRE		0xa000
 
 #define PCI_VENDOR_ID_CMD		0x1095
 #define PCI_DEVICE_ID_CMD_640		0x0640
@@ -601,6 +638,8 @@
 #define PCI_VENDOR_ID_CERN		0x10dc
 #define PCI_DEVICE_ID_CERN_SPSB_PMC	0x0001
 #define PCI_DEVICE_ID_CERN_SPSB_PCI	0x0002
+#define PCI_DEVICE_ID_CERN_HIPPI_DST	0x0021
+#define PCI_DEVICE_ID_CERN_HIPPI_SRC	0x0022
 
 #define PCI_VENDOR_ID_NVIDIA		0x10de
 
@@ -783,6 +822,9 @@
 #define PCI_DEVICE_ID_CYCLOM_Z_Lo	0x0200
 #define PCI_DEVICE_ID_CYCLOM_Z_Hi	0x0201
 
+#define PCI_VENDOR_ID_ESSENTIAL		0x120f
+#define PCI_DEVICE_ID_ROADRUNNER	0x0001
+
 #define PCI_VENDOR_ID_O2		0x1217
 #define PCI_DEVICE_ID_O2_6832		0x6832
 
@@ -933,10 +975,47 @@
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 
-/* create an index into the pci_dev base_address[] array from an offset */
-#define PCI_BASE_INDEX(o) (((o)-PCI_BASE_ADDRESS_0)>>2)
-
 #ifdef __KERNEL__
+
+/*
+ * Error values that may be returned by the PCI bios.  Use
+ * pcibios_strerror() to convert to a printable string.
+ */
+#define PCIBIOS_SUCCESSFUL		0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED	0x81
+#define PCIBIOS_BAD_VENDOR_ID		0x83
+#define PCIBIOS_DEVICE_NOT_FOUND	0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER	0x87
+#define PCIBIOS_SET_FAILED		0x88
+#define PCIBIOS_BUFFER_TOO_SMALL	0x89
+
+/* Direct configuration space access */
+
+int pcibios_present (void);
+void pcibios_init(void);
+void pcibios_fixup(void);
+char *pcibios_setup (char *str);
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+			      unsigned char where, unsigned char *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+			      unsigned char where, unsigned short *val);
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned int *val);
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned char val);
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned short val);
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+				unsigned char where, unsigned int val);
+const char *pcibios_strerror (int error);
+
+/* Don't use these in new code, use pci_find_... instead */
+
+int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn);
+int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
+			 unsigned short index, unsigned char *bus,
+			 unsigned char *dev_fn);
+
 /*
  * There is one pci_dev structure for each slot-number/function-number
  * combination:
@@ -952,6 +1031,7 @@
 	unsigned short	vendor;
 	unsigned short	device;
 	unsigned int	class;		/* 3 bytes: (base,sub,prog-if) */
+	unsigned int	hdr_type;	/* PCI header type */
 	unsigned int	master : 1;	/* set if device is master capable */
 	/*
 	 * In theory, the irq level can be read from configuration
@@ -990,15 +1070,25 @@
 
 extern struct pci_bus	pci_root;	/* root bus */
 extern struct pci_dev	*pci_devices;	/* list of all devices */
-extern struct pci_dev   *pci_find_dev (unsigned char bus, unsigned char devfn);
-
-extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end);
-
-extern unsigned int pci_scan_bus (struct pci_bus *bus, unsigned long *mem_startp);
 
-extern int get_pci_list (char *buf);
+void pci_init(void);
+void pci_setup(char *str, int *ints);
+void pci_quirks_init(void);
+unsigned int pci_scan_bus(struct pci_bus *bus);
+
+struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
+struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from);
+struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+
+#define pci_present pcibios_present
+#define pci_read_config_byte(dev, where, val) pcibios_read_config_byte(dev->bus->number, dev->devfn, where, val)
+#define pci_read_config_word(dev, where, val) pcibios_read_config_word(dev->bus->number, dev->devfn, where, val)
+#define pci_read_config_dword(dev, where, val) pcibios_read_config_dword(dev->bus->number, dev->devfn, where, val)
+#define pci_write_config_byte(dev, where, val) pcibios_write_config_byte(dev->bus->number, dev->devfn, where, val)
+#define pci_write_config_word(dev, where, val) pcibios_write_config_word(dev->bus->number, dev->devfn, where, val)
+#define pci_write_config_dword(dev, where, val) pcibios_write_config_dword(dev->bus->number, dev->devfn, where, val)
 
-extern void pci_quirks_init (void);
+int get_pci_list (char *buf);
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -u --recursive --new-file v2.1.92/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.92/linux/include/linux/proc_fs.h	Wed Apr  1 20:11:54 1998
+++ linux/include/linux/proc_fs.h	Mon Apr  6 11:50:36 1998
@@ -134,6 +134,7 @@
 	PROC_NET_DN_L1,
 	PROC_NET_DN_L2,
 	PROC_NET_DN_SKT,
+	PROC_NET_NETSTAT,
 	PROC_NET_LAST
 };
 
diff -u --recursive --new-file v2.1.92/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.1.92/linux/include/linux/skbuff.h	Wed Apr  1 20:11:54 1998
+++ linux/include/linux/skbuff.h	Mon Apr  6 11:50:36 1998
@@ -75,13 +75,7 @@
 
 	struct  dst_entry *dst;
 
-#if (defined(__alpha__) || defined(__sparc_v9__)) && (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE))
-	char		cb[48];	   /* sorry. 64bit pointers have a price */
-#elif (defined(__alpha__) || defined(__sparc_v9__))
-	char		cb[40];
-#else
-	char    	cb[36];
-#endif
+	char		cb[48];	 
 
 	unsigned int 	len;			/* Length of actual data			*/
 	unsigned int	csum;			/* Checksum 					*/
diff -u --recursive --new-file v2.1.92/linux/include/net/br.h linux/include/net/br.h
--- v2.1.92/linux/include/net/br.h	Thu Mar 27 14:40:11 1997
+++ linux/include/net/br.h	Fri Apr  3 17:48:11 1998
@@ -27,7 +27,7 @@
 /*
  * We time out our entries in the FDB after this many seconds.
  */
-#define FDB_TIMEOUT	300
+#define FDB_TIMEOUT	20 /* JRP: 20s as NSC bridge code, was 300 for Linux */
 
 /*
  * the following defines are the initial values used when the 
@@ -40,6 +40,10 @@
 #define BRIDGE_FORWARD_DELAY	15
 #define HOLD_TIME		1
 
+/* broacast/multicast storm limitation. This per source. */
+#define MAX_MCAST_PER_PERIOD    4
+#define MCAST_HOLD_TIME		10	/* in jiffies unit (10ms increment) */
+
 #define Default_path_cost 10
 
 /*
@@ -71,13 +75,25 @@
 #define BRIDGE_ID_ULA	bi.p_u.ula
 #define BRIDGE_ID	bi.id
 
+/* JRP: on the network the flags field is between "type" and "root_id"
+ * this is unfortunated! To make the code portable to a RISC machine
+ * the pdus are now massaged a little bit for processing
+ */ 
+#define TOPOLOGY_CHANGE		0x01
+#define TOPOLOGY_CHANGE_ACK	0x80
+#define BRIDGE_BPDU_8021_CONFIG_SIZE            35	/* real size */
+#define BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET	 4
+#define BRIDGE_BPDU_8021_PROTOCOL_ID 0
+#define BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID 0
+#define BRIDGE_LLC1_HS 3
+#define BRIDGE_LLC1_DSAP 0x42
+#define BRIDGE_LLC1_SSAP 0x42
+#define BRIDGE_LLC1_CTRL 0x03
+
 typedef struct {
 	unsigned short	protocol_id;	
 	unsigned char	protocol_version_id;
 	unsigned char   type;
-	unsigned char   flags;
-#define TOPOLOGY_CHANGE		0x01
-#define TOPOLOGY_CHANGE_ACK	0x80
 	bridge_id_t      root_id;		  /* (4.5.1.1)	 */
 	unsigned int     root_path_cost;	  /* (4.5.1.2)	 */
 	bridge_id_t      bridge_id;		  /* (4.5.1.3)	 */
@@ -86,8 +102,23 @@
 	unsigned short   max_age;		  /* (4.5.1.6)	 */
 	unsigned short   hello_time;		  /* (4.5.1.7)	 */
 	unsigned short   forward_delay;		  /* (4.5.1.8)	 */
+	unsigned char   top_change_ack;
+	unsigned char   top_change;
 } Config_bpdu;
 
+#ifdef __LITTLE_ENDIAN
+#define config_bpdu_hton(config_bpdu) \
+        (config_bpdu)->root_path_cost = htonl((config_bpdu)->root_path_cost); \
+        (config_bpdu)->port_id = htons((config_bpdu)->port_id); \
+        (config_bpdu)->message_age = htons((config_bpdu)->message_age); \
+        (config_bpdu)->max_age = htons((config_bpdu)->max_age); \
+        (config_bpdu)->hello_time = htons((config_bpdu)->hello_time); \
+        (config_bpdu)->forward_delay = htons((config_bpdu)->forward_delay);
+#else
+#define config_bpdu_hton(config_bpdu)
+#endif
+#define config_bpdu_ntoh config_bpdu_hton
+
 
 /** Topology Change Notification BPDU Parameters (4.5.2) **/
 
@@ -112,12 +143,10 @@
 	unsigned short   bridge_max_age;	  /* (4.5.3.8)	 */
 	unsigned short   bridge_hello_time;	  /* (4.5.3.9)	 */
 	unsigned short   bridge_forward_delay;	  /* (4.5.3.10)	 */
-	unsigned int     topology_change_detected; /* (4.5.3.11) */
-	unsigned int     topology_change;	  /* (4.5.3.12)	 */
+	unsigned int     top_change_detected;	  /* (4.5.3.11) */
+	unsigned int     top_change;		  /* (4.5.3.12)	 */
 	unsigned short   topology_change_time;	  /* (4.5.3.13)	 */
 	unsigned short   hold_time;		  /* (4.5.3.14)	 */
-	unsigned int     top_change;
-	unsigned int     top_change_detected;
 } Bridge_data;
 
 /** Port Parameters (4.5.5) **/
@@ -149,8 +178,11 @@
 	unsigned char pad[2];
 	unsigned short port;
 	unsigned int timer;
-	unsigned int flags;
+	unsigned short flags;
 #define FDB_ENT_VALID	0x01
+	unsigned short mcast_count;
+	unsigned int   mcast_timer;		/* oldest xxxxxcast */
+	
 /* AVL tree of all addresses, sorted by address */
 	short fdb_avl_height;
 	struct fdb *fdb_avl_left;
@@ -159,6 +191,19 @@
 	struct fdb *fdb_next;
 };
 
+/* data returned on BRCMD_DISPLAY_FDB */
+struct fdb_info {
+	unsigned char ula[6];
+	unsigned char port;
+        unsigned char flags;
+        unsigned int timer;
+};
+struct fdb_info_hdr {
+	int	copied;			/* nb of entries copied to user */
+	int	not_copied;		/* when user buffer is too small */
+	int	cmd_time;
+};	
+
 #define IS_BRIDGED	0x2e
 
 
@@ -169,6 +214,34 @@
 #define BR_ACCEPT 1
 #define BR_REJECT 0
 
+/* JRP: extra statistics for debug */
+typedef struct {
+	/* br_receive_frame counters */
+	int port_disable_up_stack;
+	int rcv_bpdu;
+	int notForwarding;
+	int forwarding_up_stack;
+	int unknown_state;
+
+	/* br_tx_frame counters */
+	int port_disable;
+	int port_not_disable;
+
+	/* br_forward counters */
+	int local_multicast;
+	int forwarded_multicast;	/* up stack as well */
+	int flood_unicast;
+	int aged_flood_unicast;
+	int forwarded_unicast;
+	int forwarded_unicast_up_stack;
+	int forwarded_ip_up_stack;
+	int forwarded_ip_up_stack_lie;	/* received on alternate device */
+	int arp_for_local_mac;
+	int drop_same_port;
+	int drop_same_port_aged;
+	int drop_multicast;
+} br_stats_counter;
+
 struct br_stat {
 	unsigned int flags;
 	Bridge_data bridge_data;
@@ -178,6 +251,7 @@
 	unsigned short protocols[BR_MAX_PROTOCOLS];
 	unsigned short prot_id[BR_MAX_PROT_STATS];	/* Protocol encountered */
 	unsigned int prot_counter[BR_MAX_PROT_STATS];	/* How many packets ? */
+	br_stats_counter packet_cnts;
 };
 
 /* defined flags for br_stat.flags */
@@ -215,9 +289,10 @@
 int br_tx_frame(struct sk_buff *skb);
 int br_ioctl(unsigned int cmd, void *arg);
 int br_protocol_ok(unsigned short protocol);
+void requeue_fdb(struct fdb *node, int new_port);
 
 struct fdb *br_avl_find_addr(unsigned char addr[6]);
-int br_avl_insert (struct fdb * new_node);
+struct fdb *br_avl_insert (struct fdb * new_node);
 
 /* externs */
 
diff -u --recursive --new-file v2.1.92/linux/include/net/ip.h linux/include/net/ip.h
--- v2.1.92/linux/include/net/ip.h	Thu Mar 26 15:57:06 1998
+++ linux/include/net/ip.h	Mon Apr  6 11:52:59 1998
@@ -128,6 +128,7 @@
 
 extern struct ipv4_config ipv4_config;
 extern struct ip_mib	ip_statistics;
+extern struct linux_mib	net_statistics;
 
 extern int sysctl_local_port_range[2];
 
diff -u --recursive --new-file v2.1.92/linux/include/net/snmp.h linux/include/net/snmp.h
--- v2.1.92/linux/include/net/snmp.h	Sat Nov 29 10:33:21 1997
+++ linux/include/net/snmp.h	Fri Apr  3 17:48:11 1998
@@ -124,5 +124,12 @@
  	unsigned long	UdpInErrors;
  	unsigned long	UdpOutDatagrams;
 };
+
+struct linux_mib 
+{
+	unsigned long	SyncookiesSent;
+	unsigned long	SyncookiesRecv;
+	unsigned long	SyncookiesFailed;
+};
  	
 #endif
diff -u --recursive --new-file v2.1.92/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.92/linux/include/net/sock.h	Wed Apr  1 20:11:54 1998
+++ linux/include/net/sock.h	Mon Apr  6 11:51:18 1998
@@ -274,7 +274,8 @@
 
 	struct open_request	*syn_wait_queue;
 	struct open_request	**syn_wait_last;
-	int syn_backlog;
+
+	int syn_backlog;	/* Backlog of received SYNs */
 };
 
  	
diff -u --recursive --new-file v2.1.92/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.1.92/linux/include/net/tcp.h	Wed Apr  1 20:11:54 1998
+++ linux/include/net/tcp.h	Mon Apr  6 11:53:01 1998
@@ -941,6 +941,9 @@
 	(*window_clamp) = min(65535<<(*rcv_wscale),*window_clamp);
 }
 
+/* Do new listen semantics */
+#define TCP_NEW_LISTEN
+
 extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req, struct open_request *prev)
 {
 	if(!req->dl_next)
@@ -959,20 +962,6 @@
 {
 	tp->syn_wait_queue = NULL;
 	tp->syn_wait_last = &tp->syn_wait_queue;
-}
-
-extern __inline__ struct open_request *tcp_synq_unlink_tail(struct tcp_opt *tp)
-{
-	struct open_request *head = tp->syn_wait_queue;
-#if 0
-	/* Should be a net-ratelimit'd thing, not all the time. */
-	printk(KERN_DEBUG "synq tail drop with expire=%ld\n", 
-	       head->expires-jiffies);
-#endif
-	if (head->dl_next == NULL)
-		tp->syn_wait_last = &tp->syn_wait_queue;
-	tp->syn_wait_queue = head->dl_next;
-	return head;
 }
 
 extern void __tcp_inc_slow_timer(struct tcp_sl_timer *slt);
diff -u --recursive --new-file v2.1.92/linux/init/main.c linux/init/main.c
--- v2.1.92/linux/init/main.c	Wed Apr  1 20:11:54 1998
+++ linux/init/main.c	Mon Apr  6 13:47:08 1998
@@ -40,6 +40,9 @@
 
 #include <stdarg.h>
 
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
 
 /*
  * Versions of gcc older than that listed below may actually compile
@@ -61,23 +64,25 @@
 extern int kswapd(void *);
 extern void kswapd_setup(void);
 
+extern void dquot_init(void);
 extern void init_IRQ(void);
 extern void init_modules(void);
 extern long console_init(long, long);
 extern void sock_init(void);
 extern void uidcache_init(void);
-extern unsigned long pci_init(unsigned long, unsigned long);
 extern long mca_init(long, long);
 extern long sbus_init(long, long);
 extern long powermac_init(unsigned long, unsigned long);
 extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
-extern void dquot_init(void);
 
 extern void smp_setup(char *str, int *ints);
+#ifdef __i386__
 extern void ioapic_pirq_setup(char *str, int *ints);
+#endif
 extern void no_scroll(char *str, int *ints);
+extern void kbd_reset_setup(char *str, int *ints);
 extern void panic_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
 extern void msmouse_setup(char *str, int *ints);
@@ -473,8 +478,10 @@
 #ifdef __SMP__
 	{ "nosmp", smp_setup },
 	{ "maxcpus=", smp_setup },
+#ifdef __i386__
 	{ "pirq=", ioapic_pirq_setup },
 #endif
+#endif
 #ifdef CONFIG_BLK_DEV_RAM
 	{ "ramdisk_start=", ramdisk_start_setup },
 	{ "load_ramdisk=", load_ramdisk },
@@ -492,6 +499,7 @@
 	{ "console=", console_setup },
 #ifdef CONFIG_VT
 	{ "no-scroll", no_scroll },
+	{ "kbd-reset", kbd_reset_setup },
 #endif
 #ifdef CONFIG_BUGi386
 	{ "no-hlt", no_halt },
@@ -737,6 +745,9 @@
 #ifdef CONFIG_IP_PNP
 	{ "ip=", ip_auto_config_setup },
 #endif
+#ifdef CONFIG_PCI
+	{ "pci=", pci_setup },
+#endif
 #ifdef CONFIG_PARIDE_PD
 	{ "pd.", pd_setup },
 #endif
@@ -1015,24 +1026,15 @@
 		memset(prof_buffer, 0, prof_len * sizeof(unsigned int));
 	}
 #endif
-#ifdef CONFIG_SBUS
-	memory_start = sbus_init(memory_start,memory_end);
-#endif
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
-	memory_start = powermac_init(memory_start, memory_end);
-#endif
-#if defined(CONFIG_PCI) && defined(CONFIG_PCI_CONSOLE)
-	memory_start = pci_init(memory_start,memory_end);
-#endif
+
+/*
+ * HACK ALERT! This is early. We're enabling the console before
+ * we've done PCI setups etc, and console_init() must be aware of
+ * this. But we do want output early, in case something goes wrong.
+ */
 #if HACK
 	memory_start = console_init(memory_start,memory_end);
 #endif
-#if defined(CONFIG_PCI) && !defined(CONFIG_PCI_CONSOLE)
-	memory_start = pci_init(memory_start,memory_end);
-#endif
-#ifdef CONFIG_MCA
-	memory_start = mca_init(memory_start,memory_end);
-#endif
 	memory_start = kmem_cache_init(memory_start, memory_end);
 	sti();
 	calibrate_delay();
@@ -1070,6 +1072,24 @@
 #ifdef CONFIG_SYSCTL
 	sysctl_init();
 #endif
+
+	/*
+	 * Ok, at this point all CPU's should be initialized, so
+	 * we can start looking into devices..
+	 */
+#ifdef CONFIG_PCI
+	pci_init();
+#endif
+#ifdef CONFIG_SBUS
+	sbus_init();
+#endif
+#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+	powermac_init();
+#endif
+#ifdef CONFIG_MCA
+	mca_init();
+#endif
+
 	/* 
 	 *	We count on the initial thread going ok 
 	 *	Like idlers init is an unlocked kernel thread, which will
diff -u --recursive --new-file v2.1.92/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.92/linux/kernel/ksyms.c	Wed Apr  1 20:11:54 1998
+++ linux/kernel/ksyms.c	Thu Apr  2 09:12:26 1998
@@ -54,10 +54,6 @@
 
 extern unsigned char aux_device_present, kbd_read_mask;
 
-#ifdef CONFIG_PCI
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#endif
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
 #endif
@@ -100,19 +96,6 @@
 #endif
 EXPORT_SYMBOL(get_options);
 
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pcibios_present);
-EXPORT_SYMBOL(pcibios_find_class);
-EXPORT_SYMBOL(pcibios_find_device);
-EXPORT_SYMBOL(pcibios_read_config_byte);
-EXPORT_SYMBOL(pcibios_read_config_word);
-EXPORT_SYMBOL(pcibios_read_config_dword);
-EXPORT_SYMBOL(pcibios_write_config_byte);
-EXPORT_SYMBOL(pcibios_write_config_word);
-EXPORT_SYMBOL(pcibios_write_config_dword);
-EXPORT_SYMBOL(pcibios_strerror);
-#endif
-
 /* process memory management */
 EXPORT_SYMBOL(do_mmap);
 EXPORT_SYMBOL(do_munmap);
@@ -265,6 +248,7 @@
 EXPORT_SYMBOL(unregister_binfmt);
 EXPORT_SYMBOL(search_binary_handler);
 EXPORT_SYMBOL(prepare_binprm);
+EXPORT_SYMBOL(compute_creds);
 EXPORT_SYMBOL(remove_arg_zero);
 
 /* execution environment registration */
@@ -354,6 +338,7 @@
 EXPORT_SYMBOL(_ctype);
 EXPORT_SYMBOL(secure_tcp_sequence_number);
 EXPORT_SYMBOL(get_random_bytes);
+EXPORT_SYMBOL(securebits);
 
 /* Program loader interfaces */
 EXPORT_SYMBOL(setup_arg_pages);
diff -u --recursive --new-file v2.1.92/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.92/linux/mm/page_alloc.c	Wed Apr  1 20:11:55 1998
+++ linux/mm/page_alloc.c	Sat Apr  4 09:26:23 1998
@@ -292,8 +292,12 @@
 	spin_lock_irqsave(&page_alloc_lock, flags);
 	RMQUEUE(order, maxorder, (gfp_mask & GFP_DMA));
 	spin_unlock_irqrestore(&page_alloc_lock, flags);
-	if ((gfp_mask & __GFP_WAIT) && try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX))
-		goto repeat;
+	if (gfp_mask & __GFP_WAIT) {
+		int freed = try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX);
+		gfp_mask &= ~__GFP_WAIT;	/* go through this only once */
+		if (freed)
+			goto repeat;
+	}
 nopage:
 	return 0;
 }
diff -u --recursive --new-file v2.1.92/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.92/linux/net/core/dev.c	Tue Mar 17 22:18:16 1998
+++ linux/net/core/dev.c	Fri Apr  3 17:48:11 1998
@@ -1342,10 +1342,7 @@
 	ret = 0;
 	if ((old_flags^flags)&IFF_UP)	/* Bit is different  ? */
 	{
-		if(old_flags&IFF_UP)		/* Gone down */
-			ret=dev_close(dev); 		
-		else				/* Come up */
-			ret=dev_open(dev);
+		ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
 
 		if (ret == 0) 
 			dev_mc_upload(dev);
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.92/linux/net/ipv4/af_inet.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/af_inet.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		AF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.68 1998/03/27 07:02:42 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.69 1998/04/03 09:49:42 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -117,10 +117,13 @@
 
 #define min(a,b)	((a)<(b)?(a):(b))
 
+struct linux_mib net_statistics;
+
 extern int sysctl_core_destroy_delay;
 
 extern int raw_get_info(char *, char **, off_t, int, int);
 extern int snmp_get_info(char *, char **, off_t, int, int);
+extern int netstat_get_info(char *, char **, off_t, int, int);
 extern int afinet_get_info(char *, char **, off_t, int, int);
 extern int tcp_get_info(char *, char **, off_t, int, int);
 extern int udp_get_info(char *, char **, off_t, int, int);
@@ -1016,6 +1019,12 @@
 	0, &proc_net_inode_operations,
 	raw_get_info
 };
+static struct proc_dir_entry proc_net_netstat = {
+	PROC_NET_NETSTAT, 7, "netstat",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	netstat_get_info
+};
 static struct proc_dir_entry proc_net_snmp = {
 	PROC_NET_SNMP, 4, "snmp",
 	S_IFREG | S_IRUGO, 1, 0, 0,
@@ -1141,6 +1150,7 @@
 #endif		/* RARP */
 	proc_net_register(&proc_net_raw);
 	proc_net_register(&proc_net_snmp);
+	proc_net_register(&proc_net_netstat);
 	proc_net_register(&proc_net_sockstat);
 	proc_net_register(&proc_net_tcp);
 	proc_net_register(&proc_net_udp);
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- v2.1.92/linux/net/ipv4/ip_input.c	Tue Mar 17 22:18:16 1998
+++ linux/net/ipv4/ip_input.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) module.
  *
- * Version:	$Id: ip_input.c,v 1.27 1998/03/08 05:56:24 davem Exp $
+ * Version:	$Id: ip_input.c,v 1.29 1998/04/03 10:52:06 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v2.1.92/linux/net/ipv4/proc.c	Thu Mar 26 15:57:13 1998
+++ linux/net/ipv4/proc.c	Fri Apr  3 17:48:11 1998
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.27 1998/03/18 07:51:59 davem Exp $
+ * Version:	$Id: proc.c,v 1.28 1998/04/03 09:49:45 freitag Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -25,6 +25,7 @@
  *		Alan Cox	:	Allow inode to be NULL (kernel socket)
  *	Andi Kleen		:	Add support for open_requests and 
  *					split functions for more readibility.
+ *	Andi Kleen		:	Add support for /proc/net/netstat
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -326,6 +327,34 @@
 	  		tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss);
 */
 	
+	if (offset >= len)
+	{
+		*start = buffer;
+		return 0;
+	}
+	*start = buffer + offset;
+	len -= offset;
+	if (len > length)
+		len = length;
+	return len;
+}
+
+/* 
+ *	Output /proc/net/netstat
+ */
+ 
+int netstat_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+	extern struct linux_mib net_statistics;
+	int len;
+
+	len = sprintf(buffer,
+		      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed\n"
+		      "TcpExt: %lu %lu %lu\n",
+		      net_statistics.SyncookiesSent,
+		      net_statistics.SyncookiesRecv,
+		      net_statistics.SyncookiesFailed);
+
 	if (offset >= len)
 	{
 		*start = buffer;
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c
--- v2.1.92/linux/net/ipv4/syncookies.c	Tue Mar 17 22:18:16 1998
+++ linux/net/ipv4/syncookies.c	Fri Apr  3 17:48:11 1998
@@ -9,11 +9,9 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  * 
- *  $Id: syncookies.c,v 1.4 1998/03/08 05:56:34 davem Exp $
+ *  $Id: syncookies.c,v 1.5 1998/04/03 09:49:46 freitag Exp $
  *
  *  Missing: IPv6 support. 
- *           Some counter so that the Administrator can see when the machine
- *           is under a syn flood attack.
  */
 
 #include <linux/config.h>
@@ -88,6 +86,8 @@
 found:
 	*mssp = w[-1]; 
 
+	net_statistics.SyncookiesSent++;
+
 	isn |= i; 
 	return isn; 
 }
@@ -110,8 +110,9 @@
 	__u32 seq; 
 
   	if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT
-	    && tcp_lastsynq_overflow) 
+	    && tcp_lastsynq_overflow) {
 		return 0; 
+	}
 
 	mssind = cookie & 7;
 	cookie &= ~7;
@@ -157,8 +158,12 @@
 		return sk; 
 
 	mss = cookie_check(skb, cookie);
-	if (mss == 0) 
+	if (mss == 0) {
+	 	net_statistics.SyncookiesFailed++;
 		return sk;
+	}
+
+	net_statistics.SyncookiesRecv++;
 
 	req = tcp_openreq_alloc();
 	if (req == NULL)
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- v2.1.92/linux/net/ipv4/sysctl_net_ipv4.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/sysctl_net_ipv4.c	Fri Apr  3 17:48:11 1998
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.31 1998/03/30 08:41:41 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.32 1998/04/03 09:49:47 freitag Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -154,8 +154,6 @@
 	{NET_TCP_STDURG, "tcp_stdurg", &sysctl_tcp_stdurg,
 	 sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_TCP_RFC1337, "tcp_rfc1337", &sysctl_tcp_rfc1337,
-	 sizeof(int), 0644, NULL, &proc_dointvec},
-	{NET_TCP_SYN_TAILDROP, "tcp_syn_taildrop", &sysctl_tcp_syn_taildrop,
 	 sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_TCP_MAX_SYN_BACKLOG, "tcp_max_syn_backlog", &sysctl_max_syn_backlog,
 	 sizeof(int), 0644, NULL, &proc_dointvec},
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.92/linux/net/ipv4/tcp.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/tcp.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.108 1998/03/29 08:43:51 davem Exp $
+ * Version:	$Id: tcp.c,v 1.110 1998/04/03 09:49:51 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1160,6 +1160,11 @@
 			break;
 		}
 
+		if (sk->shutdown & RCV_SHUTDOWN) {
+			sk->done = 1;
+			break;
+		}
+
 		if (sk->state == TCP_CLOSE) {
 			if (!sk->done) {
 				sk->done = 1;
@@ -1169,11 +1174,6 @@
 			break;
 		}
 
-		if (sk->shutdown & RCV_SHUTDOWN) {
-			sk->done = 1;
-			break;
-		}
-
 		if (nonblock) {
 			copied = -EAGAIN;
 			break;
@@ -1529,7 +1529,7 @@
 	tcp_synq_unlink(tp, req, prev);
 	newsk = req->sk;
 	tcp_openreq_free(req);
-	sk->ack_backlog--;  /* XXX */
+	sk->ack_backlog--; 
 
 	/* FIXME: need to check here if newsk has already
 	 * an soft_err or err set.
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.92/linux/net/ipv4/tcp_input.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/tcp_input.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.103 1998/03/30 08:41:12 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.104 1998/04/01 07:41:24 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1906,7 +1906,10 @@
 			tp->rcv_nxt = TCP_SKB_CB(skb)->seq+1;
 			tp->rcv_wup = TCP_SKB_CB(skb)->seq+1;
 
-			tp->snd_wnd = htons(th->window) << tp->snd_wscale;
+			/* RFC1323: The window in SYN & SYN/ACK segments is
+			 * never scaled.
+			 */
+			tp->snd_wnd = htons(th->window);
 			tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
 			tp->snd_wl2 = TCP_SKB_CB(skb)->ack_seq;
 			tp->fin_seq = TCP_SKB_CB(skb)->seq;
@@ -1918,6 +1921,7 @@
                 		tp->snd_wscale = tp->rcv_wscale = 0;
                 		tp->window_clamp = min(tp->window_clamp,65535);
         		}
+
 			if (tp->tstamp_ok) {
 				tp->tcp_header_len =
 					sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
@@ -1980,6 +1984,9 @@
 				tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
 				tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
 
+				/* RFC1323: The window in SYN & SYN/ACK segments is
+				 * never scaled.
+				 */
 				tp->snd_wnd = htons(th->window);
 				tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
 				
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.92/linux/net/ipv4/tcp_ipv4.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/tcp_ipv4.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.127 1998/03/30 08:41:25 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.131 1998/04/03 10:52:04 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -39,11 +39,12 @@
  *					most of it into the af independent code.
  *					Added tail drop and some other bugfixes.
  *					Added new listen sematics (ifdefed by
- *					NEW_LISTEN for now)
+ *					TCP_NEW_LISTEN for now)
  *		Mike McLagan	:	Routing by source
  *	Juan Jose Ciarlante:		ip_dynaddr bits
  *		Andi Kleen:		various fixes.
  *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.
+ *	Andi Kleen		:	Fix TCP_NEW_LISTEN and make it the default.
  */
 
 #include <linux/config.h>
@@ -812,6 +813,11 @@
 		if (req->sk) {	/* not yet accept()ed */
 			sk = req->sk; /* report error in accept */
 		} else {
+#ifdef TCP_NEW_LISTEN
+			tp->syn_backlog--;
+#else
+			sk->ack_backlog--;
+#endif
 			tcp_synq_unlink(tp, req, prev);
 			req->class->destructor(req);
 			tcp_openreq_free(req);
@@ -1017,7 +1023,6 @@
 }
 
 int sysctl_max_syn_backlog = 1024; 
-int sysctl_tcp_syn_taildrop = 1;
 
 struct or_calltable or_ipv4 = {
 	tcp_v4_send_synack,
@@ -1025,7 +1030,7 @@
 	tcp_v4_send_reset
 };
 
-#ifdef NEW_LISTEN
+#ifdef TCP_NEW_LISTEN
 #define BACKLOG(sk) ((sk)->tp_pinfo.af_tcp.syn_backlog) /* lvalue! */
 #define BACKLOGMAX(sk) sysctl_max_syn_backlog
 #else
@@ -1057,27 +1062,19 @@
 		if (sysctl_tcp_syncookies) {
 			syn_flood_warning(skb);
 			want_cookie = 1; 
-		} else 
+		} else
 #endif
-		if (sysctl_tcp_syn_taildrop) {
-			struct open_request *req;
-
-			req = tcp_synq_unlink_tail(&sk->tp_pinfo.af_tcp);
-			tcp_openreq_free(req);
-			tcp_statistics.TcpAttemptFails++;
-		} else {
-			goto error;
-		}
+		goto drop;
 	} else { 
 		if (isn == 0)
 			isn = tcp_v4_init_sequence(sk, skb);
-		BACKLOG(sk)++;
 	}
 
+	BACKLOG(sk)++;
+
 	req = tcp_openreq_alloc();
 	if (req == NULL) {
-		if (!want_cookie) BACKLOG(sk)--;
-		goto error;
+		goto dropbacklog;
 	}
 
 	req->rcv_wnd = 0;		/* So that tcp_send_synack() knows! */
@@ -1137,7 +1134,10 @@
 	tcp_statistics.TcpAttemptFails++;
 	return -ENOTCONN; /* send reset */
 
-error:
+dropbacklog:
+	if (!want_cookie) 
+		BACKLOG(sk)--;
+drop:
 	tcp_statistics.TcpAttemptFails++;
 	return 0;
 }
@@ -1184,7 +1184,12 @@
 		newtp->ato = 0;
 		newtp->snd_wl1 = req->rcv_isn;
 		newtp->snd_wl2 = req->snt_isn;
+
+		/* RFC1323: The window in SYN & SYN/ACK segments
+		 * is never scaled.
+		 */
 		newtp->snd_wnd = ntohs(skb->h.th->window);
+
 		newtp->max_window = newtp->snd_wnd;
 		newtp->pending = 0;
 		newtp->retransmits = 0;
@@ -1270,6 +1275,10 @@
 	return newsk;
 }
 
+/* 
+ * The three way handshake has completed - we got a valid synack - 
+ * now create the new socket. 
+ */
 struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 				   struct open_request *req,
 				   struct dst_entry *dst)
@@ -1280,7 +1289,7 @@
 	int snd_mss;
 	int mtu;
 
-#ifdef NEW_LISTEN
+#ifdef TCP_NEW_LISTEN
 	if (sk->ack_backlog > sk->max_ack_backlog)
 		goto exit; /* head drop */
 #endif
@@ -1288,13 +1297,14 @@
 		struct rtable *rt;
 		
 		if (ip_route_output(&rt,
-				    opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
-				    req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0))
+			opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
+			req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0))
 			return NULL;
 	        dst = &rt->u.dst;
 	}
 
-#ifdef NEW_LISTEN
+#ifdef TCP_NEW_LISTEN
+	sk->tp_pinfo.af_tcp.syn_backlog--;
 	sk->ack_backlog++;
 #endif
 
@@ -1343,6 +1353,11 @@
 	    after(TCP_SKB_CB(skb)->seq, req->snt_isn+1))
 		return;
 	tcp_synq_unlink(tp, req, prev);
+#ifdef TCP_NEW_LISTEN
+	(req->sk ? sk->ack_backlog : tp->syn_backlog)--;
+#else
+	sk->ack_backlog--;
+#endif
 	req->class->destructor(req);
 	tcp_openreq_free(req); 
 }
@@ -1468,9 +1483,14 @@
 		skb->csum = csum_partial((char *)th, len, 0);
 	case CHECKSUM_HW:
 		if (tcp_v4_check(th,len,skb->nh.iph->saddr,skb->nh.iph->daddr,skb->csum)) {
-			printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, len=%d/%d/%d\n",
- 			       NIPQUAD(skb->nh.iph->saddr), ntohs(th->source), NIPQUAD(skb->nh.iph->daddr),
-			       ntohs(th->dest), len, skb->len, ntohs(skb->nh.iph->tot_len));
+			printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, "
+			       "len=%d/%d/%d\n",
+ 			       NIPQUAD(ntohl(skb->nh.iph->saddr)),
+			       ntohs(th->source), 
+			       NIPQUAD(ntohl(skb->nh.iph->daddr)),
+			       ntohs(th->dest),
+			       len, skb->len,
+			       ntohs(skb->nh.iph->tot_len));
 			tcp_statistics.TcpInErrs++;
 			goto discard_it;
 		}
@@ -1642,7 +1662,7 @@
 	tp->rto  = TCP_TIMEOUT_INIT;		/*TCP_WRITE_TIME*/
 	tp->mdev = TCP_TIMEOUT_INIT;
 	tp->in_mss = 536;
-
+      
 	/* See draft-stevens-tcpca-spec-01 for discussion of the
 	 * initialization of these values.
 	 */
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.1.92/linux/net/ipv4/tcp_output.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/tcp_output.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.81 1998/03/30 08:41:36 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.83 1998/04/03 08:10:45 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -109,6 +109,9 @@
 		th->check		= 0;
 		th->urg_ptr		= ntohs(tcb->urg_ptr);
 		if(tcb->flags & TCPCB_FLAG_SYN) {
+			/* RFC1323: The window in SYN & SYN/ACK segments
+			 * is never scaled.
+			 */
 			th->window	= htons(tp->rcv_wnd);
 			tcp_syn_build_options((__u32 *)(th + 1), sk->mss,
 					      sysctl_tcp_timestamps,
@@ -610,6 +613,24 @@
 		TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
 		TCP_SKB_CB(skb)->end_seq++;
 		tp->write_seq++;
+
+		/* Special case to avoid Nagle bogosity.  If this
+		 * segment is the last segment, and it was queued
+		 * due to Nagle/SWS-avoidance, send it out now.
+		 */
+		if(tp->send_head == skb &&
+		   !sk->nonagle &&
+		   skb->len < (sk->mss >> 1) &&
+		   tp->packets_out &&
+		   !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) {
+			update_send_head(sk);
+			TCP_SKB_CB(skb)->when = jiffies;
+			tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+			tp->packets_out++;
+			tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+			if(!tcp_timer_is_set(sk, TIME_RETRANS))
+				tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+		}
 	} else {
 		/* Socket is locked, keep trying until memory is available. */
 		do {
@@ -755,6 +776,8 @@
 			&rcv_wscale);
 		req->rcv_wscale = rcv_wscale; 
 	}
+
+	/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
 	th->window = htons(req->rcv_wnd);
 
 	TCP_SKB_CB(skb)->when = jiffies;
diff -u --recursive --new-file v2.1.92/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.1.92/linux/net/ipv4/tcp_timer.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/tcp_timer.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.45 1998/03/30 08:41:31 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.47 1998/04/03 10:52:05 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -451,6 +451,7 @@
 					if ((long)(now - conn->expires) <= 0)
 						break;
 
+
 					tcp_synq_unlink(tp, conn, prev);
 					if (conn->retrans >= sysctl_tcp_retries1) {
 #ifdef TCP_DEBUG
@@ -459,7 +460,11 @@
 #endif
 						(*conn->class->destructor)(conn);
 						tcp_dec_slow_timer(TCP_SLT_SYNACK);
-						sk->ack_backlog--;
+#ifdef TCP_NEW_LISTEN
+					tp->syn_backlog--;
+#else
+					sk->ack_backlog--;
+#endif
 						tcp_openreq_free(conn);
 
 						if (!tp->syn_wait_queue)
diff -u --recursive --new-file v2.1.92/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.1.92/linux/net/ipv6/tcp_ipv6.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv6/tcp_ipv6.c	Fri Apr  3 17:48:11 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.72 1998/03/30 08:41:52 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.74 1998/04/03 09:50:01 freitag Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -42,9 +42,6 @@
 
 #include <asm/uaccess.h>
 
-extern int sysctl_tcp_timestamps;
-extern int sysctl_tcp_window_scaling;
-
 static void	tcp_v6_send_reset(struct sk_buff *skb);
 static void	tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
 				  struct sk_buff *skb);
@@ -748,12 +745,12 @@
 	if (sk->ack_backlog >= sk->max_ack_backlog) {
 		printk(KERN_DEBUG "droping syn ack:%d max:%d\n",
 		       sk->ack_backlog, sk->max_ack_backlog);
-		tcp_statistics.TcpAttemptFails++;
-		goto exit;
+		goto drop;		
 	}
 
 	req = tcp_openreq_alloc();
 	if (req == NULL) {
+		goto drop;
 	}
 
 	sk->ack_backlog++;
@@ -796,8 +793,11 @@
 
 	sk->data_ready(sk, 0);
 
-exit:
 	return 0;
+
+drop:
+	tcp_statistics.TcpAttemptFails++;
+	return 0; /* don't send reset */
 }
 
 static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
