diff -u --recursive --new-file v2.2.0-pre6/linux/CREDITS linux/CREDITS
--- v2.2.0-pre6/linux/CREDITS	Fri Jan  8 22:35:58 1999
+++ linux/CREDITS	Sun Jan 10 10:26:51 1999
@@ -765,9 +765,9 @@
 S: Germany
 
 N: Richard Henderson
+E: rth@twiddle.net
 E: rth@cygnus.com
-E: richard@gnu.org
-D: Alpha/ELF, gcc, binutils, and glibc
+D: Alpha hacker, kernel and userland
 S: 50 E. Middlefield #10
 S: Mountain View, California 94043
 S: USA
@@ -910,7 +910,9 @@
 N: Niels Kristian Bech Jensen
 E: nkbj@image.dk
 W: http://www.image.dk/~nkbj
-D: 4.4BSD and NeXTstep support in read-only ufs
+D: 4.4BSD and NeXTstep filesystem support in the old ufs.
+D: Openstep filesystem support in the new ufs.
+D: Danish HOWTO, Linux+FreeBSD mini-HOWTO.
 S: Dr. Holsts Vej 34, lejl. 164
 S: DK-8230 Åbyhøj
 S: Denmark
@@ -1507,7 +1509,12 @@
 
 N: Reed H. Petty
 E: rhp@draper.net
+W: http://www.draper.net
 D: Loop device driver extensions
+D: Encryption transfer modules (no export)
+S: Post Office Box 1815
+S: Harrison, Arkansas  72602-1815
+S: USA
 
 N: Kai Petzke
 E: wpp@marie.physik.tu-berlin.de
diff -u --recursive --new-file v2.2.0-pre6/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.0-pre6/linux/Documentation/Configure.help	Thu Jan  7 15:11:35 1999
+++ linux/Documentation/Configure.help	Sun Jan 10 22:27:27 1999
@@ -131,6 +131,13 @@
   If you are not sure, say Y; apart from resulting in a 45 KB bigger
   kernel, it won't hurt.
 
+Kernel FP software completion
+CONFIG_MATHEMU
+  This option is required for IEEE compliant floating point arithmetic
+  on the Alpha.  The only time you would ever not say Y is to say M
+  in order to debug the code.  Do not say anything but Y unless you
+  know what you are doing.
+
 Normal PC floppy disk support
 CONFIG_BLK_DEV_FD
   If you want to use the floppy disk drive(s) of your PC under Linux,
@@ -1169,38 +1176,50 @@
   if you have a floppy drive, otherwise N. Easy.
 
 Alpha system type
-CONFIG_ALPHA_AVANTI
-  Find out what type of Alpha motherboard you have. You will probably
-  want to read the Linux/Alpha home page on the WWW at
-  http://www.azstarnet.com/~axplinux/ (to browse the WWW, you need to
+CONFIG_ALPHA_GENERIC
+  This is the system type of your hardware.  A "generic" kernel will
+  run on any supported Alpha system.  Configuring a kernel for one
+  specific system can save about 200K and operate more efficiently.
+
+  To find out what type of Alpha system you have, you may want to
+  check out the Linux/Alpha FAQ, accessible on the WWW from
+  http://www.azstarnet.com/~axplinux/ (To browse the WWW, you need to
   have access to a machine on the Internet that has a program like
-  lynx or netscape) and also the Alpha-HOWTO, available via FTP (user:
-  anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. For this
-  question, it suffices to give a unique prefix of the option you want
-  to choose. The choices:
-  ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400)
-     AlphaStations. These usually come with a TGA graphics adapter,
-     so you'll want to say Y to "TGA Console support", below, if you
-     have one of these.
-  ** Alpha-XL: A.k.a. "Windows NT Dream Machine" :-) These usually 
-     come with a TGA graphics adapter, so you'll want to say Y to "TGA
-     Console support", below, if you have one of these.
-  ** Jensen: a.k.a. DEC 2000 a.k.a. DECpc AXP 150, the oldest Alpha
-     PC; it sports an EISA bus. The boot process on Jensen machines is
-     difficult (no booting from floppies, MILO doesn't work). You need
-     to have access to a second Linux workstation. The Linux/Alpha
-     FAQ, accessible from the above mentioned WWW page, has details.
-  ** Noname: a.k.a. AXPpci33, a PCI-bus based board using the 21066
-     Alpha CPU, running at either 166 or 233 MHz. You also want to
-     choose this option if you have a UDB (Universal Desktop Box
-     a.k.a. Multia) machine.
-  ** Cabriolet: also called AlphaPC64, a PCI-bus based board using the
-     21064 Alpha CPU typically running at 275 or 300 MHz.
-  ** EB66: "Evaluation Board"
-  ** EB66+: "Evaluation Board"
-###
-### Add info about Platform2000, EB164, etc.
-###
+  lynx or netscape).  In summary:
+
+  Alcor/Alpha-XLT     AS 600
+  Alpha-XL            XL-233, XL-266
+  AlphaBook1          Alpha laptop
+  Avanti              AS 200, AS 205, AS 250, AS 255, AS 300, AS 400
+  Cabriolet           AlphaPC64, AlphaPCI64
+  DP264               DP264
+  EB164               EB164 21164 evaluation board
+  EB64+               EB64+ 21064 evaluation board
+  EB66                EB66 21066 evaluation board
+  EB66+               EB66+ 21066 evaluation board
+  Jensen              DECpc 150, DEC 2000 model 300, DEC 2000 model 500
+  LX164               AlphaPC164-LX
+  Miata               Personal Workstation 433a, 433au, 500a,
+                      500au, 600a, or 600au
+  Mikasa              AS 1000
+  Noname              AXPpci33, UDB (Multia)
+  Noritake            AS 1000A, AS 600A, AS 800
+  PC164               AlphaPC164
+  Rawhide             AS 1200, AS 4000, AS 4100
+  Ruffian             RPX164-2, AlphaPC164-UX, AlphaPC164-BX
+  SX164               AlphaPC164-SX
+  Sable               AS 2000, AS 2100
+  Takara              Takara
+
+  If you don't know what to do, choose "generic".
+
+EV5 CPU daughtercard
+CONFIG_ALPHA_PRIMO
+  Say Y if you have an AS 1000 5/xxx or an AS 1000A 5/xxx.
+
+EV5 CPU(s)
+CONFIG_ALPHA_GAMMA
+  Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx.
 
 Using SRM as bootloader
 CONFIG_ALPHA_SRM
@@ -1225,6 +1244,12 @@
 
   If unsure, say N.
 
+Use SRM PCI setup
+CONFIG_ALPHA_SRM_SETUP
+  This option controls whether or not the PCI configuration set up by
+  SRM is modified.  If you say Y, the existing PCI configuration will
+  be left intact.
+
 Non-standard serial port support
 CONFIG_SERIAL_NONSTANDARD
   Say Y here if you have any non-standard serial boards -- boards
@@ -4108,6 +4133,17 @@
   say M here and read Documentation/modules.txt. The module will be
   called in2000.o.
 
+Initio 91XXU(W) SCSI support
+CONFIG_SCSI_INITIO
+  This is support for the Initio 91XXU(W) SCSI host adapter.
+  Please read the SCSI-HOWTO, available via FTP (user: anonymous) at
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called initio.o
+
 PAS16 SCSI support
 CONFIG_SCSI_PAS16
   This is support for a SCSI host adapter. It is explained in section
@@ -8461,13 +8497,40 @@
 
 Ignore multiple suspend/resume cycles
 CONFIG_APM_IGNORE_SUSPEND_BOUNCE
-  This option is necessary on the Dell Inspiron 3200, but should be
-  safe for all other laptops. When enabled, a system suspend event
-  that occurs within one second of a resume is ignored. Without this
-  the Inspiron will shut itself off a few seconds after you open the
-  lid, requiring you to press the power button to resume it a second
-  time.
+  This option is necessary on the Dell Inspiron 3200 and others, but
+  should be safe for all other laptops. When enabled, a system suspend
+  event that occurs within one second of a resume is ignored. Without
+  this the Inspiron will shut itself off a few seconds after you open
+  the lid, requiring you to press the power button to resume it a
+  second time.
   Say Y.
+
+RTC stores time in GMT
+CONFIG_APM_RTC_IS_GMT
+  This option can be used when your RTC (Real Time Clock aka. Hardware
+  Clock) stores the time in GMT (Greenwich Mean Time) rather than
+  localtime. When suspending/resuming, the kernel needs to know what
+  is stored in the RTC so it can update the system clock (which is
+  always GMT). Without this option the kernel attempts to measure
+  the offset between the RTC and the system clock. This means you
+  can loose one second on each suspend/resume cycle.
+  Also, on the Dell Inspiron 3200, the hardware slows down the system
+  even before the kernel can measure the RTC/system clock offset. It
+  can then take 15 seconds to do this measurement and it can be
+  incorrect by several seconds.
+  Say Y if GMT is stored in your RTC.
+  GMT is usually the best anyway, because you don't have to worry about
+  daylight savings time changes. The only reason to not use GMT in
+  your RTC is if you also run a broken OS that doesn't understand GMT.
+
+Allow interrupts during APM BIOS calls
+CONFIG_APM_ALLOW_INTS
+  Normally we disable external interrupts while we are making calls to
+  the APM BIOS as a measure to lessen the effects of a badly behaving
+  BIOS implementation.  The BIOS should reeanble interrupts if it
+  needs to.  Unfortunately, some BIOS's do not - especially those in
+  many of the newer IBM Thinkpads.  If you experience hangs when you
+  suspend, try setting this to Y.  Otherwise, say N.
 
 Watchdog Timer Support 
 CONFIG_WATCHDOG
diff -u --recursive --new-file v2.2.0-pre6/linux/Documentation/sound/VIA-chipset linux/Documentation/sound/VIA-chipset
--- v2.2.0-pre6/linux/Documentation/sound/VIA-chipset	Fri Jan  8 22:35:59 1999
+++ linux/Documentation/sound/VIA-chipset	Sat Jan  9 19:16:43 1999
@@ -39,5 +39,5 @@
 and rebuild a kernel without PCI quirk support.
 
 
-Other than this paticular glitch the VIA [M]VP* chipsets appear to work
+Other than this particular glitch the VIA [M]VP* chipsets appear to work
 perfectly with Linux.
diff -u --recursive --new-file v2.2.0-pre6/linux/Makefile linux/Makefile
--- v2.2.0-pre6/linux/Makefile	Fri Jan  8 22:36:00 1999
+++ linux/Makefile	Sun Jan 10 22:56:43 1999
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION =-pre6
+EXTRAVERSION =-pre7
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -412,8 +412,9 @@
 
 depend dep: dep-files $(MODVERFILE)
 
+# make checkconfig: Prune 'scripts' directory to avoid "false positives".
 checkconfig:
-	perl -w scripts/checkconfig.pl `find * -name '*.[hcS]' -print | sort`
+	perl -w scripts/checkconfig.pl `find * -path 'scripts' -prune -o -name '*.[hcS]' -print | sort`
 
 checkhelp:
 	perl -w scripts/checkhelp.pl `find * -name [cC]onfig.in -print`
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.2.0-pre6/linux/arch/alpha/Makefile	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/Makefile	Sun Jan 10 09:59:54 1999
@@ -31,17 +31,19 @@
   ifeq ($(CONFIG_ALPHA_EV4),y)
     CFLAGS := $(CFLAGS) -mcpu=ev4
   endif
-  # Leave out EV5, since it is too hard to figure out whether we
-  # should use EV56 insns or not.
+  ifeq ($(CONFIG_ALPHA_PYXIS),y)
+    CFLAGS := $(CFLAGS) -mcpu=ev56
+  endif
   ifeq ($(CONFIG_ALPHA_EV6),y)
     CFLAGS := $(CFLAGS) -mcpu=ev6
   endif
 endif
 
 # For TSUNAMI, we must have the assembler not emulate our instructions.
+# The same is true for POLARIS.
 # BWX is most important, but we don't really want any emulation ever.
 ifeq ($(old_gas),y)
- ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI),)
+ ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS),)
    # How do we do #error in make?
    CFLAGS := --error-please-upgrade-your-assembler
  endif
@@ -51,6 +53,9 @@
  endif
  ifeq ($(CONFIG_ALPHA_PYXIS),y)
    CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED
+ endif
+ ifeq ($(CONFIG_ALPHA_POLARIS),y)
+   CFLAGS := $(CFLAGS) -Wa,-m21164a
  endif
 endif
 
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.2.0-pre6/linux/arch/alpha/config.in	Thu Dec 31 10:28:58 1998
+++ linux/arch/alpha/config.in	Sun Jan 10 09:59:54 1999
@@ -43,6 +43,7 @@
 	 Platform2000		CONFIG_ALPHA_P2K		\
 	 Rawhide		CONFIG_ALPHA_RAWHIDE		\
 	 Ruffian		CONFIG_ALPHA_RUFFIAN		\
+	 RX164			CONFIG_ALPHA_RX164		\
 	 SX164			CONFIG_ALPHA_SX164		\
 	 Sable			CONFIG_ALPHA_SABLE		\
 	 Takara			CONFIG_ALPHA_TAKARA" Generic
@@ -51,7 +52,7 @@
 unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
 unset CONFIG_PCI CONFIG_ALPHA_EISA
 unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
-unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS
+unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
 unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
 unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
 
@@ -129,6 +130,12 @@
 	define_bool CONFIG_PCI y
 	define_bool CONFIG_ALPHA_EV5 y
 	define_bool CONFIG_ALPHA_MCPCIA y
+fi
+if [ "$CONFIG_ALPHA_RX164" = "y" ]
+then
+	define_bool CONFIG_PCI y
+	define_bool CONFIG_ALPHA_EV5 y
+	define_bool CONFIG_ALPHA_POLARIS y
 fi
 if [ "$CONFIG_ALPHA_JENSEN" = "y" ]
 then
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.2.0-pre6/linux/arch/alpha/kernel/Makefile	Tue Dec 22 14:16:53 1998
+++ linux/arch/alpha/kernel/Makefile	Sun Jan 10 09:59:54 1999
@@ -23,11 +23,11 @@
 ifdef CONFIG_ALPHA_GENERIC
 
 O_OBJS	 += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \
-	    core_t2.o core_tsunami.o \
+	    core_t2.o core_tsunami.o core_polaris.o \
 	    sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o \
 	    sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \
 	    sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \
-	    sys_sx164.o sys_takara.o \
+	    sys_sx164.o sys_takara.o sys_rx164.o \
 	    es1888.o smc37c669.o smc37c93x.o
 else
 
@@ -53,6 +53,9 @@
 ifdef CONFIG_ALPHA_TSUNAMI
 O_OBJS   += core_tsunami.o
 endif
+ifdef CONFIG_ALPHA_POLARIS
+O_OBJS   += core_polaris.o
+endif
 
 # Board support
 ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),)
@@ -84,6 +87,9 @@
 endif
 ifdef CONFIG_ALPHA_RUFFIAN
 O_OBJS   += sys_ruffian.o
+endif
+ifdef CONFIG_ALPHA_RX164
+O_OBJS   += sys_rx164.o
 endif
 ifdef CONFIG_ALPHA_SABLE
 O_OBJS   += sys_sable.o
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/bios32.h linux/arch/alpha/kernel/bios32.h
--- v2.2.0-pre6/linux/arch/alpha/kernel/bios32.h	Wed Sep  9 14:51:03 1998
+++ linux/arch/alpha/kernel/bios32.h	Sun Jan 10 09:59:54 1999
@@ -32,6 +32,13 @@
 #define DEFAULT_IO_BASE 0x8000		/* start at 8th slot */
 
 /*
+ * We try to make the DEFAULT_MEM_BASE addresses *always* have more than
+ * a single bit set. This is so that devices like the broken Myrinet card
+ * will always have a PCI memory address that will never match a IDSEL
+ * address in PCI Config space, which can cause problems with early rev cards.
+ */
+
+/*
  * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
  * that get passed through the PCI<->ISA bridge chip. Although this causes
  * us to set the PCI->Mem window bases lower than normal, we still allocate
@@ -45,22 +52,20 @@
 #define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
 
 /*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * However, APECS and LCA have only 34 bits for physical addresses, thus
- * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb.
+ * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI
+ * bus memory addresses for SPARSE access to be less than 128Mb.
  */
 #define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB)
 
 /*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
+ * Because the MCPCIA core logic supports more bits for physical addresses,
+ * it should allow an expanded range of SPARSE memory addresses.
+ * However, we do not use them all, in order to avoid the HAE manipulation
+ * that would be needed.
+ */
+#define RAWHIDE_DEFAULT_MEM_BASE (64*MB + 2*MB)
+
+/*
  * Because CIA and PYXIS and T2 have more bits for physical addresses,
  * they support an expanded range of SPARSE memory addresses.
  */
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_polaris.c linux/arch/alpha/kernel/core_polaris.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/core_polaris.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/core_polaris.c	Sun Jan 10 22:56:43 1999
@@ -0,0 +1,275 @@
+/*
+ *      linux/arch/alpha/kernel/core_polaris.c
+ *
+ * POLARIS chip-specific code
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/pci.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_polaris.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+#include "bios32.h"
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG_CONFIG
+# define DBG_CFG(args)	printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+#define DEBUG_MCHECK
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args)	printk args
+/* #define DEBUG_MCHECK_DUMP */
+#else
+# define DBG_MCK(args)
+#endif
+
+static volatile unsigned int POLARIS_mcheck_expected = 0;
+static volatile unsigned int POLARIS_mcheck_taken = 0;
+static volatile unsigned short POLARIS_jd = 0;
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address.  This is fairly straightforward
+ * on POLARIS, since the chip itself generates Type 0 or Type 1
+ * cycles automatically depending on the bus number (Bus 0 is
+ * hardwired to Type 0, all others are Type 1.  Peer bridges
+ * are not supported).
+ *
+ * All types:
+ *
+ *  3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1|1|1|1|1|0|0|1|1|1|1|1|1|1|1|0|B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|x|x|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *	23:16	bus number (8 bits = 128 possible buses)
+ *	15:11	Device number (5 bits)
+ *	10:8	function number
+ *	 7:2	register number
+ *  
+ * Notes:
+ *	The function number selects which function of a multi-function device 
+ *	(e.g., scsi and ethernet).
+ * 
+ *	The register selects a DWORD (32 bit) register offset.  Hence it
+ *	doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ *	bits.
+ */
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1)
+{
+	*type1 = (bus == 0) ? 0 : 1;
+	*pci_addr = (bus << 16) | (device_fn << 8) | (where) |
+		    POLARIS_DENSE_CONFIG_BASE;
+
+        DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+                 " returning address 0x%p\n"
+                 bus, device_fn, where, *pci_addr));
+
+	return 0;
+}
+
+int
+polaris_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
+                             struct linux_hose_info *hose)
+{
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+                return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = __kernel_ldbu(*(vucp)pci_addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
+                             struct linux_hose_info *hose)
+{
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+                return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = __kernel_ldwu(*(vusp)pci_addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
+                              struct linux_hose_info *hose)
+{
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+                return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = *(vuip)pci_addr;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int 
+polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
+                              struct linux_hose_info *hose)
+{
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+                return PCIBIOS_DEVICE_NOT_FOUND;
+
+        __kernel_stb(value, *(vucp)pci_addr);
+	mb();
+	__kernel_ldbu(*(vucp)pci_addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int 
+polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
+                              struct linux_hose_info *hose)
+{
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+                return PCIBIOS_DEVICE_NOT_FOUND;
+
+        __kernel_stw(value, *(vusp)pci_addr);
+	mb();
+	__kernel_ldbu(*(vusp)pci_addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int 
+polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
+                               struct linux_hose_info *hose)
+{
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+                return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*(vuip)pci_addr = value;
+	mb();
+	*(vuip)pci_addr;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+	/* May need to initialize error reporting (see PCICTL0/1), but
+	 * for now assume that the firmware has done the right thing
+	 * already.
+	 */
+#if 0
+	printk("polaris_init_arch(): trusting firmware for setup\n");
+#endif
+}
+
+int polaris_pci_clr_err(void)
+{
+	POLARIS_jd = *((vusp)POLARIS_W_STATUS);
+	DBG_MCK(("POLARIS_pci_clr_err: POLARIS_W_STATUS after read 0x%x\n",
+		 POLARIS_jd));
+	/* Write 1's to settable bits to clear errors */
+	*((vusp)POLARIS_W_STATUS) = 0x7800; mb();
+	POLARIS_jd = *((vusp)POLARIS_W_STATUS);
+	return 0;
+}
+
+void polaris_machine_check(unsigned long vector, unsigned long la_ptr,
+			 struct pt_regs * regs)
+{
+	struct el_common *mchk_header;
+	struct el_POLARIS_sysdata_mcheck *mchk_sysdata;
+
+	mchk_header = (struct el_common *)la_ptr;
+
+	mchk_sysdata = 
+	  (struct el_POLARIS_sysdata_mcheck *)(la_ptr+mchk_header->sys_offset);
+
+#if 0
+	DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+	     vector, la_ptr));
+	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+	     regs->pc, mchk_header->size, mchk_header->proc_offset,
+	     mchk_header->sys_offset));
+	DBG_MCK(("polaris_machine_check: expected %d status 0x%lx\n",
+	     POLARIS_mcheck_expected, mchk_sysdata->psc_status));
+#endif
+#ifdef DEBUG_MCHECK_DUMP
+	{
+	    unsigned long *ptr;
+	    int i;
+
+	    ptr = (unsigned long *)la_ptr;
+	    for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+		printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+	    }
+	}
+#endif /* DEBUG_MCHECK_DUMP */
+	/*
+	 * Check if machine check is due to a badaddr() and if so,
+	 * ignore the machine check.
+	 */
+	mb();
+	mb();
+	if (POLARIS_mcheck_expected) {
+		DBG_MCK(("POLARIS machine check expected\n"));
+		POLARIS_mcheck_expected = 0;
+		POLARIS_mcheck_taken = 1;
+		mb();
+		mb();
+		draina();
+		polaris_pci_clr_err();
+		wrmces(0x7);
+		mb();
+	}
+#if 1
+	else {
+		printk("POLARIS machine check NOT expected\n") ;
+	DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+	     vector, la_ptr));
+	DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+	     regs->pc, mchk_header->size, mchk_header->proc_offset,
+	     mchk_header->sys_offset));
+		POLARIS_mcheck_expected = 0;
+		POLARIS_mcheck_taken = 1;
+		mb();
+		mb();
+		draina();
+		polaris_pci_clr_err();
+		wrmces(0x7);
+		mb();
+	}
+#endif
+}
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_t2.c linux/arch/alpha/kernel/core_t2.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/core_t2.c	Wed Sep  9 14:51:03 1998
+++ linux/arch/alpha/kernel/core_t2.c	Sat Jan  9 19:08:21 1999
@@ -143,7 +143,7 @@
 conf_read(unsigned long addr, unsigned char type1)
 {
 	unsigned long flags;
-	unsigned int stat0, value, cpu;
+	unsigned int value, cpu;
 	unsigned long t2_cfg = 0;
 
 	cpu = smp_processor_id();
@@ -153,11 +153,14 @@
 	DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
 
 #if 0
-	/* Reset status register to avoid losing errors.  */
-	stat0 = *(vulp)T2_IOCSR;
-	*(vulp)T2_IOCSR = stat0;
-	mb();
-	DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0));
+	{
+	  unsigned long stat0;
+	  /* Reset status register to avoid losing errors.  */
+	  stat0 = *(vulp)T2_IOCSR;
+	  *(vulp)T2_IOCSR = stat0;
+	  mb();
+	  DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0));
+	}
 #endif
 
 	/* If Type1 access, must set T2 CFG.  */
@@ -202,7 +205,7 @@
 conf_write(unsigned long addr, unsigned int value, unsigned char type1)
 {
 	unsigned long flags;
-	unsigned int stat0, cpu;
+	unsigned int cpu;
 	unsigned long t2_cfg = 0;
 
 	cpu = smp_processor_id();
@@ -210,11 +213,14 @@
 	__save_and_cli(flags);	/* avoid getting hit by machine check */
 
 #if 0
-	/* Reset status register to avoid losing errors.  */
-	stat0 = *(vulp)T2_IOCSR;
-	*(vulp)T2_IOCSR = stat0;
-	mb();
-	DBG(("conf_write: T2 ERR was 0x%x\n", stat0));
+	{
+	  unsigned long stat0;
+	  /* Reset status register to avoid losing errors.  */
+	  stat0 = *(vulp)T2_IOCSR;
+	  *(vulp)T2_IOCSR = stat0;
+	  mb();
+	  DBG(("conf_write: T2 ERR was 0x%x\n", stat0));
+	}
 #endif
 
 	/* If Type1 access, must set T2 CFG.  */
@@ -346,7 +352,6 @@
 void __init
 t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
-	unsigned long t2_err;
 	unsigned int i;
 
 	for (i = 0; i < NR_CPUS; i++) {
@@ -355,13 +360,15 @@
 	}
 
 #if 0
-	/* 
-	 * Set up error reporting.
-	 */
-	t2_err = *(vulp)T2_IOCSR ;
-	t2_err |= (0x1 << 7) ;   /* master abort */
-	*(vulp)T2_IOCSR = t2_err ;
-	mb() ;
+	{
+	  /* Set up error reporting.  */
+	  unsigned long t2_err;
+
+	  t2_err = *(vulp)T2_IOCSR;
+	  t2_err |= (0x1 << 7);   /* master abort */
+	  *(vulp)T2_IOCSR = t2_err;
+	  mb();
+	}
 #endif
 
 	printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE);
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/core_tsunami.c	Wed Sep  9 14:51:03 1998
+++ linux/arch/alpha/kernel/core_tsunami.c	Sun Jan 10 22:56:43 1999
@@ -9,7 +9,6 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
@@ -302,14 +301,22 @@
 		 * For now, windows 1,2 and 3 are disabled.  In the future,
 		 * we may want to use them to do scatter/gather DMA. 
 		 *
-		 * Window 0 goes at 1 GB and is 1 GB large.
+		 * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
 		 */
 
 		pchip->wsba[0].csr = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
 		pchip->wsm[0].csr = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL;
 		pchip->tba[0].csr = 0;
 
+#if 0
 		pchip->wsba[1].csr = 0;
+#else
+		/* make the second window at 2Gb for 1Gb mapping to 1Gb */
+		pchip->wsba[1].csr = 1L | ((0x80000000U) & 0xfff00000U);
+		pchip->wsm[1].csr = (0x40000000UL - 1) & 0xfff00000UL;
+		pchip->tba[1].csr = 0x40000000;
+#endif
+
 		pchip->wsba[2].csr = 0;
 		pchip->wsba[3].csr = 0;
 		mb();
@@ -359,7 +366,9 @@
 
 	/* Find how many hoses we have, and initialize them.  */
 	tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start);
-	tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
+	/* must change this for TYPHOON which may have 4 */
+	if (TSUNAMI_cchip->csc.csr & 1L<<14)
+	    tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
 }
 
 static inline void
@@ -378,7 +387,9 @@
 {
 	int cpu = smp_processor_id();
 	tsunami_pci_clr_err_1(TSUNAMI_pchip0, cpu);
-	tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu);
+	/* must change this for TYPHOON which may have 4 */
+	if (TSUNAMI_cchip->csc.csr & 1L<<14)
+	    tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu);
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.2.0-pre6/linux/arch/alpha/kernel/entry.S	Thu Dec 31 10:28:58 1998
+++ linux/arch/alpha/kernel/entry.S	Sat Jan  9 19:08:21 1999
@@ -8,10 +8,9 @@
 
 #define halt	.long PAL_halt
 #define rti	.long PAL_rti
-#define SIGCHLD	20
+#define SIGCHLD 20
 
 #define NR_SYSCALLS 370
-#define osf_vfork sys_fork
 
 /*
  * These offsets must match with alpha_mv in <asm/machvec.h>.
@@ -502,6 +501,17 @@
 .end	sys_clone
 
 .align 3
+.globl	sys_vfork
+.ent	sys_vfork
+sys_vfork:
+	bsr $1,do_switch_stack
+	bis $30,$30,$16
+	jsr $26,alpha_vfork
+	bsr $1,undo_switch_stack
+	ret $31,($26),1
+.end	sys_vfork
+
+.align 3
 .globl  alpha_switch_to
 .ent    alpha_switch_to
 alpha_switch_to:
@@ -822,7 +832,7 @@
 	.quad sys_getpgrp
 	.quad sys_getpagesize
 	.quad alpha_ni_syscall			/* 65 */
-	.quad osf_vfork
+	.quad sys_vfork
 	.quad sys_newstat
 	.quad sys_newlstat
 	.quad alpha_ni_syscall
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/irq.c	Thu Dec 31 10:28:58 1998
+++ linux/arch/alpha/kernel/irq.c	Sun Jan 10 09:59:54 1999
@@ -105,6 +105,8 @@
 # define IACK_SC	PYXIS_IACK_SC
 #elif defined(CONFIG_ALPHA_TSUNAMI)
 # define IACK_SC	TSUNAMI_IACK_SC
+#elif defined(CONFIG_ALPHA_POLARIS)
+# define IACK_SC	POLARIS_IACK_SC
 #else
   /* This is bogus but necessary to get it to compile on all platforms. */
 # define IACK_SC	1L
@@ -314,14 +316,14 @@
 
 int get_irq_list(char *buf)
 {
-	int i, j;
+	int i;
 	struct irqaction * action;
 	char *p = buf;
 
 #ifdef __SMP__
 	p += sprintf(p, "           ");
-	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ", j);
+	for (i = 0; i < smp_num_cpus; i++)
+		p += sprintf(p, "CPU%d       ", i);
 	*p++ = '\n';
 #endif
 
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/machvec.h linux/arch/alpha/kernel/machvec.h
--- v2.2.0-pre6/linux/arch/alpha/kernel/machvec.h	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/machvec.h	Sun Jan 10 09:59:54 1999
@@ -13,6 +13,11 @@
    we can read and write it as we like.  ;-)  */
 #define TSUNAMI_HAE_ADDRESS	(&alpha_mv.hae_cache)
 
+/* Whee.  POLARIS doesn't have an HAE.  Fix things up for the GENERIC
+   kernel by defining the HAE address to be that of the cache.  Now
+   we can read and write it as we like.  ;-)  */
+#define POLARIS_HAE_ADDRESS	(&alpha_mv.hae_cache)
+
 /* Only a few systems don't define IACK_SC, handling all interrupts through
    the SRM console.  But splitting out that one case from IO() below
    seems like such a pain.  Define this to get things to compile.  */
@@ -91,6 +96,7 @@
 #define DO_LCA_IO	IO(LCA,lca,lca)
 #define DO_MCPCIA_IO	IO(MCPCIA,mcpcia,mcpcia)
 #define DO_PYXIS_IO	IO(PYXIS,pyxis_bw,pyxis)
+#define DO_POLARIS_IO	IO(POLARIS,polaris,polaris)
 #define DO_T2_IO	IO(T2,t2,t2)
 #define DO_TSUNAMI_IO	IO(TSUNAMI,tsunami,tsunami)
 
@@ -103,6 +109,7 @@
 #define DO_LCA_BUS	BUS(lca)
 #define DO_MCPCIA_BUS	BUS(mcpcia)
 #define DO_PYXIS_BUS	BUS(pyxis)
+#define DO_POLARIS_BUS	BUS(polaris)
 #define DO_T2_BUS	BUS(t2)
 #define DO_TSUNAMI_BUS	BUS(tsunami)
 
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/process.c	Fri Jan  8 22:36:00 1999
+++ linux/arch/alpha/kernel/process.c	Sat Jan  9 19:10:39 1999
@@ -55,6 +55,7 @@
 unsigned long init_user_stack[1024] = { STACK_MAGIC, };
 static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
+static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
 struct mm_struct init_mm = INIT_MM;
@@ -256,11 +257,26 @@
  * with parameters (SIGCHLD, 0).
  */
 int alpha_clone(unsigned long clone_flags, unsigned long usp,
-	struct switch_stack * swstack)
+		struct switch_stack * swstack)
 {
 	if (!usp)
 		usp = rdusp();
-	return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1));
+	return do_fork(clone_flags & ~CLONE_VFORK, usp, (struct pt_regs *) (swstack+1));
+}
+
+int alpha_vfork(struct switch_stack * swstack)
+{
+	int child;
+	struct semaphore sem = MUTEX_LOCKED;
+
+	current->vfork_sem = &sem;
+	child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
+			(struct pt_regs *) (swstack+1));
+
+	if (child > 0)
+		down(&sem);
+
+	return child;
 }
 
 extern void ret_from_sys_call(void);
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.2.0-pre6/linux/arch/alpha/kernel/proto.h	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/proto.h	Sun Jan 10 09:59:59 1999
@@ -76,6 +76,22 @@
 extern void mcpcia_init_arch(unsigned long *, unsigned long *);
 extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
 
+/* core_polaris.c */
+extern int polaris_hose_read_config_byte (u8, u8, u8, u8 *value,
+					struct linux_hose_info *hose);
+extern int polaris_hose_read_config_word (u8, u8, u8, u16 *value,
+					struct linux_hose_info *hose);
+extern int polaris_hose_read_config_dword (u8, u8, u8, u32 *value,
+					 struct linux_hose_info *hose);
+extern int polaris_hose_write_config_byte (u8, u8, u8, u8 value,
+					 struct linux_hose_info *hose);
+extern int polaris_hose_write_config_word (u8, u8, u8, u16 value,
+					 struct linux_hose_info *hose);
+extern int polaris_hose_write_config_dword (u8, u8, u8, u32 value,
+					  struct linux_hose_info *hose);
+extern void polaris_init_arch(unsigned long *, unsigned long *);
+extern void polaris_machine_check(u64, u64, struct pt_regs *);
+
 /* core_pyxis.c */
 extern int pyxis_hose_read_config_byte (u8, u8, u8, u8 *value,
 					struct linux_hose_info *hose);
@@ -129,8 +145,6 @@
 extern void tsunami_machine_check(u64, u64, struct pt_regs *);
 
 /* setup.c */
-extern void init_pit_rest(void);
-extern void generic_init_pit (void);
 extern unsigned long srm_hae;
 
 /* smp.c */
@@ -143,6 +157,8 @@
 
 /* time.c */
 extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
+extern void rtc_init_pit(void);
+extern void generic_init_pit(void);
 extern unsigned long est_cycle_freq;
 
 /* smc37c93x.c */
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/setup.c	Wed Dec 16 10:32:54 1998
+++ linux/arch/alpha/kernel/setup.c	Sun Jan 10 09:59:59 1999
@@ -109,6 +109,7 @@
 extern struct alpha_machine_vector mikasa_mv;
 extern struct alpha_machine_vector mikasa_primo_mv;
 extern struct alpha_machine_vector monet_mv;
+extern struct alpha_machine_vector webbrick_mv;
 extern struct alpha_machine_vector noname_mv;
 extern struct alpha_machine_vector noritake_mv;
 extern struct alpha_machine_vector noritake_primo_mv;
@@ -116,6 +117,7 @@
 extern struct alpha_machine_vector pc164_mv;
 extern struct alpha_machine_vector rawhide_mv;
 extern struct alpha_machine_vector ruffian_mv;
+extern struct alpha_machine_vector rx164_mv;
 extern struct alpha_machine_vector sable_mv;
 extern struct alpha_machine_vector sable_gamma_mv;
 extern struct alpha_machine_vector sx164_mv;
@@ -137,6 +139,7 @@
 #pragma weak mikasa_mv
 #pragma weak mikasa_primo_mv
 #pragma weak monet_mv
+#pragma weak webbrick_mv
 #pragma weak noname_mv
 #pragma weak noritake_mv
 #pragma weak noritake_primo_mv
@@ -144,6 +147,7 @@
 #pragma weak pc164_mv
 #pragma weak rawhide_mv
 #pragma weak ruffian_mv
+#pragma weak rx164_mv
 #pragma weak sable_mv
 #pragma weak sable_gamma_mv
 #pragma weak sx164_mv
@@ -264,7 +268,7 @@
 		if (initrd_end > *memory_end_p) {
 			printk("initrd extends beyond end of memory "
 			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			       initrd_end, memory_end_p);
+			       initrd_end, (unsigned long) memory_end_p);
 			initrd_start = initrd_end = 0;
 		}
 	}
@@ -275,6 +279,16 @@
 	if (alpha_mv.init_arch)
 		alpha_mv.init_arch(memory_start_p, memory_end_p);
 
+	/* Initialize the timers.  */
+	/* ??? There is some circumstantial evidence that this needs
+	   to be done now rather than later in time_init, which would
+	   be more natural.  Someone please explain or refute.  */
+#if defined(CONFIG_RTC)
+	rtc_init_pit();
+#else
+	alpha_mv.init_pit();
+#endif
+
 	/* 
 	 * Give us a default console.  TGA users will see nothing until
 	 * chr_dev_init is called, rather late in the boot sequence.
@@ -349,8 +363,8 @@
 
 static char unofficial_names[][8] = {"100", "Ruffian"};
 
-static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164"};
-static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
+static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164", "RX164"};
+static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3,4};
 
 static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"};
 static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
@@ -430,7 +444,7 @@
 
 	static struct alpha_machine_vector *eb164_vecs[] __initlocaldata =
 	{
-		&eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv
+		&eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv, &rx164_mv
 	};
 
 	static struct alpha_machine_vector *eb64p_vecs[] __initlocaldata =
@@ -455,7 +469,7 @@
 		&monet_mv,		/* monet */
 		&dp264_mv,		/* clipper */
 		&dp264_mv,		/* goldrush */
-		&dp264_mv,		/* webbrick */
+		&webbrick_mv,		/* webbrick */
 		&dp264_mv,		/* catamaran */
 	};
 
@@ -556,10 +570,12 @@
 		&pc164_mv,
 		&rawhide_mv,
 		&ruffian_mv,
+		&rx164_mv,
 		&sable_mv,
 		&sable_gamma_mv,
 		&sx164_mv,
 		&takara_mv,
+		&webbrick_mv,
 		&xl_mv,
 		&xlt_mv
 	};
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/sys_dp264.c	Wed Dec 16 10:32:54 1998
+++ linux/arch/alpha/kernel/sys_dp264.c	Sun Jan 10 09:59:59 1999
@@ -125,6 +125,7 @@
 	outb(0, DMA1_RESET_REG);
 	outb(0, DMA2_RESET_REG);
 	outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
+	outb(0, DMA2_MASK_REG);
 
 	if (alpha_using_srm)
 		alpha_mv.device_interrupt = dp264_srm_device_interrupt;
@@ -287,6 +288,29 @@
         return slot;
 }
 
+static int __init
+webbrick_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+	static char irq_tab[13][5] __initlocaldata = {
+		/*INT    INTA   INTB   INTC   INTD */
+		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 7 ISA Bridge */
+		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 8 unused */
+		{    29,    29,    29,    29,    29}, /* IdSel 9 21143 #1 */
+		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 10 unused */
+		{    30,    30,    30,    30,    30}, /* IdSel 11 21143 #2 */
+		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 12 unused */
+		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 13 unused */
+		{    47,    47,    46,    45,    44}, /* IdSel 14 slot 0 */
+		{    39,    39,    38,    37,    36}, /* IdSel 15 slot 1 */
+		{    43,    43,    42,    41,    40}, /* IdSel 16 slot 2 */
+		{    35,    35,    34,    33,    32}, /* IdSel 17 slot 3 */
+};
+	const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5;
+	int irq = COMMON_TABLE_LOOKUP;
+
+	return irq;
+}
+
 static void __init
 dp264_pci_fixup(void)
 {
@@ -304,6 +328,14 @@
 	SMC669_Init();
 }
 
+static void __init
+webbrick_pci_fixup(void)
+{
+	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+	common_pci_fixup(webbrick_map_irq, common_swizzle);
+	SMC669_Init();
+}
+
 
 /*
  * The System Vectors
@@ -353,5 +385,27 @@
 	pci_fixup:		monet_pci_fixup,
 	kill_arch:		generic_kill_arch,
 };
-/* No alpha_mv alias for monet, since we compile it in unconditionally
+
+struct alpha_machine_vector webbrick_mv __initmv = {
+	vector_name:		"Webbrick",
+	DO_EV6_MMU,
+	DO_DEFAULT_RTC,
+	DO_TSUNAMI_IO,
+	DO_TSUNAMI_BUS,
+	machine_check:		tsunami_machine_check,
+	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+
+	nr_irqs:		64,
+	irq_probe_mask:		_PROBE_MASK(64),
+	update_irq_hw:		dp264_update_irq_hw,
+	ack_irq:		generic_ack_irq,
+	device_interrupt:	dp264_device_interrupt,
+
+	init_arch:		tsunami_init_arch,
+	init_irq:		dp264_init_irq,
+	init_pit:		generic_init_pit,
+	pci_fixup:		webbrick_pci_fixup,
+	kill_arch:		generic_kill_arch,
+};
+/* No alpha_mv alias for webbrick, since we compile it in unconditionally
    with DP264; setup_arch knows how to cope.  */
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_rawhide.c linux/arch/alpha/kernel/sys_rawhide.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/sys_rawhide.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/alpha/kernel/sys_rawhide.c	Sun Jan 10 09:59:59 1999
@@ -159,7 +159,7 @@
 static void __init
 rawhide_pci_fixup(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+	layout_all_busses(DEFAULT_IO_BASE, RAWHIDE_DEFAULT_MEM_BASE);
 	common_pci_fixup(rawhide_map_irq, common_swizzle);
 }
 
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/sys_ruffian.c	Mon Dec 28 15:00:52 1998
+++ linux/arch/alpha/kernel/sys_ruffian.c	Sat Jan  9 19:08:27 1999
@@ -82,7 +82,7 @@
 	 * then all the PCI slots/INTXs (12-31) 
 	 * flash(5) :DWH:
 	 */
-        pld &= 0x00000000ffffff9fUL; /* was ffff7f */
+	pld &= 0x00000000ffffff9fUL; /* was ffff7f */
 
 	/*
 	 * Now for every possible bit set, work through them and call
@@ -118,12 +118,12 @@
 			} else {
 				handle_irq(j, j, regs);
 			}
-                } else { /* if not an ISA int */
+		} else { /* if not an ISA int */
 			handle_irq(16 + i, 16 + i, regs);
 		}
 
-                *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
-                *(vulp)PYXIS_INT_REQ; /* read to force the write */
+		*(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+		*(vulp)PYXIS_INT_REQ; /* read to force the write */
 	}
 }
 
@@ -222,7 +222,7 @@
 
 	pyxis_enable_errors();
 	if (!pyxis_srm_window_setup()) {
-	        printk("ruffian_init_arch: Skipping window register rewrites."
+		printk("ruffian_init_arch: Skipping window register rewrites."
 		       "\n... Trust DeskStation firmware!\n");
 	}
 	pyxis_finish_init_arch();
@@ -233,7 +233,10 @@
 {
 	/* Ruffian depends on the system timer established in MILO! */
 	request_region(0x70, 0x10, "timer");
-	init_pit_rest();
+
+	outb(0xb6, 0x43);       /* pit counter 2: speaker */
+	outb(0x31, 0x42);
+	outb(0x13, 0x42);
 }
 
 static void
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/sys_rx164.c linux/arch/alpha/kernel/sys_rx164.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/sys_rx164.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/sys_rx164.c	Sun Jan 10 09:59:59 1999
@@ -0,0 +1,237 @@
+/*
+ *	linux/arch/alpha/kernel/sys_rx164.c
+ *
+ *	Copyright (C) 1995 David A Rusling
+ *	Copyright (C) 1996 Jay A Estabrook
+ *	Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the RX164 (PCA56+POLARIS).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_polaris.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+rx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+	if (irq >= 16) {
+		unsigned int temp;
+		pcibios_write_config_dword(0, 0, 0x74, ~mask >> 16);
+		pcibios_read_config_dword(0, 0, 0x74, &temp);
+	}
+	else if (irq >= 8)
+		outb(mask >> 8, 0xA1);	/* ISA PIC2 */
+	else
+		outb(mask, 0x21);	/* ISA PIC1 */
+}
+
+static void
+rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+#if 0
+	if (irq >= 16) {
+		if (unmask_p)
+			cserve_ena(irq - 16);
+		else
+			cserve_dis(irq - 16);
+	}
+	else if (irq >= 8)
+		outb(mask >> 8, 0xA1);	/* ISA PIC2 */
+	else
+		outb(mask, 0x21);	/* ISA PIC1 */
+#endif
+}
+
+static void
+rx164_isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+        unsigned long pic;
+
+        /*
+         * It seems to me that the probability of two or more *device*
+         * interrupts occurring at almost exactly the same time is
+         * pretty low.  So why pay the price of checking for
+         * additional interrupts here if the common case can be
+         * handled so much easier?
+         */
+        /* 
+         *  The first read of the PIC gives you *all* interrupting lines.
+         *  Therefore, read the mask register and and out those lines
+         *  not enabled.  Note that some documentation has 21 and a1 
+         *  write only.  This is not true.
+         */
+        pic = inb(0x20) | (inb(0xA0) << 8);     /* read isr */
+        pic &= ~alpha_irq_mask;                 /* apply mask */
+        pic &= 0xFFFB;                          /* mask out cascade & hibits */
+
+        while (pic) {
+                int j = ffz(~pic);
+                pic &= pic - 1;
+                handle_irq(j, j, regs);
+        }
+}
+
+static void 
+rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+	unsigned long pld;
+	int i;
+
+        /* Read the interrupt summary register.  On Polaris,
+         * this is the DIRR register in PCI config space (offset 0x84)
+         */
+        pld = 0;
+        pcibios_read_config_dword(0, 0, 0x84, (unsigned int *)&pld);
+
+#if 0
+        printk("PLD 0x%lx\n", pld);
+#endif
+
+        if (pld & 0xffffffff00000000UL) pld &= 0x00000000ffffffffUL;
+
+        /*
+         * Now for every possible bit set, work through them and call
+         * the appropriate interrupt handler.
+         */
+        while (pld) {
+                i = ffz(~pld);
+                pld &= pld - 1; /* clear least bit set */
+                if (i == 20) {
+                        rx164_isa_device_interrupt(vector, regs);
+                } else {
+                        handle_irq(16+i, 16+i, regs);
+                }
+        }
+}
+
+static void
+rx164_init_irq(void)
+{
+	unsigned int temp;
+
+        STANDARD_INIT_IRQ_PROLOG;
+
+        pcibios_write_config_dword(0, 0, 0x74, (~alpha_irq_mask >> 16));
+        pcibios_read_config_dword(0, 0, 0x74, &temp);
+
+        enable_irq(16 + 20);    /* enable ISA interrupts */
+	enable_irq(2);		/* enable cascade */
+}
+/* The RX164 changed its interrupt routing between pass1 and pass2...
+ *
+ * PASS1:
+ *
+ *      Slot    IDSEL   INTA    INTB    INTC    INTD    
+ *      0       6       5       10      15      20
+ *      1       7       4       9       14      19
+ *      2       5       3       8       13      18
+ *      3       9       2       7       12      17
+ *      4       10      1       6       11      16
+ *
+ * PASS2:
+ *      Slot    IDSEL   INTA    INTB    INTC    INTD    
+ *      0       5       1       7       12      17
+ *      1       6       2       8       13      18
+ *      2       8       3       9       14      19
+ *      3       9       4       10      15      20
+ *      4       10      5       11      16      6
+ *      
+ */
+
+/*
+ * IdSel       
+ *   5  32 bit PCI option slot 0
+ *   6  64 bit PCI option slot 1
+ *   7  PCI-ISA bridge
+ *   7  64 bit PCI option slot 2
+ *   9  32 bit PCI option slot 3
+ *  10  PCI-PCI bridge
+ * 
+ */
+
+static int __init
+rx164_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+#if 0
+        char irq_tab_pass1[6][5] = {
+          /*INT   INTA  INTB  INTC   INTD */
+          { 16+3, 16+3, 16+8, 16+13, 16+18},      /* IdSel 5,  slot 2 */
+          { 16+5, 16+5, 16+10, 16+15, 16+20},     /* IdSel 6,  slot 0 */
+          { 16+4, 16+4, 16+9, 16+14, 16+19},      /* IdSel 7,  slot 1 */
+          { -1,     -1,    -1,    -1,   -1},      /* IdSel 8, PCI/ISA bridge */
+          { 16+2, 16+2, 16+7, 16+12, 16+17},      /* IdSel 9,  slot 3 */
+          { 16+1, 16+1, 16+6, 16+11, 16+16},      /* IdSel 10, slot 4 */
+        };
+#endif
+        char irq_tab[6][5] = {
+          /*INT   INTA  INTB  INTC   INTD */
+          { 16+0, 16+0, 16+6, 16+11, 16+16},      /* IdSel 5,  slot 0 */
+          { 16+1, 16+1, 16+7, 16+12, 16+17},      /* IdSel 6,  slot 1 */
+          { -1,     -1,    -1,    -1,   -1},      /* IdSel 7, PCI/ISA bridge */
+          { 16+2, 16+2, 16+8, 16+13, 16+18},      /* IdSel 8,  slot 2 */
+          { 16+3, 16+3, 16+9, 16+14, 16+19},      /* IdSel 9,  slot 3 */
+          { 16+4, 16+4, 16+10, 16+15, 16+5},      /* IdSel 10, PCI-PCI */
+        };
+	const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
+        /* JRP - Need to figure out how to distinguish pass1 from pass2,
+         * and use the correct table...
+         */
+	return COMMON_TABLE_LOOKUP;
+}
+
+void __init
+rx164_pci_fixup(void)
+{
+	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+	common_pci_fixup(rx164_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vector
+ */
+
+#define POLARIS_IACK_SC	POLARIS_IACK_BASE /* hack, move to header */
+
+struct alpha_machine_vector rx164_mv __initmv = {
+	vector_name:		"RX164",
+	DO_EV5_MMU,
+	DO_DEFAULT_RTC,
+	DO_POLARIS_IO,
+	DO_POLARIS_BUS,
+	machine_check:		polaris_machine_check,
+	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+
+	nr_irqs:		40,
+	irq_probe_mask:		_PROBE_MASK(40),
+	update_irq_hw:		rx164_update_irq_hw,
+	ack_irq:		generic_ack_irq,
+	device_interrupt:	rx164_device_interrupt,
+
+	init_arch:		polaris_init_arch,
+	init_irq:		rx164_init_irq,
+	init_pit:		generic_init_pit,
+	pci_fixup:		rx164_pci_fixup,
+	kill_arch:		generic_kill_arch,
+};
+ALIAS_MV(rx164)
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.2.0-pre6/linux/arch/alpha/kernel/time.c	Mon Dec 28 15:00:52 1998
+++ linux/arch/alpha/kernel/time.c	Sat Jan  9 19:08:27 1999
@@ -158,43 +158,28 @@
  * drivers depend on them being initialized (e.g., joystick driver).
  */
 
-/* It is (normally) only counter 0 that presents config problems, so
-   provide this support function to do the rest of the job.  */
-
-void inline
-init_pit_rest(void)
-{
-#if 0
-	/* Leave refresh timer alone---nobody should depend on a
-	   particular value anyway. */
-	outb(0x54, 0x43);	/* counter 1: refresh timer */
-	outb(0x18, 0x41);
-#endif
-
-	outb(0xb6, 0x43);	/* counter 2: speaker */
-	outb(0x31, 0x42);
-	outb(0x13, 0x42);
-}
-
 #ifdef CONFIG_RTC
-static inline void
+void
 rtc_init_pit (void)
 {
 	unsigned char control;
 
-	/* Setup interval timer if /dev/rtc is being used */
+	/* Turn off RTC interrupts before /dev/rtc is initialized */
+	control = CMOS_READ(RTC_CONTROL);
+	control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
+	CMOS_WRITE(control, RTC_CONTROL);
+	(void) CMOS_READ(RTC_INTR_FLAGS);
+
+	request_region(0x40, 0x20, "timer"); /* reserve pit */
+
+	/* Setup interval timer.  */
 	outb(0x34, 0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
 	outb(LATCH & 0xff, 0x40);	/* LSB */
 	outb(LATCH >> 8, 0x40);		/* MSB */
-	request_region(0x40, 0x20, "timer"); /* reserve pit */
 
-	/* Turn off RTC interrupts before /dev/rtc is initialized */
-	control = CMOS_READ(RTC_CONTROL);
-        control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
-        CMOS_WRITE(control, RTC_CONTROL);
-        CMOS_READ(RTC_INTR_FLAGS);
-
-	init_pit_rest();
+	outb(0xb6, 0x43);	/* pit counter 2: speaker */
+	outb(0x31, 0x42);
+	outb(0x13, 0x42);
 }
 #endif
 
@@ -203,7 +188,7 @@
 {
 	unsigned char x;
 
-        /* Reset periodic interrupt frequency.  */
+	/* Reset periodic interrupt frequency.  */
 	x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
 	if (x != 0x26 && x != 0x19 && x != 0x06) {
 		printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
@@ -218,36 +203,26 @@
 		x &= ~(RTC_AIE | RTC_UIE);
 		CMOS_WRITE(x, RTC_CONTROL);
 	}
-	CMOS_READ(RTC_INTR_FLAGS);
+	(void) CMOS_READ(RTC_INTR_FLAGS);
 
 	request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */
 
-	/* Turn off the PIT.  */
-	outb(0x36, 0x43);	/* counter 0: system timer */
+	outb(0x36, 0x43);	/* pit counter 0: system timer */
 	outb(0x00, 0x40);
 	outb(0x00, 0x40);
 
-	init_pit_rest();
+	outb(0xb6, 0x43);	/* pit counter 2: speaker */
+	outb(0x31, 0x42);
+	outb(0x13, 0x42);
 }
 
-/* This probably isn't Right, but it is what the old code did.  */
-#if defined(CONFIG_RTC)
-# define init_pit	rtc_init_pit
-#else
-# define init_pit	alpha_mv.init_pit
-#endif
-
-
 void
 time_init(void)
 {
-        void (*irq_handler)(int, void *, struct pt_regs *);
+	void (*irq_handler)(int, void *, struct pt_regs *);
 	unsigned int year, mon, day, hour, min, sec, cc1, cc2;
 	unsigned long cycle_freq;
 
-	/* Initialize the timers.  */
-	init_pit();
-
 	/*
 	 * The Linux interpretation of the CMOS clock register contents:
 	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
@@ -322,8 +297,8 @@
 	state.partial_tick = 0L;
 
 	/* setup timer */ 
-        irq_handler = timer_interrupt;
-        if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
+	irq_handler = timer_interrupt;
+	if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
 		panic("Could not allocate timer IRQ!");
 }
 
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c
--- v2.2.0-pre6/linux/arch/i386/kernel/ioport.c	Thu May  7 22:51:46 1998
+++ linux/arch/i386/kernel/ioport.c	Mon Jan 11 15:02:52 1999
@@ -58,7 +58,7 @@
 
 	if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
 		return -EINVAL;
-	if (!capable(CAP_SYS_RAWIO))
+	if (turn_on && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
 	/*
 	 * If it's the first ioperm() call in this thread's lifetime, set the
@@ -91,11 +91,15 @@
 {
 	struct pt_regs * regs = (struct pt_regs *) &unused;
 	unsigned int level = regs->ebx;
+	unsigned int old = (regs->eflags >> 12) & 3;
 
 	if (level > 3)
 		return -EINVAL;
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
+	/* Trying to gain more privileges? */
+	if (level > old) {
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+	}
 	regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
 	return 0;
 }
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.2.0-pre6/linux/arch/i386/kernel/process.c	Fri Jan  8 22:36:00 1999
+++ linux/arch/i386/kernel/process.c	Sat Jan  9 00:07:41 1999
@@ -778,17 +778,19 @@
 	newsp = regs.ecx;
 	if (!newsp)
 		newsp = regs.esp;
-	return do_fork(clone_flags, newsp, &regs);
+	return do_fork(clone_flags & ~CLONE_VFORK, newsp, &regs);
 }
 
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
-	int     child;
+	int child;
+	struct semaphore sem = MUTEX_LOCKED;
 
-	child = do_fork(CLONE_VM | SIGCHLD, regs.esp, &regs);
+	current->vfork_sem = &sem;
+	child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs);
 
 	if (child > 0)
-		sleep_on(&current->vfork_sleep);
+		down(&sem);
 
 	return child;
 }
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.2.0-pre6/linux/arch/i386/kernel/ptrace.c	Fri Jan  8 22:36:01 1999
+++ linux/arch/i386/kernel/ptrace.c	Tue Jan 12 12:03:53 1999
@@ -67,33 +67,6 @@
 	return 0;
 }
 
-extern int _stext, _etext;
-static void print_child_state(struct task_struct *task)
-{
-	unsigned int * stack = (unsigned int *) task->tss.esp;
-	int count = 40;
-
-	printk("Process: %s (stack=%p, task=%p)\n", task->comm, stack, task);
-	for (;;) {
-		unsigned int data;
-		if ((unsigned int) stack < (unsigned int) task)
-			break;
-		if ((unsigned int) stack >= 2*PAGE_SIZE + (unsigned int) task)
-			break;
-		data = *stack;
-		stack++;
-		if (data < (unsigned long) &_stext)
-			continue;
-		if (data >= (unsigned long) &_etext)
-			continue;
-		printk("[<%08x>] ", data);
-		if (--count)
-			continue;
-		break;
-	}	
-	printk("\n");
-}
-
 /*
  * This routine gets a long from any process space by following the page
  * tables. NOTE! You should check that the long isn't on a page boundary,
@@ -400,7 +373,6 @@
 	read_unlock(&tasklist_lock);	/* FIXME!!! */
 	if (!child)
 		goto out;
-print_child_state(child);
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
 		goto out;
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.2.0-pre6/linux/drivers/block/floppy.c	Thu Nov 12 16:21:18 1998
+++ linux/drivers/block/floppy.c	Sun Jan 10 09:59:59 1999
@@ -4154,6 +4154,7 @@
 	fdc_state[1].address = FDC2;
 #endif
 
+	fdc = 0; /* reset fdc in case of unexpected interrupt */
 	if (floppy_grab_irq_and_dma()){
 		del_timer(&fd_timeout);
 		blk_dev[MAJOR_NR].request_fn = NULL;
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.2.0-pre6/linux/drivers/block/genhd.c	Thu Jan  7 15:11:36 1999
+++ linux/drivers/block/genhd.c	Fri Jan  8 22:54:17 1999
@@ -439,7 +439,7 @@
 #ifdef CONFIG_BSD_DISKLABEL
 	/* no bsd disklabel as a default */
 	kdev_t bsd_kdev = 0;
-	int bsd_maxpart;
+	int bsd_maxpart = BSD_MAXPARTITIONS;
 #endif
 #ifdef CONFIG_BLK_DEV_IDE
 	int tested_for_xlate = 0;
@@ -558,23 +558,15 @@
 		}
 #ifdef CONFIG_BSD_DISKLABEL
 			/* tag first disklabel for late recognition */
-		if (SYS_IND(p) == BSD_PARTITION) {
+		if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
 			printk("!");
-			if (!bsd_kdev) {
+			if (!bsd_kdev)
 				bsd_kdev = MKDEV(hd->major, minor);
-				bsd_maxpart = BSD_MAXPARTITIONS;
-			}
 		} else if (SYS_IND(p) == OPENBSD_PARTITION) {
 			printk("!");
 			if (!bsd_kdev) {
 				bsd_kdev = MKDEV(hd->major, minor);
 				bsd_maxpart = OPENBSD_MAXPARTITIONS;
-			}
-		} else if (SYS_IND(p) == NETBSD_PARTITION) {
-			printk("!");
-			if (!bsd_kdev) {
-				bsd_kdev = MKDEV(hd->major, minor);
-				bsd_maxpart = BSD_MAXPARTITIONS;
 			}
 		}
 #endif
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.2.0-pre6/linux/drivers/char/epca.c	Thu Dec 31 10:28:59 1998
+++ linux/drivers/char/epca.c	Sat Jan  9 19:16:43 1999
@@ -2363,10 +2363,10 @@
 			eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART));
 		}
 
-		/* Get the channel the event occured on */
+		/* Get the channel the event occurred on */
 		channel = eventbuf[0];
 
-		/* Get the actual event code that occured */
+		/* Get the actual event code that occurred */
 		event = eventbuf[1];
 
 		/*  ----------------------------------------------------------------
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.2.0-pre6/linux/drivers/char/lp_m68k.c	Fri Jan  1 12:58:20 1999
+++ linux/drivers/char/lp_m68k.c	Sat Jan  9 19:16:43 1999
@@ -531,7 +531,7 @@
  * (un-)register for hardware drivers
  * tab is an inititalised lp_struct, dev the desired minor
  * if dev < 0, let the driver choose the first free minor
- * if sucessful return the minor, else -1
+ * if successful return the minor, else -1
  */
 int register_parallel(struct lp_struct *tab, int dev)
 {
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.2.0-pre6/linux/drivers/char/pc_keyb.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/pc_keyb.c	Tue Jan 12 10:14:40 1999
@@ -55,6 +55,7 @@
 #endif
 
 static void kbd_write(int address, int data);
+static unsigned char handle_kbd_event(void);
 
 spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
 
@@ -101,16 +102,15 @@
 static inline void kb_wait(void)
 {
 	unsigned long timeout = KBC_TIMEOUT;
-	unsigned char status;
 
 	do {
-		status = inb_p(KBD_STATUS_REG);
-		if (status & KBD_STAT_OBF) {
-			if (status & KBD_STAT_MOUSE_OBF)
-			inb_p(KBD_DATA_REG); /* Flush. */
-		}
+		/*
+		 * "handle_kbd_event()" will handle any incoming events
+		 * while we wait - keypresses or mouse movement.
+		 */
+		unsigned char status = handle_kbd_event();
 
-		if (! (inb_p(KBD_STATUS_REG) & KBD_STAT_IBF))
+		if (! (status & KBD_STAT_IBF))
 			return;
 		mdelay(1);
 		timeout--;
@@ -256,25 +256,6 @@
 	    e0_keys[scancode - 128];
 }
 
-#if DISABLE_KBD_DURING_INTERRUPTS
-static inline void send_cmd(unsigned char c)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&kbd_controller_lock, flags);
-	kb_wait();
-	outb(c, KBD_CNTL_REG);
-	spin_unlock_irqrestore(&kbd_controller_lock, flags);
-}
-
-/* #define disable_keyboard()	do { send_cmd(KBD_CCMD_KBD_DISABLE); kb_wait(); } while (0) */
-#define disable_keyboard()	send_cmd(KBD_CCMD_KBD_DISABLE)
-#define enable_keyboard()	send_cmd(KBD_CCMD_KBD_ENABLE)
-#else
-#define disable_keyboard()	/* nothing */
-#define enable_keyboard()	/* nothing */
-#endif
-
 static int do_acknowledge(unsigned char scancode)
 {
 	if (reply_expected) {
@@ -419,16 +400,17 @@
 	    return 0200;
 }
 
-static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ * It requires that we hold the keyboard controller
+ * spinlock.
+ */
+static unsigned char handle_kbd_event(void)
 {
-	unsigned long flags;
-	unsigned char status;
-
-	disable_keyboard();
-	spin_lock_irqsave(&kbd_controller_lock, flags);
-	kbd_pt_regs = regs;
+	unsigned char status = inb(KBD_STATUS_REG);
 
-	status = inb(KBD_STATUS_REG);
 	while (status & KBD_STAT_OBF) {
 		unsigned char scancode;
 
@@ -459,8 +441,19 @@
 		status = inb(KBD_STATUS_REG);
 	}
 
+	return status;
+}
+
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	kbd_pt_regs = regs;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	handle_kbd_event();
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
-	enable_keyboard();
 }
 
 /*
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c
--- v2.2.0-pre6/linux/drivers/char/radio-aimslab.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/radio-aimslab.c	Sun Jan 10 22:28:14 1999
@@ -101,6 +101,7 @@
 		outb(0x48, io);		/* volume down but still "on"	*/
 		sleep_delay(2000000);	/* make sure it's totally down	*/
 		outb(0xd0, io);		/* volume steady, off		*/
+		dev->curvol = 0;	/* track the volume state!	*/
 		return 0;
 	}
 
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.2.0-pre6/linux/drivers/char/vt.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/char/vt.c	Sun Jan 10 22:56:43 1999
@@ -22,7 +22,6 @@
 #include <linux/malloc.h>
 #include <linux/major.h>
 #include <linux/fs.h>
-#include <linux/config.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.2.0-pre6/linux/drivers/net/3c59x.c	Fri Jan  8 22:36:06 1999
+++ linux/drivers/net/3c59x.c	Sat Jan  9 19:16:43 1999
@@ -86,9 +86,7 @@
 
 #include <linux/delay.h>
 
-#if (LINUX_VERSION_CODE >= 0x20100)
-char kernel_version[] = UTS_RELEASE;
-#else
+#if (LINUX_VERSION_CODE <= 0x20100)
 #ifndef __alpha__
 #define ioremap(a,b) \
 	(((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.2.0-pre6/linux/drivers/net/epic100.c	Fri Jan  1 12:58:20 1999
+++ linux/drivers/net/epic100.c	Sat Jan  9 19:16:43 1999
@@ -58,10 +58,8 @@
 #endif
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
@@ -77,7 +75,6 @@
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
-#include <asm/dma.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -125,11 +122,10 @@
 
 I. Board Compatibility
 
-This device driver is designed for the SMC "EPCI/100", the SMC
+This device driver is designed for the SMC "EPIC/100", the SMC
 single-chip Ethernet controllers for PCI.  This chip is used on
 the SMC EtherPower II boards.
 
-
 II. Board-specific settings
 
 PCI bus devices are configured by the system at boot time, so no jumpers
@@ -144,9 +140,10 @@
 
 IVb. References
 
-http://www.smc.com/components/catalog/smc83c170.html
+http://www.smsc.com/main/datasheets/83c171.pdf
+http://www.smsc.com/main/datasheets/83c175.pdf
 http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.national.com/pf/DP/DP83840.html
+http://www.national.com/pf/DP/DP83840A.html
 
 IVc. Errata
 
@@ -162,6 +159,7 @@
 	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
 	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
 };
+
 struct chip_info {
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, pci_flags;
@@ -221,7 +219,7 @@
 	const char *product_name;
 	struct device *next_module;
 
-	/* Rx and Rx rings here so that they remain paragraph aligned. */
+	/* Tx and Rx rings here so that they remain paragraph aligned. */
 	struct epic_rx_desc rx_ring[RX_RING_SIZE];
 	struct epic_tx_desc tx_ring[TX_RING_SIZE];
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
@@ -930,7 +928,7 @@
 #if defined(__i386__)
 	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
 	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+		printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n",
 			   dev->name);
 		dev->interrupt = 0;	/* Avoid halting machine. */
 		return;
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.2.0-pre6/linux/drivers/net/hp100.c	Fri Jan  8 22:36:07 1999
+++ linux/drivers/net/hp100.c	Mon Jan 11 10:55:29 1999
@@ -2798,7 +2798,7 @@
     if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break;
   } while (time_after(time, jiffies));
 
-  if ( time_before_eq(jiffies, time) )       /* no signal->no logout */
+  if ( time_after_eq(jiffies, time) )       /* no signal->no logout */
     return 0;
 
   /* Drop the VG Link by clearing the link up cmd and load addr.*/
@@ -2813,7 +2813,7 @@
   } while(time_after(time, jiffies));
 
 #ifdef HP100_DEBUG
-  if (time_before_eq(jiffies, time))
+  if (time_after_eq(jiffies, time))
     printk("hp100: %s: down_vg_link: Link does not go down?\n", dev->name);
 #endif
 
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.2.0-pre6/linux/drivers/net/tulip.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/net/tulip.c	Sun Jan 10 09:59:59 1999
@@ -104,9 +104,6 @@
 #define NEW_MULTICAST
 #include <linux/delay.h>
 #endif
-#if (LINUX_VERSION_CODE >= 0x20100)
-char kernel_version[] = UTS_RELEASE;
-#endif
 #ifdef SA_SHIRQ
 #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
 #else
@@ -465,7 +462,7 @@
 #endif
 	for (;pci_index < 0xff; pci_index++) {
 		u16 vendor, device, pci_command, new_command;
-		u32 pci_ioaddr;
+		unsigned long pci_ioaddr = 0;
 		int chip_idx = 0;
 
 		if (pcibios_find_class
@@ -503,7 +500,7 @@
 		pci_ioaddr &= ~3;
 
 		if (tulip_debug > 2)
-			printk(KERN_DEBUG "Found %s at I/O %#x.\n",
+			printk(KERN_DEBUG "Found %s at I/O %#lx.\n",
 				   tulip_tbl[chip_idx].chip_name, pci_ioaddr);
 
 		if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size))
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c
--- v2.2.0-pre6/linux/drivers/scsi/AM53C974.c	Sun Jun  7 11:16:33 1998
+++ linux/drivers/scsi/AM53C974.c	Mon Jan 11 13:46:47 1999
@@ -756,7 +756,7 @@
 		 (search->irq != instance->irq) || (search == instance));
 	     search = search->next);
 	if (!search) {
-		if (request_irq(instance->irq, do_AM53C974_intr, SA_INTERRUPT, "AM53C974", NULL)) {
+		if (request_irq(instance->irq, do_AM53C974_intr, SA_SHIRQ, "AM53C974", instance)) {
 			printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq);
 			scsi_unregister(instance);
 			return 0;
@@ -2458,7 +2458,7 @@
  */
 int AM53C974_release(struct Scsi_Host *shp)
 {
-	free_irq(shp->irq, NULL);
+	free_irq(shp->irq, shp);
 	scsi_unregister(shp);
 	return 0;
 }
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.2.0-pre6/linux/drivers/scsi/aha152x.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/scsi/aha152x.c	Sat Jan  9 19:16:43 1999
@@ -247,7 +247,7 @@
  C/H/S addressing.
 
  The number of cylinders/heads/sectors is called geometry and is required
- as base for requests in C/H/S adressing.  SCSI only knows about the
+ as base for requests in C/H/S addressing.  SCSI only knows about the
  total capacity of disks in blocks (sectors).
 
  Therefore the SCSI BIOS/DOS driver has to calculate a logical/virtual
@@ -276,7 +276,7 @@
  extended translation.  This means that the BIOS uses 255 for heads,
  63 for sectors and then divides the capacity of the disk by 255*63
  (about 8 MB), as soon it sees a disk greater than 1 GB.  That results
- in a maximum of about 8 GB adressable diskspace in the partition table
+ in a maximum of about 8 GB addressable diskspace in the partition table
  (but there are already bigger disks out there today).
 
  To make it even more complicated the translation mode might/might
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.2.0-pre6/linux/drivers/scsi/aic7xxx.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/scsi/aic7xxx.c	Sun Jan 10 12:42:42 1999
@@ -354,7 +354,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.9"
+#define AIC7XXX_C_VERSION  "5.1.10"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -9116,19 +9116,22 @@
           {
             case AHC_AIC7870: /* 3840 / 3985 */
             case AHC_AIC7880: /* 3840 UW / 3985 UW */
-              switch(PCI_SLOT(temp_p->pci_device_fn))
+              if(temp_p->flags & AHC_MULTI_CHANNEL)
               {
-                case 5:
-                  temp_p->flags |= AHC_CHNLB;
-                  break;
-                case 8:
-                  temp_p->flags |= AHC_CHNLB;
-                  break;
-                case 12:
-                  temp_p->flags |= AHC_CHNLC;
-                  break;
-                default:
-                  break;
+                switch(PCI_SLOT(temp_p->pci_device_fn))
+                {
+                  case 5:
+                    temp_p->flags |= AHC_CHNLB;
+                    break;
+                  case 8:
+                    temp_p->flags |= AHC_CHNLB;
+                    break;
+                  case 12:
+                    temp_p->flags |= AHC_CHNLC;
+                    break;
+                  default:
+                    break;
+                }
               }
               break;
 
@@ -10999,11 +11002,13 @@
        * entirely and avoids getting a bogus dead command back through the
        * mid-level code due to too many retries.
        */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132)
       if ( flags & SCSI_RESET_SYNCHRONOUS )
       {
         cmd->result = DID_BUS_BUSY << 16;
         cmd->done(cmd);
       }
+#endif
       p->flags &= ~AHC_IN_RESET;
       /*
        * We can't rely on run_waiting_queues to unpause the sequencer for
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/atari_dma_emul.c linux/drivers/scsi/atari_dma_emul.c
--- v2.2.0-pre6/linux/drivers/scsi/atari_dma_emul.c	Thu Mar 26 15:57:03 1998
+++ linux/drivers/scsi/atari_dma_emul.c	Sat Jan  9 19:16:43 1999
@@ -429,7 +429,7 @@
 	if (eff_addr == &hades_psdm_reg)
 	{
 		/*
-		 * Bus error occured while reading the pseudo
+		 * Bus error occurred while reading the pseudo
 		 * DMA register. Time out.
 		 */
 
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- v2.2.0-pre6/linux/drivers/scsi/gdth.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/scsi/gdth.c	Mon Jan 11 10:17:20 1999
@@ -2,7 +2,7 @@
  * GDT ISA/EISA/PCI Disk Array Controller driver for Linux              *
  *                                                                      *
  * gdth.c                                                               *
- * Copyright (C) 1995-97 ICP vortex Computersysteme GmbH, Achim Leubner *
+ * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner *
  *                                                                      *
  * <achim@vortex.de>                                                    *
  *                                                                      *
@@ -20,27 +20,49 @@
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Tested with Linux 1.2.13, ..., 2.1.61                                *
+ * Tested with Linux 1.2.13, ..., 2.1.131                               *
  *                                                                      *
  * $Log: gdth.c,v $
- * Revision 1.3  1998/02/25 23:52:32  ecd
- * Final round of PCI device driver patches by Martin Mares.
+ * Revision 1.17  1998/12/17 15:58:11  achim
+ * Command line parameters implemented
+ * Changes for Alpha platforms
+ * PCI controller scan changed
+ * SMP support improved (spin_lock_irqsave(),...)
+ * New async. events, new scan/reserve commands included
  *
- * 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.16  1998/09/28 16:08:46  achim
+ * GDT_PCIMPR: DPMEM remapping, if required
+ * mdelay() added
  *
- * 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.15  1998/06/03 14:54:06  achim
+ * gdth_delay(), gdth_flush() implemented
+ * Bugfix: gdth_release() changed
+ *
+ * Revision 1.14  1998/05/22 10:01:17  achim
+ * mj: pcibios_strerror() removed
+ * Improved SMP support (if version >= 2.1.95)
+ * gdth_halt(): halt_called flag added (if version < 2.1)
+ *
+ * Revision 1.13  1998/04/16 09:14:57  achim
+ * Reserve drives (for raw service) implemented
+ * New error handling code enabled
+ * Get controller name from board_info() IOCTL
+ * Final round of PCI device driver patches by Martin Mares
+ *
+ * Revision 1.12  1998/03/03 09:32:37  achim
+ * Fibre channel controller support added
+ *
+ * Revision 1.11  1998/01/27 16:19:14  achim
+ * SA_SHIRQ added
+ * add_timer()/del_timer() instead of GDTH_TIMER
+ * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
+ * New error handling included
  *
  * Revision 1.10  1997/10/31 12:29:57  achim
  * Read heads/sectors from host drive
  *
  * Revision 1.9  1997/09/04 10:07:25  achim
- * IO-mapping with virt_to_bus(), readb(), writeb(), ...
+ * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
  * register_reboot_notifier() to get a notify on shutdown used
  *
  * Revision 1.8  1997/04/02 12:14:30  achim
@@ -72,9 +94,49 @@
  * Revision 1.1  1996/04/11 07:35:57  achim
  * Initial revision
  *
- *
- * $Id: gdth.c,v 1.4 1998/04/15 14:35:26 mj Exp $ 
  ************************************************************************/
+#ident "$Id: gdth.c,v 1.17 1998/12/17 15:58:11 achim Exp $" 
+
+/* All GDT Disk Array Controllers are fully supported by this driver.
+ * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
+ * PCI Fibre Channel Disk Array Controllers. See gdth.h for a complete
+ * list of all controller types.
+ * 
+ * If you have one or more GDT3000/3020 EISA controllers with 
+ * controller BIOS disabled, you have to set the IRQ values with the 
+ * command line option "gdth=irq1,irq2,...", where the irq1,irq2,... are
+ * the IRQ values for the EISA controllers.
+ * 
+ * After the optional list of IRQ values, other possible 
+ * command line options are:
+ * disable:Y                    disable driver
+ * disable:N                    enable driver
+ * reserve_mode:0               reserve no drives for the raw service
+ * reserve_mode:1               reserve all not init., removable drives
+ * reserve_mode:2               reserve all not init. drives
+ * reserve_list:h,b,t,l,h,b,t,l,...     reserve particular drive(s) with 
+ *                              h- controller no., b- channel no., 
+ *                              t- target ID, l- LUN
+ * reverse_scan:Y               reverse scan order for PCI controllers         
+ * reverse_scan:N               scan PCI controllers like BIOS
+ * max_ids:x                    x - target ID count per channel (1..MAXID)
+ * rescan:Y                     rescan all channels/IDs 
+ * rescan:N                     use all devices found until now
+ *
+ * The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
+ *                        max_ids:127,rescan:N".
+ * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
+ * 
+ * When loading the gdth driver as a module, the same options are available. 
+ * You can set the IRQs with "IRQ=...". However, the syntax to specify the
+ * options changes slightly. You must replace all ',' between options 
+ * with ' ' and all ':' with '=' and you must use 
+ * '1' in place of 'Y' and '0' in place of 'N'.
+ * 
+ * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
+ *                         max_ids=127 rescan=0"
+ * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
+ */
 
 #ifdef MODULE
 #include <linux/module.h>
@@ -85,6 +147,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/string.h>
+#include <linux/ctype.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -101,7 +164,9 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#if LINUX_VERSION_CODE >= 0x02015F
 #include <asm/spinlock.h>
+#endif
 
 #if LINUX_VERSION_CODE >= 0x010300
 #include <linux/blk.h>
@@ -116,33 +181,34 @@
 
 #if LINUX_VERSION_CODE >= 0x010346
 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
 #else
 static void gdth_interrupt(int irq,struct pt_regs *regs);
 #endif
 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
 static int gdth_async_event(int hanum,int service);
+static void gdth_log_event(gdth_evt_data *dvr);
 
 static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
 static void gdth_next(int hanum);
 static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
-static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
-static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
-                                      gdth_evt_data *evt);
-static int gdth_read_event(int handle, gdth_evt_str *estr);
-static void gdth_readapp_event(unchar application, gdth_evt_str *estr);
+static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp);
+static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
+                                      ushort idx, gdth_evt_data *evt);
+static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
+static void gdth_readapp_event(gdth_ha_str *ha, unchar application, 
+                               gdth_evt_str *estr);
 static void gdth_clear_events(void);
 
 static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
-static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
-                                   unchar b,ulong *flags);
+static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
 static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
 
 static int gdth_search_eisa(ushort eisa_adr);
-static int gdth_search_isa(ulong bios_adr);
-static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr);
+static int gdth_search_isa(ulong32 bios_adr);
+static int gdth_search_pci(gdth_pci_str *pcistr);
+static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt);
 static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
-static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha);
+static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha);
 static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
 
 static void gdth_enable_int(int hanum);
@@ -150,38 +216,28 @@
 static int gdth_test_busy(int hanum);
 static int gdth_get_cmd_index(int hanum);
 static void gdth_release_event(int hanum);
-static int gdth_wait(int hanum,int index,ulong time);
-static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
-                             ulong p2,ulong p3);
+static int gdth_wait(int hanum,int index,ulong32 time);
+static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
+                             ulong32 p2,ulong32 p3);
 static int gdth_search_drives(int hanum);
 
 static void *gdth_mmap(ulong paddr, ulong size);
 static void gdth_munmap(void *addr);
 
 static const char *gdth_ctr_name(int hanum);
+
+static void gdth_flush(int hanum);
 #if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
 #else
+static int halt_called = FALSE;
 void gdth_halt(void);
 #endif
 
 #ifdef DEBUG_GDTH
 static unchar   DebugState = DEBUG_GDTH;
 extern int sys_syslog(int,char*,int);
-#define LOGEN           sys_syslog(7,NULL,0);
-#define WAITSEC(a)      mdelay((a)*1000)
-
-#ifdef SLOWMOTION_GDTH
-#define SLOWM   WAITSEC(2)  
-#undef  INIT_RETRIES
-#undef  INIT_TIMEOUT
-#undef  POLL_TIMEOUT
-#define INIT_RETRIES    15
-#define INIT_TIMEOUT    150
-#define POLL_TIMEOUT    150
-#else
-#define SLOWM
-#endif
+#define LOGEN sys_syslog(7,NULL,0)
 
 #ifdef __SERIAL__
 #define MAX_SERBUF 160
@@ -245,14 +301,14 @@
     return i;
 }
 
-#define TRACE(a)    {if (DebugState==1) {ser_printk a; SLOWM}}
-#define TRACE2(a)   {if (DebugState==1 || DebugState==2) {ser_printk a; SLOWM}}
-#define TRACE3(a)   {if (DebugState!=0) {ser_printk a; SLOWM}}
+#define TRACE(a)    {if (DebugState==1) {ser_printk a;}}
+#define TRACE2(a)   {if (DebugState==1 || DebugState==2) {ser_printk a;}}
+#define TRACE3(a)   {if (DebugState!=0) {ser_printk a;}}
 
 #else /* !__SERIAL__ */
-#define TRACE(a)    {if (DebugState==1) {LOGEN;printk a; SLOWM}}
-#define TRACE2(a)   {if (DebugState==1 || DebugState==2) {LOGEN;printk a; SLOWM}}
-#define TRACE3(a)   {if (DebugState!=0) {LOGEN;printk a; SLOWM}}
+#define TRACE(a)    {if (DebugState==1) {LOGEN;printk a;}}
+#define TRACE2(a)   {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}}
+#define TRACE3(a)   {if (DebugState!=0) {LOGEN;printk a;}}
 #endif
 
 #else /* !DEBUG */
@@ -262,70 +318,77 @@
 #endif
 
 #ifdef GDTH_STATISTICS
-static ulong max_rq=0, max_index=0, max_sg=0;
-static ulong act_ints=0, act_ios=0, act_stats=0, act_rq=0;
-#define GDTH_TIMER      31                      /* see linux/timer.h ! */
+static ulong32 max_rq=0, max_index=0, max_sg=0;
+static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0;
+static struct timer_list gdth_timer;
 #endif
 
 #define PTR2USHORT(a)   (ushort)(ulong)(a)
-#define JIFFYWAIT(a)    {ulong gdtjf;gdtjf=jiffies+(a);while(time_before(jiffies,gdtjf));}
 #define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)   
 #define INDEX_OK(i,t)   ((i)<sizeof(t)/sizeof((t)[0]))
 
 #define NUMDATA(a)      ( (gdth_num_str  *)((a)->hostdata))
 #define HADATA(a)       (&((gdth_ext_str *)((a)->hostdata))->haext)
 #define CMDDATA(a)      (&((gdth_ext_str *)((a)->hostdata))->cmdext)
-#define DMADATA(a)      (&((gdth_ext_str *)((a)->hostdata))->dmaext)
 
 
 #if LINUX_VERSION_CODE < 0x010300
 static void *gdth_mmap(ulong paddr, ulong size) 
 {
     if (paddr >= high_memory)
-	return NULL; 
+        return NULL; 
     else
-	return (void *)paddr;
+        return (void *)paddr;
 }
 static void gdth_munmap(void *addr) 
 {
 }
-inline ulong virt_to_phys(volatile void *addr)
+inline ulong32 virt_to_phys(volatile void *addr)
 {
-    return (ulong)addr;
+    return (ulong32)addr;
 }
-inline void *phys_to_virt(ulong addr)
+inline void *phys_to_virt(ulong32 addr)
 {
     return (void *)addr;
 }
-#define virt_to_bus		virt_to_phys
-#define bus_to_virt		phys_to_virt
-#define readb(addr)		(*(volatile unchar *)(addr))
-#define readw(addr)		(*(volatile ushort *)(addr))
-#define readl(addr)		(*(volatile ulong *)(addr))
-#define writeb(b,addr)		(*(volatile unchar *)(addr) = (b))
-#define writew(b,addr)		(*(volatile ushort *)(addr) = (b))
-#define writel(b,addr)		(*(volatile ulong *)(addr) = (b))
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
+#define virt_to_bus             virt_to_phys
+#define bus_to_virt             phys_to_virt
+#define gdth_readb(addr)        (*(volatile unchar *)(addr))
+#define gdth_readw(addr)        (*(volatile ushort *)(addr))
+#define gdth_readl(addr)        (*(volatile ulong32 *)(addr))
+#define gdth_writeb(b,addr)     (*(volatile unchar *)(addr) = (b))
+#define gdth_writew(b,addr)     (*(volatile ushort *)(addr) = (b))
+#define gdth_writel(b,addr)     (*(volatile ulong32 *)(addr) = (b))
+#define memset_io(a,b,c)        memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)    memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)      memcpy((void *)(a),(b),(c))
+
+#define PCI_SLOT(devfn)         ((devfn >> 3) & 0x1f)
 
 #elif LINUX_VERSION_CODE < 0x020100
 static int remapped = FALSE;
 static void *gdth_mmap(ulong paddr, ulong size) 
 {
     if ( paddr >= high_memory) {
-	remapped = TRUE;
-	return vremap(paddr, size);
+        remapped = TRUE;
+        return vremap(paddr, size);
     } else {
-	return (void *)paddr; 
+        return (void *)paddr; 
     }
 }
 static void gdth_munmap(void *addr) 
 {
     if (remapped)
-	vfree(addr);
+        vfree(addr);
     remapped = FALSE;
 }
+#define gdth_readb(addr)        readb((ulong)(addr))
+#define gdth_readw(addr)        readw((ulong)(addr))
+#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
+#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
+#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
+#define gdth_writel(b,addr)     writel((b),(ulong)(addr))
+
 #else
 static void *gdth_mmap(ulong paddr, ulong size) 
 { 
@@ -335,6 +398,12 @@
 {
     return iounmap(addr);
 }
+#define gdth_readb(addr)        readb((ulong)(addr))
+#define gdth_readw(addr)        readw((ulong)(addr))
+#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
+#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
+#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
+#define gdth_writel(b,addr)     writel((b),(ulong)(addr))
 #endif
 
 
@@ -345,19 +414,14 @@
 static int      wait_index,wait_hanum;                  /* gdth_wait() */
 static int      gdth_ctr_count  = 0;                    /* controller count */
 static int      gdth_ctr_vcount = 0;                    /* virt. ctr. count */
+static int      gdth_ctr_released = 0;                  /* gdth_release() */
 static struct Scsi_Host *gdth_ctr_tab[MAXHA];           /* controller table */
 static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS];   /* virt. ctr. table */
 static unchar   gdth_write_through = FALSE;             /* write through */
-static char *gdth_ioctl_tab[4][MAXHA];                  /* ioctl buffer */
 static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
 static int elastidx;
 static int eoldidx;
 
-static struct {
-    Scsi_Cmnd   *cmnd;                          /* pending request */
-    ushort      service;                        /* service */
-} gdth_cmd_tab[GDTH_MAXCMDS][MAXHA];            /* table of pend. requests */
-
 #define DIN     1                               /* IN data direction */
 #define DOU     2                               /* OUT data direction */
 #define DNO     DIN                             /* no data transfer */
@@ -381,17 +445,34 @@
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
 };
 
-/* LILO params: gdth=<IRQ>
- *
- * Where: <IRQ> is any of the valid IRQs for EISA controllers (10,11,12,14)
- * Sets the IRQ of the GDT3000/3020 EISA controller to this value,
- * if the IRQ can not automat. detect (controller BIOS disabled)
- * See gdth_init_eisa() 
- *
- * You can use the command line gdth=0 to disable the driver 
- */
-static unchar irqs[MAXHA] = {0xff};
-static unchar disable_gdth_scan = FALSE;
+/* __initfunc, __initdata macros */
+#if LINUX_VERSION_CODE >= 0x020126
+#include <linux/init.h>
+#else
+#define __initfunc(A) A
+#define __initdata
+#define __init
+#endif
+
+#if LINUX_VERSION_CODE >= 0x02015F
+#define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
+#define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
+#define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
+
+#define GDTH_LOCK_SCSI_DONE(flags)      spin_lock_irqsave(&io_request_lock,flags)
+#define GDTH_UNLOCK_SCSI_DONE(flags)    spin_unlock_irqrestore(&io_request_lock,flags)
+#define GDTH_LOCK_SCSI_DOCMD()          spin_lock_irq(&io_request_lock)
+#define GDTH_UNLOCK_SCSI_DOCMD()        spin_unlock_irq(&io_request_lock)
+#else
+#define GDTH_INIT_LOCK_HA(ha)           do {} while (0)
+#define GDTH_LOCK_HA(ha,flags)          do {save_flags(flags); cli();} while (0)
+#define GDTH_UNLOCK_HA(ha,flags)        do {restore_flags(flags);} while (0)
+
+#define GDTH_LOCK_SCSI_DONE(flags)      do {} while (0)
+#define GDTH_UNLOCK_SCSI_DONE(flags)    do {} while (0)
+#define GDTH_LOCK_SCSI_DOCMD()          do {} while (0)
+#define GDTH_UNLOCK_SCSI_DOCMD()        do {} while (0)
+#endif
 
 /* /proc support */
 #if LINUX_VERSION_CODE >= 0x010300
@@ -411,11 +492,63 @@
 };
 #endif
 
+
+/* LILO and modprobe/insmod parameters */
+/* IRQ list for GDT3000/3020 EISA controllers */
+static int irq[MAXHA] __initdata = 
+{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+/* disable driver flag */
+static int disable __initdata = 0;
+/* reserve flag */
+static int reserve_mode __initdata = 1;                  
+/* reserve list */
+static int reserve_list[MAX_RES_ARGS] __initdata = 
+{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+/* scan order for PCI controllers */
+static int reverse_scan __initdata = 0;
+/* max. IDs per channel */
+static int max_ids = MAXID;
+/* rescan all IDs */
+static int rescan = 0;
+
+#ifdef MODULE
+#if LINUX_VERSION_CODE >= 0x02011A
+/* parameters for modprobe/insmod */
+MODULE_PARM(irq, "i");
+MODULE_PARM(disable, "i");
+MODULE_PARM(reserve_mode, "i");
+MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
+MODULE_PARM(reverse_scan, "i");
+MODULE_PARM(max_ids, "i");
+MODULE_PARM(rescan, "i");
+MODULE_AUTHOR("Achim Leubner");
+#endif
+#endif
+
+
+static void gdth_delay(int milliseconds)
+{
+    if (milliseconds == 0) {
+        udelay(1);
+    } else {
+#if LINUX_VERSION_CODE >= 0x020168
+        mdelay(milliseconds);
+#else
+        int i;
+        for (i = 0; i < milliseconds; ++i) 
+            udelay(1000);
+#endif
+    }
+}
+
 /* controller search and initialization functions */
 
-static int gdth_search_eisa(ushort eisa_adr)
+__initfunc (static int gdth_search_eisa(ushort eisa_adr))
 {
-    ulong id;
+    ulong32 id;
     
     TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr));
     id = inl(eisa_adr+ID0REG);
@@ -431,99 +564,181 @@
 }
 
 
-static int gdth_search_isa(ulong bios_adr)
+__initfunc (static int gdth_search_isa(ulong32 bios_adr))
 {
     void *addr;
-    ulong id;
+    ulong32 id;
 
-    TRACE(("gdth_search_isa() bios adr. %lx\n",bios_adr));
-    if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong))) != NULL) {
-	id = readl(addr);
-	gdth_munmap(addr);
-	if (id == GDT2_ID)                          /* GDT2000 */
-	    return 1;
+    TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
+    if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
+        id = gdth_readl(addr);
+        gdth_munmap(addr);
+        if (id == GDT2_ID)                          /* GDT2000 */
+            return 1;
     }
     return 0;
 }
 
 
-static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr)
+__initfunc (static int gdth_search_pci(gdth_pci_str *pcistr))
 {
+    ulong32 base0, base1, base2;
+    ushort device_id, cnt;
+#if LINUX_VERSION_CODE >= 0x2015C
+    struct pci_dev *pdev;
+#else
     int error;
-    ulong base0,base1,base2;
-
-    TRACE(("gdth_search_pci() device_id %d, index %d\n",
-                 device_id,index));
-
-    if (!pci_present())
-        return 0;
-
-    if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index,
-                             &pcistr->bus,&pcistr->device_fn))
-        return 0;
+    ushort idx;
+#endif
+    
+    TRACE(("gdth_search_pci()\n"));
 
-    /* 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 %d reading configuration space", error);
-		return -1;
-		}
-	pcistr->irq = pdev->irq;
-    }
-#else
+    cnt = 0;
+    for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; 
+         ++device_id) {
+        if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
+            device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
+            continue;
+#if LINUX_VERSION_CODE >= 0x2015C
+        pdev = NULL;
+        while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) 
+               != NULL) {
+            if (cnt >= MAXHA)
+                return cnt;
+            /* GDT PCI controller found, resources are already in pdev */
+            pcistr[cnt].pdev = pdev;
+            pcistr[cnt].device_id = device_id;
+            pcistr[cnt].bus = pdev->bus->number;
+            pcistr[cnt].device_fn = pdev->devfn;
+            pcistr[cnt].irq = pdev->irq;
+            base0 = pdev->base_address[0];
+            base1 = pdev->base_address[1];
+            base2 = pdev->base_address[2];
+            if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
+                device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
+                if ((base0 & PCI_BASE_ADDRESS_SPACE) != 
+                    PCI_BASE_ADDRESS_SPACE_MEMORY)
+                    continue;
+                pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+            } else {                                    /* GDT6110, GDT6120, .. */
+                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
+                    (base2 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
+                    (base1 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_IO)
+                    continue;
+                pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
+            }
+            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
+                    pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
+                    pcistr[cnt].irq, pcistr[cnt].dpmem));
+            cnt++;
+        }       
+#else   
+        idx = 0;
+        while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++,
+                                    &pcistr[cnt].bus,&pcistr[cnt].device_fn)) {
+            if (cnt >= MAXHA)
+                return cnt;
+            /* GDT PCI ctr. found, now read resources from config space */
 #if LINUX_VERSION_CODE >= 0x010300
 #define GDTH_BASEP      (int *)
 #else
 #define GDTH_BASEP
 #endif
-    if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_0,
-                                           GDTH_BASEP&base0)) ||
-        (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_1,
-                                           GDTH_BASEP&base1)) ||
-        (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_2,
-                                           GDTH_BASEP&base2)) ||
-        (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
-                                           PCI_ROM_ADDRESS,
-                                           GDTH_BASEP&pcistr->bios)) ||
-        (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn,
-                                          PCI_INTERRUPT_LINE,&pcistr->irq))) {
-        printk("GDT-PCI: error %d reading configuration space", error);
-        return -1;
-    }
+            if ((error = pcibios_read_config_dword(pcistr[cnt].bus,
+                                                   pcistr[cnt].device_fn,
+                                                   PCI_BASE_ADDRESS_0,
+                                                   GDTH_BASEP&base0)) ||
+                (error = pcibios_read_config_dword(pcistr[cnt].bus,
+                                                   pcistr[cnt].device_fn,
+                                                   PCI_BASE_ADDRESS_1,
+                                                   GDTH_BASEP&base1)) ||
+                (error = pcibios_read_config_dword(pcistr[cnt].bus,
+                                                   pcistr[cnt].device_fn,
+                                                   PCI_BASE_ADDRESS_2,
+                                                   GDTH_BASEP&base2)) ||
+                (error = pcibios_read_config_byte(pcistr[cnt].bus,
+                                                  pcistr[cnt].device_fn,
+                                                  PCI_INTERRUPT_LINE,
+                                                  &pcistr[cnt].irq))) {
+                printk("GDT-PCI: error %d reading configuration space", error);
+                continue;
+            }
+            pcistr[cnt].device_id = device_id;
+            if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
+                device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
+                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY)
+                    continue;
+                pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+            } else {                                    /* GDT6110, GDT6120, .. */
+                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
+                    (base2 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
+                    (base1 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_IO)
+                    continue;
+                pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
+            }
+            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
+                    pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
+                    pcistr[cnt].irq, pcistr[cnt].dpmem));
+            cnt++;
+        }
 #endif
+    }   
+    return cnt;
+}
 
-    pcistr->device_id = device_id;
-    if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000 or GDT6000B */
-        device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
-        if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY)
-            return -1;
-        pcistr->dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-    } else {                                    /* GDT6110, GDT6120, .. */
-        if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
-            (base2 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
-            (base1 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO)
-            return -1;
-        pcistr->dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
-        pcistr->io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-        pcistr->io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
-    }
-    return 1;
+
+__initfunc (static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
+{    
+    gdth_pci_str temp;
+    int i, changed;
+    
+    TRACE(("gdth_sort_pci() cnt %d\n",cnt));
+    if (cnt == 0)
+        return;
+
+    do {
+        changed = FALSE;
+        for (i = 0; i < cnt-1; ++i) {
+            if (!reverse_scan) {
+                if ((pcistr[i].bus > pcistr[i+1].bus) ||
+                    (pcistr[i].bus == pcistr[i+1].bus &&
+                     PCI_SLOT(pcistr[i].device_fn) > 
+                     PCI_SLOT(pcistr[i+1].device_fn))) {
+                    temp = pcistr[i];
+                    pcistr[i] = pcistr[i+1];
+                    pcistr[i+1] = temp;
+                    changed = TRUE;
+                }
+            } else {
+                if ((pcistr[i].bus < pcistr[i+1].bus) ||
+                    (pcistr[i].bus == pcistr[i+1].bus &&
+                     PCI_SLOT(pcistr[i].device_fn) < 
+                     PCI_SLOT(pcistr[i+1].device_fn))) {
+                    temp = pcistr[i];
+                    pcistr[i] = pcistr[i+1];
+                    pcistr[i+1] = temp;
+                    changed = TRUE;
+                }
+            }
+        }
+    } while (changed);
 }
 
 
-static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
+__initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
 {
-    ulong retries,id;
+    ulong32 retries,id;
     unchar prot_ver,eisacf,i,irq_found;
 
     TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr));
@@ -535,14 +750,14 @@
     
     outb(0xff,eisa_adr+LDOORREG);
     retries = INIT_RETRIES;
-    JIFFYWAIT(2);
+    gdth_delay(20);
     while (inb(eisa_adr+EDOORREG) != 0xff) {
         if (--retries == 0) {
             printk("GDT-EISA: Initialization error (DEINIT failed)\n");
             return 0;
         }
-        mdelay(1);
-        TRACE2(("wait for DEINIT: retries=%ld\n",retries));
+        gdth_delay(1);
+        TRACE2(("wait for DEINIT: retries=%d\n",retries));
     }
     prot_ver = inb(eisa_adr+MAILBOXREG);
     outb(0xff,eisa_adr+EDOORREG);
@@ -551,7 +766,7 @@
         return 0;
     }
     ha->bmic = eisa_adr;
-    ha->brd_phys = (ulong)eisa_adr >> 12;
+    ha->brd_phys = (ulong32)eisa_adr >> 12;
 
     outl(0,eisa_adr+MAILBOXREG);
     outl(0,eisa_adr+MAILBOXREG+4);
@@ -565,76 +780,82 @@
         outl(1,eisa_adr+MAILBOXREG+8);
         outb(0xfe,eisa_adr+LDOORREG);
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
+        gdth_delay(20);
         while (inb(eisa_adr+EDOORREG) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-EISA: Initialization error (get IRQ failed)\n");
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
         ha->irq = inb(eisa_adr+MAILBOXREG);
         outb(0xff,eisa_adr+EDOORREG);
         TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq));
-	/* check the result */
-	if (ha->irq == 0) {
-	    TRACE2(("Unknown IRQ, check IRQ table from cmd line !\n"));
-	    for (i=0,irq_found=FALSE; i<MAXHA && irqs[i]!=0xff; ++i) {
-		if (irqs[i]!=0) {
-		    irq_found=TRUE;
-		    break;
-		}
-	    }
-	    if (irq_found) {
-		ha->irq = irqs[i];
-		irqs[i] = 0;
-		printk("GDT-EISA: Can not detect controller IRQ,\n");
-		printk("Use IRQ setting from command line (IRQ = %d)\n",
-		       ha->irq);
-	    } else {
-		printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
-		printk("the controller BIOS or use command line parameters\n");
-		return 0;
-	    }
-	}
+        /* check the result */
+        if (ha->irq == 0) {
+                TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n"));
+                for (i = 0, irq_found = FALSE; 
+                     i < MAXHA && irq[i] != 0xff; ++i) {
+                if (irq[i]==10 || irq[i]==11 || irq[i]==12 || irq[i]==14) {
+                    irq_found = TRUE;
+                    break;
+                }
+                }
+            if (irq_found) {
+                ha->irq = irq[i];
+                irq[i] = 0;
+                printk("GDT-EISA: Can not detect controller IRQ,\n");
+                printk("Use IRQ setting from command line (IRQ = %d)\n",
+                       ha->irq);
+            } else {
+                printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
+                printk("the controller BIOS or use command line parameters\n");
+                return 0;
+            }
+        }
     } else {
         eisacf = inb(eisa_adr+EISAREG) & 7;
         if (eisacf > 4)                         /* level triggered */
             eisacf -= 4;
         ha->irq = gdth_irq_tab[eisacf];
         ha->type = GDT_EISA;
-        ha->stype= id;
+        ha->stype = id;
     }
     return 1;
 }
 
        
-static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha)
+__initfunc (static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
 {
     register gdt2_dpram_str *dp2_ptr;
     int i;
     unchar irq_drq,prot_ver;
-    ulong retries;
+    ulong32 retries;
 
-    TRACE(("gdth_init_isa() bios adr. %lx\n",bios_adr));
+    TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr));
 
     ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str));
     if (ha->brd == NULL) {
-	printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
-	return 0;
+        printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
+        return 0;
     }
     dp2_ptr = (gdt2_dpram_str *)ha->brd;
-    writeb(1, &dp2_ptr->io.memlock);			/* switch off write protection */
+    gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
     /* reset interface area */
     memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
+    if (gdth_readl(&dp2_ptr->u) != 0) {
+        printk("GDT-PCI: Initialization error (DPMEM write error)\n");
+        gdth_munmap(ha->brd);
+        return 0;
+    }
 
     /* disable board interrupts, read DRQ and IRQ */
-    writeb(0xff, &dp2_ptr->io.irqdel);
-    writeb(0x00, &dp2_ptr->io.irqen);
-    writeb(0x00, &dp2_ptr->u.ic.S_Status);
-    writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
+    gdth_writeb(0xff, &dp2_ptr->io.irqdel);
+    gdth_writeb(0x00, &dp2_ptr->io.irqen);
+    gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status);
+    gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
 
-    irq_drq = readb(&dp2_ptr->io.rq);
+    irq_drq = gdth_readb(&dp2_ptr->io.rq);
     for (i=0; i<3; ++i) {
         if ((irq_drq & 1)==0)
             break;
@@ -642,7 +863,7 @@
     }
     ha->drq = gdth_drq_tab[i];
 
-    irq_drq = readb(&dp2_ptr->io.rq) >> 3;
+    irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3;
     for (i=1; i<5; ++i) {
         if ((irq_drq & 1)==0)
             break;
@@ -651,25 +872,25 @@
     ha->irq = gdth_irq_tab[i];
 
     /* deinitialize services */
-    writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
-    writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
-    writeb(0, &dp2_ptr->io.event);
+    gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
+    gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
+    gdth_writeb(0, &dp2_ptr->io.event);
     retries = INIT_RETRIES;
-    JIFFYWAIT(2);
-    while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
+    gdth_delay(20);
+    while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error (DEINIT failed)\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
-        mdelay(1);
+        gdth_delay(1);
     }
-    prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]);
-    writeb(0, &dp2_ptr->u.ic.Status);
-    writeb(0xff, &dp2_ptr->io.irqdel);
+    prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]);
+    gdth_writeb(0, &dp2_ptr->u.ic.Status);
+    gdth_writeb(0xff, &dp2_ptr->io.irqdel);
     if (prot_ver != PROTOCOL_VERSION) {
         printk("GDT-ISA: Illegal protocol version\n");
-	gdth_munmap(ha->brd);
+        gdth_munmap(ha->brd);
         return 0;
     }
 
@@ -679,83 +900,84 @@
     ha->brd_phys = bios_adr >> 4;
 
     /* special request to controller BIOS */
-    writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
-    writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
-    writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
-    writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
-    writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
-    writeb(0, &dp2_ptr->io.event);
+    gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
+    gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
+    gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
+    gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
+    gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
+    gdth_writeb(0, &dp2_ptr->io.event);
     retries = INIT_RETRIES;
-    JIFFYWAIT(2);
-    while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
+    gdth_delay(20);
+    while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
-        mdelay(1);
+        gdth_delay(1);
     }
-    writeb(0, &dp2_ptr->u.ic.Status);
-    writeb(0xff, &dp2_ptr->io.irqdel);
+    gdth_writeb(0, &dp2_ptr->u.ic.Status);
+    gdth_writeb(0xff, &dp2_ptr->io.irqdel);
     return 1;
 }
 
 
-static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+__initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
 {
     register gdt6_dpram_str *dp6_ptr;
     register gdt6c_dpram_str *dp6c_ptr;
     register gdt6m_dpram_str *dp6m_ptr;
-    ulong retries;
+    ulong32 retries;
     unchar prot_ver;
+    int i, found = FALSE;
 
     TRACE(("gdth_init_pci()\n"));
 
     ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8);
-    ha->stype    = (ulong)pcistr->device_id;
+    ha->stype    = (ulong32)pcistr->device_id;
     ha->irq      = pcistr->irq;
     
-    if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) {   /* GDT6000 or GDT6000B */
+    if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) {  /* GDT6000/B */
         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
-	ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
-	if (ha->brd == NULL) {
-	    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
-	    return 0;
-	}
+        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
+        if (ha->brd == NULL) {
+            printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+            return 0;
+        }
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
         /* reset interface area */
         memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
-        if (readl(&dp6_ptr->u) != 0) {
+        if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
         
         /* disable board interrupts, deinit services */
-        writeb(0xff, &dp6_ptr->io.irqdel);
-        writeb(0x00, &dp6_ptr->io.irqen);;
-        writeb(0x00, &dp6_ptr->u.ic.S_Status);
-        writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
-
-        writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
-        writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
-        writeb(0, &dp6_ptr->io.event);
+        gdth_writeb(0xff, &dp6_ptr->io.irqdel);
+        gdth_writeb(0x00, &dp6_ptr->io.irqen);;
+        gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status);
+        gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
+
+        gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
+        gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
+        gdth_writeb(0, &dp6_ptr->io.event);
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
-        while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
+        gdth_delay(20);
+        while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
-		gdth_munmap(ha->brd);
+                gdth_munmap(ha->brd);
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
-        prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]);
-        writeb(0, &dp6_ptr->u.ic.S_Status);
-        writeb(0xff, &dp6_ptr->io.irqdel);
+        prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]);
+        gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
+        gdth_writeb(0xff, &dp6_ptr->io.irqdel);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
 
@@ -763,41 +985,41 @@
         ha->ic_all_size = sizeof(dp6_ptr->u);
         
         /* special command to controller BIOS */
-        writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
-        writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
-        writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
-        writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
-        writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
-        writeb(0, &dp6_ptr->io.event);
+        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
+        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
+        gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
+        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
+        gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
+        gdth_writeb(0, &dp6_ptr->io.event);
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
-        while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
+        gdth_delay(20);
+        while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
-		gdth_munmap(ha->brd);
+                gdth_munmap(ha->brd);
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
-        writeb(0, &dp6_ptr->u.ic.S_Status);
-        writeb(0xff, &dp6_ptr->io.irqdel);
+        gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
+        gdth_writeb(0xff, &dp6_ptr->io.irqdel);
 
-    } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, GDT6120, .. */
-	ha->plx = (gdt6c_plx_regs *)pcistr->io;
-	TRACE2(("init_pci_new() dpmem %lx io %lx irq %d\n",
-		pcistr->dpmem,(ulong)ha->plx,ha->irq));
-	ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
-	if (ha->brd == NULL) {
-	    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
-	    gdth_munmap(ha->brd);
-	    return 0;
-	}
+    } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */
+        ha->plx = (gdt6c_plx_regs *)pcistr->io;
+        TRACE2(("init_pci_new() dpmem %lx irq %d\n",
+            pcistr->dpmem,ha->irq));
+        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
+        if (ha->brd == NULL) {
+            printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+            gdth_munmap(ha->brd);
+            return 0;
+        }
         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
         /* reset interface area */
         memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
-        if (readl(&dp6c_ptr->u) != 0) {
+        if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
         
@@ -805,29 +1027,29 @@
         outb(0x00,PTR2USHORT(&ha->plx->control1));
         outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
         
-        writeb(0x00, &dp6c_ptr->u.ic.S_Status);
-        writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
+        gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
+        gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
 
-        writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
-        writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
+        gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
+        gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
 
         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
 
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
-        while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
+        gdth_delay(20);
+        while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
-		gdth_munmap(ha->brd);
+                gdth_munmap(ha->brd);
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
-        prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]);
-        writeb(0, &dp6c_ptr->u.ic.Status);
+        prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]);
+        gdth_writeb(0, &dp6c_ptr->u.ic.Status);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
 
@@ -835,68 +1057,106 @@
         ha->ic_all_size = sizeof(dp6c_ptr->u);
 
         /* special command to controller BIOS */
-        writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
-        writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
-        writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
-        writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
-        writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
+        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
+        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
+        gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
+        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
+        gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
         
         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
 
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
-        while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
+        gdth_delay(20);
+        while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
-		gdth_munmap(ha->brd);
+                gdth_munmap(ha->brd);
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
-        writeb(0, &dp6c_ptr->u.ic.S_Status);
+        gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
 
     } else {                                            /* MPR */
-	TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
-	ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
-	if (ha->brd == NULL) {
-	    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
-	    return 0;
-	}
+        TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
+        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
+        if (ha->brd == NULL) {
+            printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+            return 0;
+        }
 
+        /* check and reset interface area */
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
-        /* reset interface area */
-        memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
-        if (readl(&dp6m_ptr->u) != 0) {
-            printk("GDT-PCI: Initialization error (DPMEM write error)\n");
-	    gdth_munmap(ha->brd);
-            return 0;
+        gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
+        if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n", 
+                   (int)pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_0, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_0, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
+                if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
         }
+        memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
         
         /* disable board interrupts, deinit services */
-        writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
-	       &dp6m_ptr->i960r.edoor_en_reg);
-        writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        writeb(0x00, &dp6m_ptr->u.ic.S_Status);
-        writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
-
-        writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
-        writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
-        writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+        gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
+                    &dp6m_ptr->i960r.edoor_en_reg);
+        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status);
+        gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
+
+        gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
+        gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
+        gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
-        while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
+        gdth_delay(20);
+        while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
-		gdth_munmap(ha->brd);
+                gdth_munmap(ha->brd);
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
-        prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]);
-        writeb(0, &dp6m_ptr->u.ic.S_Status);
+        prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]);
+        gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
-	    gdth_munmap(ha->brd);
+            gdth_munmap(ha->brd);
             return 0;
         }
 
@@ -904,23 +1164,23 @@
         ha->ic_all_size = sizeof(dp6m_ptr->u);
         
         /* special command to controller BIOS */
-        writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
-        writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
-        writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
-        writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
-        writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
-        writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
+        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
+        gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
+        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
+        gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
+        gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
         retries = INIT_RETRIES;
-        JIFFYWAIT(2);
-        while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
+        gdth_delay(20);
+        while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
-		gdth_munmap(ha->brd);
+                gdth_munmap(ha->brd);
                 return 0;
             }
-            mdelay(1);
+            gdth_delay(1);
         }
-        writeb(0, &dp6m_ptr->u.ic.S_Status);
+        gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
     }
 
     return 1;
@@ -929,7 +1189,7 @@
 
 /* controller protocol functions */
 
-static void gdth_enable_int(int hanum)
+__initfunc (static void gdth_enable_int(int hanum))
 {
     gdth_ha_str *ha;
     ulong flags;
@@ -939,9 +1199,7 @@
 
     TRACE(("gdth_enable_int() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
-
-    save_flags(flags);
-    cli();
+    GDTH_LOCK_HA(ha, flags);
 
     if (ha->type == GDT_EISA) {
         outb(0xff, ha->bmic + EDOORREG);
@@ -949,24 +1207,24 @@
         outb(0x01, ha->bmic + EINTENABREG);
     } else if (ha->type == GDT_ISA) {
         dp2_ptr = (gdt2_dpram_str *)ha->brd;
-        writeb(1, &dp2_ptr->io.irqdel);
-        writeb(0, &dp2_ptr->u.ic.Cmd_Index);
-        writeb(1, &dp2_ptr->io.irqen);
+        gdth_writeb(1, &dp2_ptr->io.irqdel);
+        gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
+        gdth_writeb(1, &dp2_ptr->io.irqen);
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        writeb(1, &dp6_ptr->io.irqdel);
-        writeb(0, &dp6_ptr->u.ic.Cmd_Index);
-        writeb(1, &dp6_ptr->io.irqen);
+        gdth_writeb(1, &dp6_ptr->io.irqdel);
+        gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
+        gdth_writeb(1, &dp6_ptr->io.irqen);
     } else if (ha->type == GDT_PCINEW) {
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
         outb(0x03, PTR2USHORT(&ha->plx->control1));
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
-        writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
-	       &dp6m_ptr->i960r.edoor_en_reg);
+        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
+                    &dp6m_ptr->i960r.edoor_en_reg);
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 
 
@@ -976,7 +1234,7 @@
     int i;
 
     TRACE(("gdth_get_status() irq %d ctr_count %d\n",
-                 irq,gdth_ctr_count));
+           irq,gdth_ctr_count));
     
     *pIStatus = 0;
     for (i=0; i<gdth_ctr_count; ++i) {
@@ -986,13 +1244,16 @@
         if (ha->type == GDT_EISA)
             *pIStatus = inb((ushort)ha->bmic + EDOORREG);
         else if (ha->type == GDT_ISA)
-            *pIStatus = readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+            *pIStatus =
+                gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCI)
-            *pIStatus = readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+            *pIStatus =
+                gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCINEW) 
             *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
         else if (ha->type == GDT_PCIMPR)
-            *pIStatus = readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
+            *pIStatus =
+                gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
    
         if (*pIStatus)                                  
             return i;                           /* board found */
@@ -1012,13 +1273,14 @@
     if (ha->type == GDT_EISA)
         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
     else if (ha->type == GDT_ISA)
-        gdtsema0 = (int)readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCI)
-        gdtsema0 = (int)readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCINEW) 
         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
     else if (ha->type == GDT_PCIMPR)
-        gdtsema0 = (int)readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+        gdtsema0 = 
+            (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
 
     return (gdtsema0 & 1);
 }
@@ -1033,10 +1295,10 @@
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     for (i=0; i<GDTH_MAXCMDS; ++i) {
-        if (gdth_cmd_tab[i][hanum].cmnd == UNUSED_CMND) {
-            gdth_cmd_tab[i][hanum].cmnd = ha->pccb->RequestBuffer;
-            gdth_cmd_tab[i][hanum].service = ha->pccb->Service;
-            ha->pccb->CommandIndex = (ulong)i+2;
+        if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
+            ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
+            ha->cmd_tab[i].service = ha->pccb->Service;
+            ha->pccb->CommandIndex = (ulong32)i+2;
             return (i+2);
         }
     }
@@ -1051,17 +1313,17 @@
     TRACE(("gdth_set_sema0() hanum %d\n",hanum));
 
     ha = HADATA(gdth_ctr_tab[hanum]);
-    if (ha->type == GDT_EISA)
+    if (ha->type == GDT_EISA) {
         outb(1, ha->bmic + SEMA0REG);
-    else if (ha->type == GDT_ISA)
-        writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
-    else if (ha->type == GDT_PCI)
-        writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
-    else if (ha->type == GDT_PCINEW)  
+    } else if (ha->type == GDT_ISA) {
+        gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+    } else if (ha->type == GDT_PCI) {
+        gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+    } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
-    else if (ha->type == GDT_PCIMPR)
-        writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
-    
+    } else if (ha->type == GDT_PCIMPR) {
+        gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+    }
 }
 
 
@@ -1096,31 +1358,31 @@
     /* set offset and service, copy command to DPMEM */
     if (ha->type == GDT_ISA) {
         dp2_ptr = (gdt2_dpram_str *)ha->brd;
-        writew(dp_offset + DPMEM_COMMAND_OFFSET, 
-	       &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
-        writew((ushort)cmd_ptr->Service, 
-	       &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
-	memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
+        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+                    &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
+        gdth_writew((ushort)cmd_ptr->Service, 
+                    &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
+        memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        writew(dp_offset + DPMEM_COMMAND_OFFSET, 
-	       &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
-        writew((ushort)cmd_ptr->Service, 
-	       &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
+        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+                    &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
+        gdth_writew((ushort)cmd_ptr->Service, 
+                    &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCINEW) {
         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
-        writew(dp_offset + DPMEM_COMMAND_OFFSET, 
-	       &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
-	writew((ushort)cmd_ptr->Service, 
-	       &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
-	memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
+        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+                    &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
+        gdth_writew((ushort)cmd_ptr->Service, 
+                    &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
+        memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
-        writew(dp_offset + DPMEM_COMMAND_OFFSET, 
-	       &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
-        writew((ushort)cmd_ptr->Service, 
-	       &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
+        gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
+                    &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
+        gdth_writew((ushort)cmd_ptr->Service, 
+                    &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     }
 }
@@ -1130,21 +1392,23 @@
 {
     register gdth_ha_str *ha;
 
+    TRACE(("gdth_release_event() hanum %d\n",hanum));
+    ha = HADATA(gdth_ctr_tab[hanum]);
+
 #ifdef GDTH_STATISTICS
-    ulong i,j;
-    for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
-        if (gdth_cmd_tab[j][hanum].cmnd != UNUSED_CMND)
-            ++i;
-    }
-    if (max_index < i) {
-        max_index = i;
-        TRACE3(("GDT: max_index = %d\n",(ushort)i));
+    {
+        ulong32 i,j;
+        for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
+            if (ha->cmd_tab[j].cmnd != UNUSED_CMND)
+                ++i;
+        }
+        if (max_index < i) {
+            max_index = i;
+            TRACE3(("GDT: max_index = %d\n",(ushort)i));
+        }
     }
 #endif
 
-    TRACE(("gdth_release_event() hanum %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
-
     if (ha->pccb->OpCode == GDT_INIT)
         ha->pccb->Service |= 0x80;
 
@@ -1152,23 +1416,24 @@
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
         if (ha->pccb->OpCode == GDT_INIT)               /* store DMA buffer */
             outl((ulong)ha->pccb, ha->bmic + MAILBOXREG);
-    } else if (ha->type == GDT_ISA)
-        writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
-    else if (ha->type == GDT_PCI)
-        writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
-    else if (ha->type == GDT_PCINEW) 
+    } else if (ha->type == GDT_ISA) {
+        gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
+    } else if (ha->type == GDT_PCI) {
+        gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
+    } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
-    else if (ha->type == GDT_PCIMPR)
-        writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
+    } else if (ha->type == GDT_PCIMPR) {
+        gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
+    }
 }
 
     
-static int gdth_wait(int hanum,int index,ulong time)
+static int gdth_wait(int hanum,int index,ulong32 time)
 {
     gdth_ha_str *ha;
     int answer_found = FALSE;
 
-    TRACE(("gdth_wait() hanum %d index %d time %ld\n",hanum,index,time));
+    TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time));
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     if (index == 0)
@@ -1177,7 +1442,7 @@
     gdth_from_wait = TRUE;
     do {
 #if LINUX_VERSION_CODE >= 0x010346
-        gdth_interrupt((int)ha->irq,NULL,NULL);
+        gdth_interrupt((int)ha->irq,ha,NULL);
 #else
         gdth_interrupt((int)ha->irq,NULL);
 #endif
@@ -1185,19 +1450,19 @@
             answer_found = TRUE;
             break;
         }
-        mdelay(1);
+        gdth_delay(1);
     } while (--time);
     gdth_from_wait = FALSE;
     
     while (gdth_test_busy(hanum))
-        udelay(1);
+        gdth_delay(0);
 
     return (answer_found);
 }
 
 
-static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
-                             ulong p2,ulong p3)
+static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
+                             ulong32 p2,ulong32 p3)
 {
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmd_ptr;
@@ -1234,21 +1499,21 @@
             cmd_ptr->u.raw.direction  = p1;
             cmd_ptr->u.raw.bus        = (unchar)p2;
             cmd_ptr->u.raw.target     = (unchar)p3;
-            cmd_ptr->u.raw.lun        = 0;
+            cmd_ptr->u.raw.lun        = (unchar)(p3 >> 8);
         }
         ha->cmd_len          = sizeof(gdth_cmd_str);
         ha->cmd_offs_dpmem   = 0;
         ha->cmd_cnt          = 0;
         gdth_copy_command(hanum);
         gdth_release_event(hanum);
-        JIFFYWAIT(2);
+        gdth_delay(20);
         if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
             printk("GDT: Initialization error (timeout service %d)\n",service);
             return 0;
         }
         if (ha->status != S_BSY || --retries == 0)
             break;
-        mdelay(1);   
+        gdth_delay(1);   
     }   
     
     return (ha->status != S_OK ? 0:1);
@@ -1257,14 +1522,14 @@
 
 /* search for devices */
 
-static int gdth_search_drives(int hanum)
+__initfunc (static int gdth_search_drives(int hanum))
 {
     register gdth_ha_str *ha;
-    ushort cdev_cnt,i;
-    unchar b,t,pos_found;
-    ulong drv_cyls, drv_hds, drv_secs;
-    ulong bus_no;
+    ushort cdev_cnt, i;
+    ulong32 drv_cyls, drv_hds, drv_secs;
+    ulong32 bus_no;
     gdth_getch_str *chn;
+    gdth_iochan_str *ioc;
     
     TRACE(("gdth_search_drives() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -1292,45 +1557,76 @@
 
     /* initialize cache service after mountall */
     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
-	printk("GDT: Initialization error cache service (code %d)\n",
-	       ha->status);
-	return 0;
+        printk("GDT: Initialization error cache service (code %d)\n",
+               ha->status);
+        return 0;
     }
     TRACE2(("gdth_search_drives() CACHES. init. after mountall\n"));
     cdev_cnt = (ushort)ha->info;
 
-    /* detect number of SCSI buses */
-    chn = (gdth_getch_str *)DMADATA(gdth_ctr_tab[hanum]);
-    for (bus_no=0; bus_no<MAXBUS; ++bus_no) {
-	chn->channel_no = bus_no;
-	if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
-			       SCSI_CHAN_CNT | L_CTRL_PATTERN,
-			       IO_CHANNEL | INVALID_CHANNEL,
-			       sizeof(gdth_getch_str))) {
-	    if (bus_no == 0) {
-		printk("GDT: Error detecting SCSI channel count (0x%x)\n",
-		       ha->status);
-		return 0;
-	    }
-	    break;
-	}
-	if (chn->siop_id < MAXID)
-	    ha->id[bus_no][chn->siop_id].type = SIOP_DTYP;
-    }       
-    ha->bus_cnt = (unchar)bus_no;
-    TRACE2(("gdth_search_drives() %d SCSI channels\n",ha->bus_cnt));
+    /* detect number of buses - try new IOCTL */
+    ioc = (gdth_iochan_str *)ha->pscratch;
+    ioc->version        = 0xffffffff;
+    ioc->list_entries   = MAXBUS;
+    ioc->first_chan     = 0;
+    ioc->last_chan      = MAXBUS-1;
+    ioc->list_offset    = GDTOFFSOF(gdth_iochan_str, list[0]);
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC,
+                          INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
+        TRACE2(("GET_IOCHAN_DESC supported!\n"));
+        ha->bus_cnt = ioc->chan_count;
+        for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+            if (ioc->list[bus_no].proc_id < MAXID)
+                ha->bus_id[bus_no] = ioc->list[bus_no].proc_id;
+            else
+                ha->bus_id[bus_no] = 0xff;
+        }
+    } else {
+        /* old method */
+        chn = (gdth_getch_str *)ha->pscratch;
+        for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
+            chn->channel_no = bus_no;
+            if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+                                   SCSI_CHAN_CNT | L_CTRL_PATTERN,
+                                   IO_CHANNEL | INVALID_CHANNEL,
+                                   sizeof(gdth_getch_str))) {
+                if (bus_no == 0) {
+                    printk("GDT: Error detecting channel count (0x%x)\n",
+                           ha->status);
+                    return 0;
+                }
+                break;
+            }
+            if (chn->siop_id < MAXID)
+                ha->bus_id[bus_no] = chn->siop_id;
+            else
+                ha->bus_id[bus_no] = 0xff;
+        }       
+        ha->bus_cnt = (unchar)bus_no;
+    }
+    TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
 
     /* read cache configuration */
     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
-			   INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
-	printk("GDT: Initialization error cache service (code %d)\n",
-	       ha->status);
-	return 0;
-    }
-    ha->cpar = ((gdth_cinfo_str *)DMADATA(gdth_ctr_tab[hanum]))->cpar;
-    TRACE2(("gdth_search_drives() cinfo: vs %lx sta %d str %d dw %d b %d\n",
-	    ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
-	    ha->cpar.write_back,ha->cpar.block_size));
+                           INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
+        printk("GDT: Initialization error cache service (code %d)\n",
+               ha->status);
+        return 0;
+    }
+    ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
+    TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n",
+            ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
+            ha->cpar.write_back,ha->cpar.block_size));
+
+    /* read board info, fill ctr_name[] */
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
+                          INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
+        TRACE2(("BOARD_INFO supported!\n"));
+        strcpy(ha->ctr_name, ((gdth_binfo_str *)ha->pscratch)->type_string);
+    } else {
+        strcpy(ha->ctr_name, gdth_ctr_name(hanum));
+    }
+    TRACE2(("Controller name: %s\n",ha->ctr_name));
 
     /* initialize raw service */
     if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
@@ -1345,10 +1641,9 @@
     if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
                           0,0)) {
         TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
-        if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0))
-        {
-            TRACE2(("gdth_search_dr(): get feat RAWSERVICE %ld\n",
-                          ha->info));
+        if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
+            TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
+                    ha->info));
             ha->raw_feat = (ushort)ha->info;
         }
     } 
@@ -1358,20 +1653,31 @@
                           SCATTER_GATHER,0)) {
         TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
         if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
-            TRACE2(("gdth_search_dr(): get feat CACHESERV. %ld\n",
-                          ha->info));
+            TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
+                    ha->info));
             ha->cache_feat = (ushort)ha->info;
         }
     }
 
-    /* scanning for raw devices */
-    for (b=0; b<ha->bus_cnt; ++b) {
-        for (t=0; t<MAXID; ++t) {
-            TRACE(("gdth_search_drives() rawd. bus %d id %d\n",b,t));
-            if (ha->id[b][t].type != SIOP_DTYP && 
-                gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INFO,0,b,t)) {
-                ha->id[b][t].type = RAW_DTYP;
-            }
+    /* reserve drives for raw service */
+    if (reserve_mode != 0) {
+        gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL,
+                          reserve_mode == 1 ? 1 : 3, 0, 0);
+        TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", 
+                ha->status));
+    }
+    for (i = 0; i < MAX_RES_ARGS; i += 4) {
+        if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt && 
+            reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) {
+            TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
+                    reserve_list[i], reserve_list[i+1],
+                    reserve_list[i+2], reserve_list[i+3]));
+            if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
+                                   reserve_list[i+1], reserve_list[i+2] | 
+                                   (reserve_list[i+3] << 8))) {
+                printk("GDT: Error raw service (RESERVE, code %d)\n",
+                       ha->status);
+             }
         }
     }
 
@@ -1379,63 +1685,49 @@
     for (i=0; i<cdev_cnt && i<MAX_HDRIVES; ++i) {
         TRACE(("gdth_search_drives() cachedev. %d\n",i));
         if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,i,0,0)) {
-            /* dynamic relation between host drive number and Bus/ID */
-            /* search free position */
-            pos_found = FALSE;
-            for (b=0,t=0; b<ha->bus_cnt; ++b) {
-                for (t=0; t<MAXID; ++t) {
-                    if (ha->id[b][t].type == EMPTY_DTYP) {
-                        pos_found = TRUE;
-                        break;
-                    }
-                }
-                if (pos_found)
-                    break;
-            }
-            TRACE(("gdth_search_dr() drive %d free pos at bus/id %d/%d\n",
-                         i,b,t));
+            /* static relation between host drive number and Bus/ID */
+            TRACE(("gdth_search_dr() drive %d mapped to bus/id %d/%d\n",
+                   i,ha->bus_cnt,i));
 
-            ha->id[b][t].type      = CACHE_DTYP;
-            ha->id[b][t].devtype   = 0;
-            ha->id[b][t].size      = ha->info;
-            ha->id[b][t].hostdrive = i;
+            ha->hdr[i].present = TRUE;
+            ha->hdr[i].size = ha->info;
 
             /* evaluate mapping (sectors per head, heads per cylinder) */
-	    ha->id[b][t].size &= ~SECS32;
-	    if (ha->info2 == 0) {
-		drv_cyls = ha->id[b][t].size /HEADS/SECS;
-		if (drv_cyls <= MAXCYLS) {
-		    drv_hds = HEADS;
-		    drv_secs= SECS;
-		} else {                            /* too high for 64*32 */
-		    drv_cyls = ha->id[b][t].size /MEDHEADS/MEDSECS;
-		    if (drv_cyls <= MAXCYLS) {
-			drv_hds = MEDHEADS;
-			drv_secs= MEDSECS;
-		    } else {                        /* too high for 127*63 */
-			drv_cyls = ha->id[b][t].size /BIGHEADS/BIGSECS;
-			drv_hds = BIGHEADS;
-			drv_secs= BIGSECS;
-		    }
-		}
+            ha->hdr[i].size &= ~SECS32;
+            if (ha->info2 == 0) {
+                drv_cyls = ha->hdr[i].size /HEADS/SECS;
+                if (drv_cyls <= MAXCYLS) {
+                    drv_hds = HEADS;
+                    drv_secs= SECS;
+                } else {                            /* too high for 64*32 */
+                    drv_cyls = ha->hdr[i].size /MEDHEADS/MEDSECS;
+                    if (drv_cyls <= MAXCYLS) {
+                        drv_hds = MEDHEADS;
+                        drv_secs= MEDSECS;
+                    } else {                        /* too high for 127*63 */
+                        drv_cyls = ha->hdr[i].size /BIGHEADS/BIGSECS;
+                        drv_hds = BIGHEADS;
+                        drv_secs= BIGSECS;
+                    }
+                }
             } else {
-		drv_hds = ha->info2 & 0xff;
-		drv_secs = (ha->info2 >> 8) & 0xff;
-		drv_cyls = ha->id[b][t].size /drv_hds/drv_secs;
-	    }
-            ha->id[b][t].heads = (unchar)drv_hds;
-            ha->id[b][t].secs  = (unchar)drv_secs;
+                drv_hds = ha->info2 & 0xff;
+                drv_secs = (ha->info2 >> 8) & 0xff;
+                drv_cyls = ha->hdr[i].size /drv_hds/drv_secs;
+            }
+            ha->hdr[i].heads = (unchar)drv_hds;
+            ha->hdr[i].secs  = (unchar)drv_secs;
             /* round size */
-            ha->id[b][t].size  = drv_cyls * drv_hds * drv_secs;
-            TRACE2(("gdth_search_dr() cdr. %d size %ld hds %ld scs %ld\n",
-                   i,ha->id[b][t].size,drv_hds,drv_secs));
+            ha->hdr[i].size  = drv_cyls * drv_hds * drv_secs;
+            TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
+                   i,ha->hdr[i].size,drv_hds,drv_secs));
             
             /* get informations about device */
             if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i,
                                   0,0)) {
-                TRACE(("gdth_search_dr() cache drive %d devtype %ld\n",
+                TRACE(("gdth_search_dr() cache drive %d devtype %d\n",
                        i,ha->info));
-                ha->id[b][t].devtype = (ushort)ha->info;
+                ha->hdr[i].devtype = (ushort)ha->info;
             }
         }
     }
@@ -1456,12 +1748,11 @@
     unchar b, t;
 
     TRACE(("gdth_putq() priority %d\n",priority));
-    save_flags(flags);
-    cli();
-
     ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
+
     scp->SCp.this_residual = (int)priority;
-    gdth_update_timeout(scp, scp->timeout * 6);
+    gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
 #if LINUX_VERSION_CODE >= 0x020000
     b = scp->channel;
 #else
@@ -1469,9 +1760,12 @@
 #endif
     t = scp->target;
 #if LINUX_VERSION_CODE >= 0x010300
-    if (priority >= DEFAULT_PRI && ha->id[b][t].lock) {
-        TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
-        scp->SCp.buffers_residual = gdth_update_timeout(scp, 0);
+    if (priority >= DEFAULT_PRI) {
+        if ((b < ha->bus_cnt && ha->raw[b].lock) ||
+            (b == ha->bus_cnt && ha->hdr[t].lock)) {
+            TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
+            scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+        }
     }
 #endif
 
@@ -1489,7 +1783,7 @@
         pscp->SCp.ptr = (char *)scp;
         scp->SCp.ptr  = (char *)nscp;
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 
 #ifdef GDTH_STATISTICS
     flags = 0;
@@ -1507,18 +1801,18 @@
     register gdth_ha_str *ha;
     register Scsi_Cmnd *pscp;
     register Scsi_Cmnd *nscp;
-    unchar b, t, next_cmd, firsttime;
-    ushort hdrive;
+    unchar b, t, firsttime;
+    unchar this_cmd, next_cmd;
     ulong flags;
     int cmd_index;
 
     TRACE(("gdth_next() hanum %d\n",hanum));
-    save_flags(flags);
-    cli();
-
     ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
+
     ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
-    next_cmd = firsttime = TRUE;
+    this_cmd = firsttime = TRUE;
+    next_cmd = gdth_polling ? FALSE:TRUE;
     cmd_index = 0;
 
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
@@ -1530,105 +1824,173 @@
         b = NUMDATA(nscp->host)->busnum;
 #endif
         t = nscp->target;
-        if (nscp->SCp.this_residual < DEFAULT_PRI || !ha->id[b][t].lock) {
+        if (nscp->SCp.this_residual >= DEFAULT_PRI) {
+            if ((b < ha->bus_cnt && ha->raw[b].lock) ||
+                (b == ha->bus_cnt && ha->hdr[t].lock)) 
+                continue;
+        }
 
-            if (firsttime) {
-                if (gdth_test_busy(hanum)) {        /* controller busy ? */
-                    TRACE(("gdth_next() controller %d busy !\n",hanum));
-                    if (!gdth_polling) {
-                        restore_flags(flags);
-                        return;
+        if (firsttime) {
+            if (gdth_test_busy(hanum)) {        /* controller busy ? */
+                TRACE(("gdth_next() controller %d busy !\n",hanum));
+                if (!gdth_polling) {
+                    GDTH_UNLOCK_HA(ha, flags);
+                    return;
+                }
+                while (gdth_test_busy(hanum))
+                    gdth_delay(1);
+            }   
+            firsttime = FALSE;
+        }
+
+        if (nscp->SCp.phase == -1) {
+            nscp->SCp.phase = SCSIRAWSERVICE;           /* default: raw svc. */ 
+            if (nscp->cmnd[0] == TEST_UNIT_READY) {
+                TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
+                        nscp->channel, nscp->target, nscp->lun));
+                /* TEST_UNIT_READY -> set scan mode */
+                if ((ha->scan_mode & 0x0f) == 0) {
+                    if (nscp->channel == 0 && nscp->target == 0 &&
+                        nscp->lun == 0) {
+                        ha->scan_mode |= 1;
+                        TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
+                    }
+                } else if ((ha->scan_mode & 0x0f) == 1) {
+                    if (nscp->channel == 0 && 
+                        ((nscp->target == 0 && nscp->lun == 1) ||
+                         (nscp->target == 1 && nscp->lun == 0))) {
+                        nscp->SCp.Status = GDT_SCAN_START;
+                        nscp->SCp.phase |= ((ha->scan_mode & 0x10 ? 1:0) << 8);
+                        ha->scan_mode = 0x12;
+                        TRACE2(("Scan mode: 0x%x (SCAN_START)\n", 
+                                ha->scan_mode));
+                    } else {
+                        ha->scan_mode &= 0x10;
+                        TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
+                    }                   
+                } else if (ha->scan_mode == 0x12) {
+                    if (b == ha->bus_cnt) {
+                        nscp->SCp.Status = GDT_SCAN_END;
+                        ha->scan_mode &= 0x10;
+                        TRACE2(("Scan mode: 0x%x (SCAN_END)\n", 
+                                ha->scan_mode));
                     }
-                    while (gdth_test_busy(hanum))
-                        mdelay(1);
                 }
-                firsttime = FALSE;
             }
+        }
+
+        if (nscp->SCp.Status != -1) {
+            if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
+                cmd_index=gdth_fill_raw_cmd(hanum,nscp,b);
+                next_cmd = FALSE;
+            }
+        } else
 
 #if LINUX_VERSION_CODE >= 0x010300
-            if (nscp->done == gdth_scsi_done) {
-                if (!(cmd_index=gdth_special_cmd(hanum,nscp,b)))
-                    next_cmd = FALSE;
-            } else
-#endif
-            if (ha->id[b][t].type != CACHE_DTYP) {
-                if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b)))
-                    next_cmd = FALSE;
-            } else {
-                hdrive = ha->id[b][t].hostdrive;
-                switch (nscp->cmnd[0]) {
-                  case TEST_UNIT_READY:
-                  case INQUIRY:
-                  case REQUEST_SENSE:
-                  case READ_CAPACITY:
-                  case VERIFY:
-                  case START_STOP:
-                  case MODE_SENSE:
-                    TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
-                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
-                        nscp->cmnd[4],nscp->cmnd[5]));
-                        gdth_internal_cache_cmd(hanum,nscp,b,&flags);
-                    break;
+        if (nscp->done == gdth_scsi_done) {
+            if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
+                this_cmd = FALSE;
+            next_cmd = FALSE;
+        } else
+#endif
+        if (b < ha->bus_cnt) {
+            if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) {
+                this_cmd = FALSE;
+            }
+        } else if (!ha->hdr[nscp->target].present || nscp->lun != 0) {
+            TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
+                    nscp->cmnd[0], b, nscp->target, nscp->lun));
+            nscp->result = DID_BAD_TARGET << 16;
+            GDTH_UNLOCK_HA(ha,flags);
+            /* io_request_lock already active ! */      
+            nscp->scsi_done(nscp);
+            GDTH_LOCK_HA(ha,flags);
+        } else {
+            switch (nscp->cmnd[0]) {
+              case TEST_UNIT_READY:
+              case INQUIRY:
+              case REQUEST_SENSE:
+              case READ_CAPACITY:
+              case VERIFY:
+              case START_STOP:
+              case MODE_SENSE:
+                TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
+                       nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
+                       nscp->cmnd[4],nscp->cmnd[5]));
+                if (gdth_internal_cache_cmd(hanum,nscp)) {
+                    GDTH_UNLOCK_HA(ha,flags);
+                    /* io_request_lock already active ! */      
+                    nscp->scsi_done(nscp);
+                    GDTH_LOCK_HA(ha,flags);
+                }
+                break;
 
-                  case ALLOW_MEDIUM_REMOVAL:
-                    TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
-                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
-                        nscp->cmnd[4],nscp->cmnd[5]));
-                    if ( (nscp->cmnd[4]&1) && !(ha->id[b][t].devtype&1) ) {
-                        TRACE2(("Prevent r. nonremov. drive->do nothing\n"));
-                        nscp->result = DID_OK << 16;
-                        restore_flags( flags );
+              case ALLOW_MEDIUM_REMOVAL:
+                TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
+                       nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
+                       nscp->cmnd[4],nscp->cmnd[5]));
+                if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
+                    TRACE(("Prevent r. nonremov. drive->do nothing\n"));
+                    nscp->result = DID_OK << 16;
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                        save_flags( flags );
-                        cli();
-                    } else {
-                        nscp->cmnd[3] = (ha->id[b][t].devtype&1) ? 1:0;
-                        TRACE2(("Prevent/allow r. %d rem. drive %d\n",
-                            nscp->cmnd[4],nscp->cmnd[3]));
-                        if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
-                            next_cmd = FALSE;
+                        GDTH_LOCK_HA(ha,flags);
                     }
-                    break;
-
-                  case READ_6:
-                  case WRITE_6:
-                  case READ_10:
-                  case WRITE_10:
-                    if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
-                        next_cmd = FALSE;
-                    break;
+                } else {
+                    nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
+                    TRACE(("Prevent/allow r. %d rem. drive %d\n",
+                           nscp->cmnd[4],nscp->cmnd[3]));
+                    if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                        this_cmd = FALSE;
+                }
+                break;
+                
+              case READ_6:
+              case WRITE_6:
+              case READ_10:
+              case WRITE_10:
+                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                    this_cmd = FALSE;
+                break;
 
-                  default:
-                    TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
+              default:
+                TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                         nscp->cmnd[4],nscp->cmnd[5]));
-                    printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
+                printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
                        nscp->cmnd[0]);
-                    nscp->result = DID_ABORT << 16;
-                    restore_flags( flags );
-                    nscp->scsi_done( nscp );
-                    save_flags( flags );
-                    cli();
-                    break;
+                nscp->result = DID_ABORT << 16;
+                if (!nscp->SCp.have_data_in)
+                    nscp->SCp.have_data_in++;
+                else {
+                    GDTH_UNLOCK_HA(ha,flags);
+                    /* io_request_lock already active ! */  
+                    nscp->scsi_done(nscp);
+                    GDTH_LOCK_HA(ha,flags);
                 }
-            }
-
-            if (!next_cmd)
-                break;
-            if (nscp == ha->req_first)
-                ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
-            else
-                pscp->SCp.ptr = nscp->SCp.ptr;
-            if (gdth_polling)
                 break;
+            }
         }
+
+        if (!this_cmd)
+            break;
+        if (nscp == ha->req_first)
+            ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
+        else
+            pscp->SCp.ptr = nscp->SCp.ptr;
+        if (!next_cmd)
+            break;
     }
 
     if (ha->cmd_cnt > 0) {
         gdth_release_event(hanum);
     }
 
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 
     if (gdth_polling && ha->cmd_cnt > 0) {
         if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
@@ -1664,11 +2026,9 @@
     }
 }
 
-static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
-                                   unchar b,ulong *flags)
+static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
 {
     register gdth_ha_str *ha;
-    ushort hdrive;
     unchar t;
     gdth_inq_data inq;
     gdth_rdcap_data rdc;
@@ -1677,77 +2037,73 @@
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     t  = scp->target;
-    hdrive = ha->id[b][t].hostdrive;
     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
-                 scp->cmnd[0],hdrive));
-
-    if (scp->lun !=0)
-        scp->result = DID_BAD_TARGET << 16;
-    else {
-        switch (scp->cmnd[0]) {
-          case TEST_UNIT_READY:
-          case VERIFY:
-          case START_STOP:
-            TRACE2(("Test/Verify/Start hdrive %d\n",hdrive));
-            break;
-
-          case INQUIRY:
-            TRACE2(("Inquiry hdrive %d devtype %d\n",
-                          hdrive,ha->id[b][t].devtype));
-            inq.type_qual = (ha->id[b][t].devtype&4) ? TYPE_ROM:TYPE_DISK;
-            /* you can here set all disks to removable, if you want to do
-               a flush using the ALLOW_MEDIUM_REMOVAL command */
-            inq.modif_rmb = ha->id[b][t].devtype&1 ? 0x80:0x00;
-            inq.version   = 2;
-            inq.resp_aenc = 2;
-            inq.add_length= 32;
-            strcpy(inq.vendor,"ICP    ");
-            sprintf(inq.product,"Host Drive  #%02d",hdrive);
-            strcpy(inq.revision,"   ");
-            gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
-            break;
-
-          case REQUEST_SENSE:
-            TRACE2(("Request sense hdrive %d\n",hdrive));
-            sd.errorcode = 0x70;
-            sd.segno     = 0x00;
-            sd.key       = NO_SENSE;
-            sd.info      = 0;
-            sd.add_length= 0;
-            gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
-            break;
-
-          case MODE_SENSE:
-            TRACE2(("Mode sense hdrive %d\n",hdrive));
-            memset((char*)&mpd,0,sizeof(gdth_modep_data));
-            mpd.hd.data_length = sizeof(gdth_modep_data);
-            mpd.hd.dev_par     = (ha->id[b][t].devtype&2) ? 0x80:0;
-            mpd.hd.bd_length   = sizeof(mpd.bd);
-            mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
-            mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
-            mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
-            gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
-            break;
-
-          case READ_CAPACITY:
-            TRACE2(("Read capacity hdrive %d\n",hdrive));
-            rdc.last_block_no = ntohl(ha->id[b][t].size-1);
-            rdc.block_length  = ntohl(SECTOR_SIZE);
-            gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
-            break;
+           scp->cmnd[0],t));
 
-          default:
-            TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
-            break;
-        }
-        scp->result = DID_OK << 16;
+    switch (scp->cmnd[0]) {
+      case TEST_UNIT_READY:
+      case VERIFY:
+      case START_STOP:
+        TRACE2(("Test/Verify/Start hdrive %d\n",t));
+        break;
+
+      case INQUIRY:
+        TRACE2(("Inquiry hdrive %d devtype %d\n",
+                t,ha->hdr[t].devtype));
+        inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK;
+        /* you can here set all disks to removable, if you want to do
+           a flush using the ALLOW_MEDIUM_REMOVAL command */
+        inq.modif_rmb = ha->hdr[t].devtype&1 ? 0x80:0x00;
+        inq.version   = 2;
+        inq.resp_aenc = 2;
+        inq.add_length= 32;
+        strcpy(inq.vendor,"ICP    ");
+        sprintf(inq.product,"Host Drive  #%02d",t);
+        strcpy(inq.revision,"   ");
+        gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
+        break;
+
+      case REQUEST_SENSE:
+        TRACE2(("Request sense hdrive %d\n",t));
+        sd.errorcode = 0x70;
+        sd.segno     = 0x00;
+        sd.key       = NO_SENSE;
+        sd.info      = 0;
+        sd.add_length= 0;
+        gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
+        break;
+
+      case MODE_SENSE:
+        TRACE2(("Mode sense hdrive %d\n",t));
+        memset((char*)&mpd,0,sizeof(gdth_modep_data));
+        mpd.hd.data_length = sizeof(gdth_modep_data);
+        mpd.hd.dev_par     = (ha->hdr[t].devtype&2) ? 0x80:0;
+        mpd.hd.bd_length   = sizeof(mpd.bd);
+        mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
+        mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
+        mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
+        gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
+        break;
+
+      case READ_CAPACITY:
+        TRACE2(("Read capacity hdrive %d\n",t));
+        rdc.last_block_no = ntohl(ha->hdr[t].size-1);
+        rdc.block_length  = ntohl(SECTOR_SIZE);
+        gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
+        break;
+
+      default:
+        TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
+        break;
     }
+    scp->result = DID_OK << 16;
 
-    restore_flags(*flags);
-    scp->scsi_done(scp);
-    save_flags(*flags);
-    cli();
-    return 1;
+    if (!scp->SCp.have_data_in)
+        scp->SCp.have_data_in++;
+    else 
+        return 1;
+
+    return 0;
 }
     
 static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
@@ -1804,25 +2160,26 @@
         cmdp->u.cache.sg_canz = 0;
     } else {
         if (scp->cmd_len != 6) {
-            cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[2]);
-            cmdp->u.cache.BlockCnt= (ulong)ntohs(*(ushort*)&scp->cmnd[7]);
+            cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]);
+            cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]);
         } else {
-            cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[0]) & 0x001fffffUL;
+            cmdp->u.cache.BlockNo = 
+                ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL;
             cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
         }
 
         if (scp->use_sg) {
-            cmdp->u.cache.DestAddr= -1UL;
+            cmdp->u.cache.DestAddr= 0xffffffff;
             sl = (struct scatterlist *)scp->request_buffer;
             for (i=0; i<scp->use_sg; ++i,++sl) {
                 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
-                cmdp->u.cache.sg_lst[i].sg_len = (ulong)sl->length;
+                cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
             }
-            cmdp->u.cache.sg_canz = (ulong)i;
+            cmdp->u.cache.sg_canz = (ulong32)i;
 
 #ifdef GDTH_STATISTICS
-            if (max_sg < (ulong)i) {
-                max_sg = (ulong)i;
+            if (max_sg < (ulong32)i) {
+                max_sg = (ulong32)i;
                 TRACE3(("GDT: max_sg = %d\n",i));
             }
 #endif
@@ -1830,9 +2187,10 @@
                 cmdp->u.cache.sg_lst[i].sg_len = 0;
         } else {
             if (ha->cache_feat & SCATTER_GATHER) {
-                cmdp->u.cache.DestAddr = -1UL;
+                cmdp->u.cache.DestAddr = 0xffffffff;
                 cmdp->u.cache.sg_canz = 1;
-                cmdp->u.cache.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
+                cmdp->u.cache.sg_lst[0].sg_ptr = 
+                    virt_to_bus(scp->request_buffer);
                 cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
                 cmdp->u.cache.sg_lst[1].sg_len = 0;
             } else {
@@ -1841,12 +2199,12 @@
             }
         }
     }
-    TRACE(("cache cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
-                  cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
-                  cmdp->u.cache.sg_lst[0].sg_ptr,
-                  cmdp->u.cache.sg_lst[0].sg_len));
-    TRACE(("cache cmd: cmd %d blockno. %ld, blockcnt %ld\n",
-                  cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
+    TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+           cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
+           cmdp->u.cache.sg_lst[0].sg_ptr,
+           cmdp->u.cache.sg_lst[0].sg_len));
+    TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
+           cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
 
     /* evaluate command size, check space */
     ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
@@ -1858,7 +2216,7 @@
         if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
             ha->ic_all_size) {
             TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
-            gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
+            ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
             return 0;
         }
     }
@@ -1882,7 +2240,7 @@
     l = scp->lun;
     cmdp = ha->pccb;
     TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
-                 scp->cmnd[0],b,t,l));
+           scp->cmnd[0],b,t,l));
 
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
         return 0;
@@ -1899,61 +2257,73 @@
         gdth_set_sema0(hanum);
 
     /* fill command */  
-    cmdp->OpCode           = GDT_WRITE;         /* always */
-    cmdp->BoardNode        = LOCALBOARD;
-    cmdp->u.raw.reserved   = 0;
-    cmdp->u.raw.mdisc_time = 0;
-    cmdp->u.raw.mcon_time  = 0;
-    cmdp->u.raw.clen       = scp->cmd_len;
-    cmdp->u.raw.target     = t;
-    cmdp->u.raw.lun        = l;
-    cmdp->u.raw.bus        = b;
-    cmdp->u.raw.priority   = 0;
-    cmdp->u.raw.link_p     = NULL;
-    cmdp->u.raw.sdlen      = scp->request_bufflen;
-    cmdp->u.raw.sense_len  = 16;
-    cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
-    cmdp->u.raw.direction  = 
-        gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
-    memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
+    if (scp->SCp.Status != -1) {
+        cmdp->OpCode           = scp->SCp.Status;       /* special raw cmd. */
+        cmdp->BoardNode        = LOCALBOARD;
+        cmdp->u.raw.direction  = (scp->SCp.phase >> 8);
+        TRACE2(("special raw cmd 0x%x param 0x%x\n", 
+                cmdp->OpCode, cmdp->u.raw.direction));
 
-    if (scp->use_sg) {
-        cmdp->u.raw.sdata  = -1UL;
-        sl = (struct scatterlist *)scp->request_buffer;
-        for (i=0; i<scp->use_sg; ++i,++sl) {
-            cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
-            cmdp->u.raw.sg_lst[i].sg_len = (ulong)sl->length;
-        }
-        cmdp->u.raw.sg_ranz = (ulong)i;
+        /* evaluate command size */
+        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
+    } else {
+        cmdp->OpCode           = GDT_WRITE;             /* always */
+        cmdp->BoardNode        = LOCALBOARD;
+        cmdp->u.raw.reserved   = 0;
+        cmdp->u.raw.mdisc_time = 0;
+        cmdp->u.raw.mcon_time  = 0;
+        cmdp->u.raw.clen       = scp->cmd_len;
+        cmdp->u.raw.target     = t;
+        cmdp->u.raw.lun        = l;
+        cmdp->u.raw.bus        = b;
+        cmdp->u.raw.priority   = 0;
+        cmdp->u.raw.link_p     = NULL;
+        cmdp->u.raw.sdlen      = scp->request_bufflen;
+        cmdp->u.raw.sense_len  = 16;
+        cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
+        cmdp->u.raw.direction  = 
+            gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
+        memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
+
+        if (scp->use_sg) {
+            cmdp->u.raw.sdata  = 0xffffffff;
+            sl = (struct scatterlist *)scp->request_buffer;
+            for (i=0; i<scp->use_sg; ++i,++sl) {
+                cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+                cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
+            }
+            cmdp->u.raw.sg_ranz = (ulong32)i;
 
 #ifdef GDTH_STATISTICS
-        if (max_sg < (ulong)i) {
-            max_sg = (ulong)i;
-            TRACE3(("GDT: max_sg = %d\n",i));
-        }
+            if (max_sg < (ulong32)i) {
+                max_sg = (ulong32)i;
+                TRACE3(("GDT: max_sg = %d\n",i));
+            }
 #endif
-        if (i<GDTH_MAXSG)
-            cmdp->u.raw.sg_lst[i].sg_len = 0;
-    } else {
-        if (ha->raw_feat & SCATTER_GATHER) {
-            cmdp->u.raw.sdata  = -1UL;
-            cmdp->u.raw.sg_ranz= 1;
-            cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
-            cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
-            cmdp->u.raw.sg_lst[1].sg_len = 0;
+            if (i<GDTH_MAXSG)
+                cmdp->u.raw.sg_lst[i].sg_len = 0;
         } else {
-            cmdp->u.raw.sdata  = virt_to_bus(scp->request_buffer);
-            cmdp->u.raw.sg_ranz= 0;
+            if (ha->raw_feat & SCATTER_GATHER) {
+                cmdp->u.raw.sdata  = 0xffffffff;
+                cmdp->u.raw.sg_ranz= 1;
+                cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
+                cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
+                cmdp->u.raw.sg_lst[1].sg_len = 0;
+            } else {
+                cmdp->u.raw.sdata  = virt_to_bus(scp->request_buffer);
+                cmdp->u.raw.sg_ranz= 0;
+            }
         }
-    }
-    TRACE(("raw cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
-                  cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
-                  cmdp->u.raw.sg_lst[0].sg_ptr,
-                  cmdp->u.raw.sg_lst[0].sg_len));
+        TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+               cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
+               cmdp->u.raw.sg_lst[0].sg_ptr,
+               cmdp->u.raw.sg_lst[0].sg_len));
 
-    /* evaluate command size, check space */
-    ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
-        (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
+        /* evaluate command size */
+        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
+            (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
+    }
+    /* check space */
     if (ha->cmd_len & 3)
         ha->cmd_len += (4 - (ha->cmd_len & 3));
 
@@ -1961,7 +2331,7 @@
         if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
             ha->ic_all_size) {
             TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
-            gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
+            ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
             return 0;
         }
     }
@@ -1971,7 +2341,7 @@
     return cmd_index;
 }
 
-static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
+static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
 {
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
@@ -2000,13 +2370,16 @@
     /* evaluate command size, check space */
     if (cmdp->OpCode == GDT_IOCTL) {
         TRACE2(("IOCTL\n"));
-        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong);
+        ha->cmd_len = 
+            GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32);
     } else if (cmdp->Service == CACHESERVICE) {
         TRACE2(("cache command %d\n",cmdp->OpCode));
-        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
+        ha->cmd_len = 
+            GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
     } else if (cmdp->Service == SCSIRAWSERVICE) {
         TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0]));
-        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
+        ha->cmd_len = 
+            GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
     }
 
     if (ha->cmd_len & 3)
@@ -2016,7 +2389,7 @@
         if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
             ha->ic_all_size) {
             TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
-            gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
+            ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
             return 0;
         }
     }
@@ -2028,8 +2401,8 @@
 
 
 /* Controller event handling functions */
-static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
-                                      gdth_evt_data *evt)
+static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, 
+                                      ushort idx, gdth_evt_data *evt)
 {
     gdth_evt_str *e;
     ulong flags;
@@ -2039,8 +2412,7 @@
     if (source == 0)                        /* no source -> no event */
         return 0;
 
-    save_flags(flags);
-    cli();
+    GDTH_LOCK_HA(ha, flags);
     if (ebuffer[elastidx].event_source == source &&
         ebuffer[elastidx].event_idx == idx &&
         !memcmp((char *)&ebuffer[elastidx].event_data.eu,
@@ -2068,19 +2440,18 @@
         e->same_count = 1;
         e->event_data = *evt;
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
     return e;
 }
 
-static int gdth_read_event(int handle, gdth_evt_str *estr)
+static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
 {
     gdth_evt_str *e;
     int eindex;
     ulong flags;
 
     TRACE2(("gdth_read_event() handle %d\n", handle));
-    save_flags(flags);
-    cli();
+    GDTH_LOCK_HA(ha, flags);
     if (handle == -1)
         eindex = eoldidx;
     else
@@ -2088,7 +2459,7 @@
     estr->event_source = 0;
 
     if (eindex >= MAX_EVENTS) {
-        restore_flags(flags);
+        GDTH_UNLOCK_HA(ha, flags);
         return eindex;
     }
     e = &ebuffer[eindex];
@@ -2101,11 +2472,12 @@
         }
         memcpy(estr, e, sizeof(gdth_evt_str));
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
     return eindex;
 }
 
-static void gdth_readapp_event(unchar application, gdth_evt_str *estr)
+static void gdth_readapp_event(gdth_ha_str *ha,
+                               unchar application, gdth_evt_str *estr)
 {
     gdth_evt_str *e;
     int eindex;
@@ -2113,8 +2485,7 @@
     unchar found = FALSE;
 
     TRACE2(("gdth_readapp_event() app. %d\n", application));
-    save_flags(flags);
-    cli();
+    GDTH_LOCK_HA(ha, flags);
     eindex = eoldidx;
     for (;;) {
         e = &ebuffer[eindex];
@@ -2134,35 +2505,21 @@
         memcpy(estr, e, sizeof(gdth_evt_str));
     else
         estr->event_source = 0;
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 
 static void gdth_clear_events()
 {
-    ulong flags;
-
     TRACE(("gdth_clear_events()"));
-    save_flags(flags);
-    cli();
 
     eoldidx = elastidx = 0;
     ebuffer[0].event_source = 0;
-    restore_flags(flags);
 }
 
 
 /* SCSI interface functions */
 
 #if LINUX_VERSION_CODE >= 0x010346
-static void do_gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-    gdth_interrupt(irq, dev_id, regs);
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
 #else
 static void gdth_interrupt(int irq,struct pt_regs *regs)
@@ -2173,11 +2530,12 @@
     gdt6_dpram_str *dp6_ptr;
     gdt2_dpram_str *dp2_ptr;
     Scsi_Cmnd *scp;
-    int hanum;
+    int hanum, rval;
     unchar IStatus;
     ushort CmdStatus, Service = 0;
-    ulong InfoBytes, InfoBytes2 = 0;
+    ulong32 InfoBytes, InfoBytes2 = 0;
     gdth_evt_data dvr;
+    ulong flags = 0;
 
     TRACE(("gdth_interrupt() IRQ %d\n",irq));
 
@@ -2188,6 +2546,8 @@
         }
     }
 
+    if (!gdth_polling)
+        GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags);
     wait_index = 0;
 
     /* search controller */
@@ -2195,6 +2555,8 @@
         /*
         TRACE2(("gdth_interrupt(): Spurious interrupt received\n"));
         */
+        if (!gdth_polling)
+            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
         return;
     }
 
@@ -2204,63 +2566,63 @@
     
     ha = HADATA(gdth_ctr_tab[hanum]);
     if (ha->type == GDT_EISA) {
-        if (IStatus & 0x80) {                   /* error flag */
+        if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
             CmdStatus = inw(ha->bmic + MAILBOXREG+8);
             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {        /* async. event ? */
+            if (IStatus == ASYNCINDEX) {            /* async. event ? */
                 Service = inw(ha->bmic + MAILBOXREG+10);
                 InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
             }
-        } else                                  /* no error */
+        } else                                      /* no error */
             CmdStatus = S_OK;
         InfoBytes = inl(ha->bmic + MAILBOXREG+12);
-	if (gdth_polling)			/* init. -> more info */
-	    InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
-        outb(0xff, ha->bmic + EDOORREG);    /* acknowledge interrupt */
-        outb(0x00, ha->bmic + SEMA1REG);    /* reset status semaphore */
+        if (gdth_polling)                           /* init. -> more info */
+            InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
+        outb(0xff, ha->bmic + EDOORREG);            /* acknowledge interrupt */
+        outb(0x00, ha->bmic + SEMA1REG);            /* reset status semaphore */
     } else if (ha->type == GDT_ISA) {
         dp2_ptr = (gdt2_dpram_str *)ha->brd;
-        if (IStatus & 0x80) {                   /* error flag */
+        if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = readw(&dp2_ptr->u.ic.Status);
+            CmdStatus = gdth_readw(&dp2_ptr->u.ic.Status);
             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {        /* async. event ? */
-                Service = readw(&dp2_ptr->u.ic.Service);
-                InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
+            if (IStatus == ASYNCINDEX) {            /* async. event ? */
+                Service = gdth_readw(&dp2_ptr->u.ic.Service);
+                InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
             }
-        } else                                  /* no error */
+        } else                                      /* no error */
             CmdStatus = S_OK;
-        InfoBytes = readl(&dp2_ptr->u.ic.Info[0]);
-	if (gdth_polling)			/* init. -> more info */
-	    InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
-        writeb(0xff, &dp2_ptr->io.irqdel);              /* acknowledge interrupt */
-        writeb(0, &dp2_ptr->u.ic.Cmd_Index);            /* reset command index */
-        writeb(0, &dp2_ptr->io.Sema1);                 /* reset status semaphore */
+        InfoBytes = gdth_readl(&dp2_ptr->u.ic.Info[0]);
+        if (gdth_polling)                           /* init. -> more info */
+            InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
+        gdth_writeb(0xff, &dp2_ptr->io.irqdel);     /* acknowledge interrupt */
+        gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);   /* reset command index */
+        gdth_writeb(0, &dp2_ptr->io.Sema1);         /* reset status semaphore */
     } else if (ha->type == GDT_PCI) {
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        if (IStatus & 0x80) {                   /* error flag */
+        if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = readw(&dp6_ptr->u.ic.Status);
+            CmdStatus = gdth_readw(&dp6_ptr->u.ic.Status);
             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
             if (IStatus == ASYNCINDEX) {        /* async. event ? */
-                Service = readw(&dp6_ptr->u.ic.Service);
-                InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
+                Service = gdth_readw(&dp6_ptr->u.ic.Service);
+                InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
             }
-        } else                                  /* no error */
+        } else                                      /* no error */
             CmdStatus = S_OK;
-        InfoBytes = readl(&dp6_ptr->u.ic.Info[0]);
-	if (gdth_polling)			/* init. -> more info */
-	    InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
-        writeb(0xff, &dp6_ptr->io.irqdel);              /* acknowledge interrupt */
-        writeb(0, &dp6_ptr->u.ic.Cmd_Index);            /* reset command index */
-        writeb(0, &dp6_ptr->io.Sema1);                 /* reset status semaphore */
+        InfoBytes = gdth_readl(&dp6_ptr->u.ic.Info[0]);
+        if (gdth_polling)                           /* init. -> more info */
+            InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
+        gdth_writeb(0xff, &dp6_ptr->io.irqdel);     /* acknowledge interrupt */
+        gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);   /* reset command index */
+        gdth_writeb(0, &dp6_ptr->io.Sema1);         /* reset status semaphore */
     } else if (ha->type == GDT_PCINEW) {
-        if (IStatus & 0x80) {                   /* error flag */
+        if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
             CmdStatus = inw(PTR2USHORT(&ha->plx->status));
             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {        /* async. event ? */
+            if (IStatus == ASYNCINDEX) {            /* async. event ? */
                 Service = inw(PTR2USHORT(&ha->plx->service));
                 InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
             }
@@ -2268,34 +2630,36 @@
             CmdStatus = S_OK;
 
         InfoBytes = inl(PTR2USHORT(&ha->plx->info[0]));
-	if (gdth_polling)			/* init. -> more info */
-	    InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
+        if (gdth_polling)                           /* init. -> more info */
+            InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
         outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
-        if (IStatus & 0x80) {                   /* error flag */
+        if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = readw(&dp6m_ptr->i960r.status);
+            CmdStatus = gdth_readw(&dp6m_ptr->i960r.status);
             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {        /* async. event ? */
-                Service = readw(&dp6m_ptr->i960r.service);
-                InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
+            if (IStatus == ASYNCINDEX) {            /* async. event ? */
+                Service = gdth_readw(&dp6m_ptr->i960r.service);
+                InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
             }
-        } else                                  /* no error */
+        } else                                      /* no error */
             CmdStatus = S_OK;
-        InfoBytes = readl(&dp6m_ptr->i960r.info[0]);
-	if (gdth_polling)			/* init. -> more info */
-	    InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
-        writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        writeb(0, &dp6m_ptr->i960r.sema1_reg);
+        InfoBytes = gdth_readl(&dp6m_ptr->i960r.info[0]);
+        if (gdth_polling)                           /* init. -> more info */
+            InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
     } else {
         TRACE2(("gdth_interrupt() unknown controller type\n"));
+        if (!gdth_polling)
+            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
         return;
     }
 
-    TRACE(("gdth_interrupt() index %d stat %d info %ld\n",
-                 IStatus,CmdStatus,InfoBytes));
+    TRACE(("gdth_interrupt() index %d stat %d info %d\n",
+           IStatus,CmdStatus,InfoBytes));
     ha->status = CmdStatus;
     ha->info   = InfoBytes;
     ha->info2  = InfoBytes2;
@@ -2308,31 +2672,51 @@
     if (IStatus == ASYNCINDEX) {
         TRACE2(("gdth_interrupt() async. event\n"));
         gdth_async_event(hanum,Service);
-    } else {
-        if (IStatus == SPEZINDEX) {
-            TRACE2(("Service unknown or not initialized !\n"));
-            dvr.size = sizeof(dvr.eu.driver);
-            dvr.eu.driver.ionode = hanum;
-            gdth_store_event(ES_DRIVER, 4, &dvr);
-            return;
-        }
-        scp     = gdth_cmd_tab[IStatus-2][hanum].cmnd;
-        Service = gdth_cmd_tab[IStatus-2][hanum].service;
-        gdth_cmd_tab[IStatus-2][hanum].cmnd = UNUSED_CMND;
-        if (scp == UNUSED_CMND) {
-            TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
-            dvr.size = sizeof(dvr.eu.driver);
-            dvr.eu.driver.ionode = hanum;
-            dvr.eu.driver.index = IStatus;
-            gdth_store_event(ES_DRIVER, 1, &dvr);
-            return;
-        }
-        if (scp == INTERNAL_CMND) {
-            TRACE(("gdth_interrupt() answer to internal command\n"));
-            return;
-        }
-        TRACE(("gdth_interrupt() sync. status\n"));
-        gdth_sync_event(hanum,Service,IStatus,scp);
+        if (!gdth_polling)
+            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+        gdth_next(hanum);
+        return;
+    } 
+
+    if (IStatus == SPEZINDEX) {
+        TRACE2(("Service unknown or not initialized !\n"));
+        dvr.size = sizeof(dvr.eu.driver);
+        dvr.eu.driver.ionode = hanum;
+        gdth_store_event(ha, ES_DRIVER, 4, &dvr);
+        if (!gdth_polling)
+            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+        return;
+    }
+    scp     = ha->cmd_tab[IStatus-2].cmnd;
+    Service = ha->cmd_tab[IStatus-2].service;
+    ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
+    if (scp == UNUSED_CMND) {
+        TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
+        dvr.size = sizeof(dvr.eu.driver);
+        dvr.eu.driver.ionode = hanum;
+        dvr.eu.driver.index = IStatus;
+        gdth_store_event(ha, ES_DRIVER, 1, &dvr);
+        if (!gdth_polling)
+            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+        return;
+    }
+    if (scp == INTERNAL_CMND) {
+        TRACE(("gdth_interrupt() answer to internal command\n"));
+        if (!gdth_polling)
+            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+        return;
+    }
+
+    TRACE(("gdth_interrupt() sync. status\n"));
+    rval = gdth_sync_event(hanum,Service,IStatus,scp);
+    if (!gdth_polling)
+        GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+    if (rval == 2) {
+        gdth_putq(hanum,scp,scp->SCp.this_residual);
+    } else if (rval == 1) {
+        GDTH_LOCK_SCSI_DONE(flags);
+        scp->scsi_done(scp);
+        GDTH_UNLOCK_SCSI_DONE(flags);
     }
     gdth_next(hanum);
 }
@@ -2348,13 +2732,14 @@
 
     ha   = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
-    TRACE(("gdth_sync_event() scp %lx serv %d status %d\n",
-                 (ulong)scp,service,ha->status));
+    TRACE(("gdth_sync_event() serv %d status %d\n",
+           service,ha->status));
 
     if (service == SCREENSERVICE) {
         msg  = (gdth_msg_str *)ha->pscratch;
-        TRACE(("len: %ld, answer: %d, ext: %d, alen: %ld\n",
-                     msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
+        ha->scratch_busy = FALSE;
+        TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
+               msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
         if (msg->msg_len)
             if (!(msg->msg_answer && msg->msg_ext)) {
                 msg->msg_text[msg->msg_len] = '\0';
@@ -2363,7 +2748,7 @@
 
         if (msg->msg_ext && !msg->msg_answer) {
             while (gdth_test_busy(hanum))
-                udelay(1);
+                gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
             gdth_get_cmd_index(hanum);
@@ -2372,14 +2757,15 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.msg_handle= msg->msg_handle;
-            cmdp->u.screen.msg_addr  = (ulong)msg;
+            cmdp->u.screen.msg_addr  = virt_to_bus(msg);
+            ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
-                + sizeof(ulong);
+                + sizeof(ulong32);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
             gdth_release_event(hanum);
-            return 1;
+            return 0;
         }
 
         if (msg->msg_answer && msg->msg_alen) {
@@ -2400,7 +2786,7 @@
             }
             msg->msg_len = i;
             while (gdth_test_busy(hanum))
-                udelay(1);
+                gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
             gdth_get_cmd_index(hanum);
@@ -2409,14 +2795,15 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.msg_handle= msg->msg_handle;
-            cmdp->u.screen.msg_addr  = (ulong)msg;
+            cmdp->u.screen.msg_addr  = virt_to_bus(msg);
+            ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
-                + sizeof(ulong);
+                + sizeof(ulong32);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
             gdth_release_event(hanum);
-            return 1;
+            return 0;
         }
         printk("\n");
 
@@ -2424,12 +2811,25 @@
         scp->SCp.Message = (int)ha->status;
         /* cache or raw service */
         if (ha->status == S_OK) {
+            if (scp->SCp.Status != -1) {
+                TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
+                        scp->SCp.Status));
+                scp->SCp.Status = -1;
+                scp->SCp.this_residual = HIGH_PRI;
+                return 2;
+            }
             scp->result = DID_OK << 16;
         } else if (ha->status == S_BSY) {
             TRACE2(("Controller busy -> retry !\n"));
-            gdth_putq(hanum,scp,DEFAULT_PRI);
-            return 1;
+            return 2;
         } else {
+            if (scp->SCp.Status != -1) {
+                TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
+                        scp->SCp.Status, ha->status));
+                scp->SCp.Status = -1;
+                scp->SCp.this_residual = HIGH_PRI;
+                return 2;
+            }
             if (service == CACHESERVICE) {
                 memset((char*)scp->sense_buffer,0,16);
                 scp->sense_buffer[0] = 0x70;
@@ -2442,30 +2842,27 @@
                     dvr.eu.sync.service = service;
                     dvr.eu.sync.status  = ha->status;
                     dvr.eu.sync.info    = ha->info;
-                    dvr.eu.sync.hostdrive =
-#if LINUX_VERSION_CODE >= 0x020000
-                        ha->id[scp->channel][scp->target].hostdrive;
-#else
-                        ha->id[NUMDATA(scp->host)->busnum][scp->target].hostdrive;
-#endif
+                    dvr.eu.sync.hostdrive = scp->target;
                     if (ha->status >= 0x8000)
-                        gdth_store_event(ES_SYNC, 0, &dvr);
+                        gdth_store_event(ha, ES_SYNC, 0, &dvr);
                     else
-                        gdth_store_event(ES_SYNC, service, &dvr);
+                        gdth_store_event(ha, ES_SYNC, service, &dvr);
                 }
             } else {
-                if (ha->status!=S_RAW_SCSI || ha->status==S_RAW_ILL) {
+                if (ha->status!=S_RAW_SCSI || ha->info>=0x100) {
                     scp->result = DID_BAD_TARGET << 16;
                 } else {
                     scp->result = (DID_OK << 16) | ha->info;
                 }
             }
         }
-        scp->SCp.have_data_in++;
-        scp->scsi_done(scp);
+        if (!scp->SCp.have_data_in)
+            scp->SCp.have_data_in++;
+        else 
+            return 1;
     }
 
-    return 1;
+    return 0;
 }
 
 static char *async_cache_tab[] = {
@@ -2587,15 +2984,40 @@
         "GDT HA %u, Array Drive %u: expand restarted",
 /*58*/  "\005\000\002\006\002"
         "GDT HA %u, Array Drive %u: expand stopped",
+/*59*/  "\005\000\002\010\002"
+        "GDT HA %u, Mirror Drive %u: drive build quited",
+/*60*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: parity build quited",
+/*61*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: drive rebuild quited",
+/*62*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: parity verify started",
+/*63*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: parity verify done",
+/*64*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: parity verify failed",
+/*65*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: parity error detected",
+/*66*/  "\005\000\002\006\002"
+        "GDT HA %u, Array Drive %u: parity verify quited",
+/*67*/  "\005\000\002\006\002"
+        "GDT HA %u, Host Drive %u reserved",
+/*68*/  "\005\000\002\006\002"
+        "GDT HA %u, Host Drive %u mounted and released",
+/*69*/  "\005\000\002\006\002"
+        "GDT HA %u, Host Drive %u released",
+/*70*/  "\003\000\002"
+        "GDT HA %u, DRAM error detected and corrected with ECC",
+/*71*/  "\003\000\002"
+        "GDT HA %u, Uncorrectable DRAM error detected with ECC",
+/*72*/  "\011\000\002\012\001\013\001\014\001"
+        "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
 };
 
 
 static int gdth_async_event(int hanum,int service)
 {
-    gdth_stackframe stack;
     gdth_evt_data dvr;
-    char *f = NULL;
-    int i,j;
     gdth_ha_str *ha;
     gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
@@ -2605,12 +3027,12 @@
     cmdp= ha->pccb;
     msg = (gdth_msg_str *)ha->pscratch;
     TRACE2(("gdth_async_event() ha %d serv %d\n",
-                 hanum,service));
+            hanum,service));
 
     if (service == SCREENSERVICE) {
         if (ha->status == MSG_REQUEST) {
             while (gdth_test_busy(hanum))
-                udelay(1);
+                gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
             cmdp->RequestBuffer = SCREEN_CMND;
             cmd_index = gdth_get_cmd_index(hanum);
@@ -2619,10 +3041,11 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.msg_handle= MSG_INV_HANDLE;
-            cmdp->u.screen.msg_addr  = (ulong)msg;
+            cmdp->u.screen.msg_addr  = virt_to_bus(msg);
+            ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
-                + sizeof(ulong);
+                + sizeof(ulong32);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
             if (ha->type == GDT_EISA)
@@ -2641,80 +3064,89 @@
         dvr.eu.async.service = service;
         dvr.eu.async.status  = ha->status;
         dvr.eu.async.info    = ha->info;
-        *(ulong *)dvr.eu.async.scsi_coord  = ha->info2;
-        gdth_store_event(ES_ASYNC, service, &dvr);
+        *(ulong32 *)dvr.eu.async.scsi_coord  = ha->info2;
+        gdth_store_event(ha, ES_ASYNC, service, &dvr);
+        gdth_log_event( &dvr );
+    }
+    return 1;
+}
 
-        if (service==CACHESERVICE && INDEX_OK(ha->status,async_cache_tab)) {
-            TRACE2(("GDT: Async. event cache service, event no.: %d\n",
-                ha->status));
-        
-            f = async_cache_tab[ha->status];
+static void gdth_log_event(gdth_evt_data *dvr)
+{
+    gdth_stackframe stack;
+    char *f = NULL;
+    int i,j;
 
-            /* i: parameter to push, j: stack element to fill */
-            for (j=0,i=1; i < f[0]; i+=2) {
-                switch (f[i+1]) {
-                  case 4:
-                    stack.b[j++] = *(ulong*)&dvr.eu.stream[(int)f[i]];
-                    break;
-                  case 2:
-                    stack.b[j++] = *(ushort*)&dvr.eu.stream[(int)f[i]];
-                    break;
-                  case 1:
-                    stack.b[j++] = *(unchar*)&dvr.eu.stream[(int)f[i]];
-                    break;
-                  default:
-                    break;
-                }
+    TRACE2(("gdth_log_event()\n"));
+    if (dvr->eu.async.service == CACHESERVICE && 
+        INDEX_OK(dvr->eu.async.status, async_cache_tab)) {
+        TRACE2(("GDT: Async. event cache service, event no.: %d\n",
+                dvr->eu.async.status));
+        
+        f = async_cache_tab[dvr->eu.async.status];
+        
+        /* i: parameter to push, j: stack element to fill */
+        for (j=0,i=1; i < f[0]; i+=2) {
+            switch (f[i+1]) {
+              case 4:
+                stack.b[j++] = *(ulong32*)&dvr->eu.stream[(int)f[i]];
+                break;
+              case 2:
+                stack.b[j++] = *(ushort*)&dvr->eu.stream[(int)f[i]];
+                break;
+              case 1:
+                stack.b[j++] = *(unchar*)&dvr->eu.stream[(int)f[i]];
+                break;
+              default:
+                break;
             }
+        }
 
-            printk(&f[f[0]],stack); printk("\n");
+        printk(&f[(int)f[0]],stack); printk("\n");
 
-        } else {
-            printk("GDT: Unknown async. event service %d event no. %d\n",
-                service,ha->status);
-        }
+    } else {
+        printk("GDT: Unknown async. event service %d event no. %d\n",
+               dvr->eu.async.service,dvr->eu.async.status);
     }
-    return 1;
 }
 
 #ifdef GDTH_STATISTICS
-void gdth_timeout(void)
+void gdth_timeout(ulong data)
 {
-    ulong flags,i;
+    ulong32 i;
     Scsi_Cmnd *nscp;
     gdth_ha_str *ha;
+    ulong flags;
     int hanum = 0;
 
-    save_flags(flags);
-    cli();
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
 
     for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i) 
-        if (gdth_cmd_tab[i][hanum].cmnd != UNUSED_CMND)
+        if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
             ++act_stats;
 
-    ha = HADATA(gdth_ctr_tab[hanum]);
     for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
         ++act_rq;
 
-    TRACE2(("gdth_to(): ints %ld, ios %ld, act_stats %ld, act_rq %ld\n",
+    TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n",
             act_ints, act_ios, act_stats, act_rq));
     act_ints = act_ios = 0;
 
-    timer_table[GDTH_TIMER].expires = jiffies + 30*HZ;
-    timer_active |= 1<<GDTH_TIMER;
-    restore_flags(flags);
+    gdth_timer.expires = jiffies + 30 * HZ;
+    add_timer(&gdth_timer);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 #endif
 
-int gdth_detect(Scsi_Host_Template *shtp)
+
+__initfunc (int gdth_detect(Scsi_Host_Template *shtp))
 {
     struct Scsi_Host *shp;
     gdth_ha_str *ha;
-    unsigned long flags;
-    ulong isa_bios;
-    ushort eisa_slot,device_id,index;
-    gdth_pci_str pcistr;
-    int i,j,hanum;
+    ulong32 isa_bios;
+    ushort eisa_slot;
+    int i,hanum,cnt,ctr;
     unchar b;
     
  
@@ -2731,28 +3163,24 @@
 #else
     printk("Console\n");
 #endif
-    WAITSEC(3);
+    gdth_delay(3000);
 #endif
 
     TRACE(("gdth_detect()\n"));
 
-    if (disable_gdth_scan) {
+    if (disable) {
         printk("GDT: Controller driver disabled from command line !\n");
         return 0;
     }
 
     /* initializations */
     gdth_polling = TRUE; b = 0;
-    for (i=0; i<GDTH_MAXCMDS; ++i)
-        for (j=0; j<MAXHA; ++j)
-            gdth_cmd_tab[i][j].cmnd = UNUSED_CMND;
-    for (i=0; i<4; ++i)
-        for (j=0; j<MAXHA; ++j)
-            gdth_ioctl_tab[i][j] = NULL;
     gdth_clear_events();
 
     /* scanning for controllers, at first: ISA controller */
     for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
+        if (gdth_ctr_count >= MAXHA) 
+            break;
         if (gdth_search_isa(isa_bios)) {        /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
             ha = HADATA(shp);
@@ -2761,19 +3189,16 @@
                 continue;
             }
             /* controller found and initialized */
-            printk("Configuring GDT-ISA HA at BIOS 0x%05lX IRQ %u DRQ %u\n",
+            printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
                    isa_bios,ha->irq,ha->drq);
 
-            save_flags(flags);
-            cli();
 #if LINUX_VERSION_CODE >= 0x010346 
-            if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
+            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
 #else
             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
 #endif
             {
                 printk("GDT-ISA: Unable to allocate IRQ\n");
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
@@ -2784,7 +3209,6 @@
 #else
                 free_irq(ha->irq);
 #endif
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
@@ -2793,12 +3217,6 @@
             shp->unchecked_isa_dma = 1;
             shp->irq = ha->irq;
             shp->dma_channel = ha->drq;
-            for (i=0; i<MAXID; ++i) {
-                if (ha->id[0][i].type==SIOP_DTYP) {
-                    shp->this_id = i;
-                    break;
-                }
-            }
             hanum = gdth_ctr_count;         
             gdth_ctr_tab[gdth_ctr_count++] = shp;
             gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
@@ -2807,61 +3225,56 @@
             NUMDATA(shp)->busnum= 0;
 
             ha->pccb = CMDDATA(shp);
-            ha->pscratch = DMADATA(shp);
+            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+            ha->scratch_busy = FALSE;
             ha->req_first = NULL;
-            for (i=0; i<MAXBUS; ++i) {
-                for (j=0; j<MAXID; ++j) {
-                    ha->id[i][j].type = EMPTY_DTYP;
-                    ha->id[i][j].lock = 0;
-                }
-            }
-            restore_flags(flags);
+            ha->tid_cnt = MAX_HDRIVES;
+            if (max_ids > 0 && max_ids < ha->tid_cnt)
+                ha->tid_cnt = max_ids;
+            for (i=0; i<GDTH_MAXCMDS; ++i)
+                ha->cmd_tab[i].cmnd = UNUSED_CMND;
+            ha->scan_mode = rescan ? 0x10 : 0;
 
-            if (!gdth_search_drives(hanum)) {
+            if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
                 printk("GDT-ISA: Error during device scan\n");
                 --gdth_ctr_count;
-		--gdth_ctr_vcount;
-                save_flags(flags);
-                cli();
+                --gdth_ctr_vcount;
+                if (ha->pscratch != NULL)
+                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
 #else
                 free_irq(ha->irq);
 #endif
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
 
 #if LINUX_VERSION_CODE >= 0x020000
-            shp->max_id      = 8;
-            shp->max_lun     = 8;
-            shp->max_channel = ha->bus_cnt - 1;
+            shp->max_id      = ha->tid_cnt;
+            shp->max_lun     = MAXLUN;
+            shp->max_channel = ha->bus_cnt;
 #else
             /* register addit. SCSI channels as virtual controllers */
-            for (b=1; b<ha->bus_cnt; ++b) {
+            for (b=1; b<ha->bus_cnt+1; ++b) {
                 shp = scsi_register(shtp,sizeof(gdth_num_str));
                 shp->unchecked_isa_dma = 1;
                 shp->irq = ha->irq;
                 shp->dma_channel = ha->drq;
-                for (i=0; i<MAXID; ++i) {
-                    if (ha->id[b][i].type==SIOP_DTYP) {
-                        shp->this_id = i;
-                        break;
-                    }
-                }
                 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                 NUMDATA(shp)->hanum = (ushort)hanum;
                 NUMDATA(shp)->busnum = b;
             }
 #endif
-
+            GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
     }
 
     /* scanning for EISA controllers */
     for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
+        if (gdth_ctr_count >= MAXHA) 
+            break;
         if (gdth_search_eisa(eisa_slot)) {      /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
             ha = HADATA(shp);
@@ -2873,134 +3286,117 @@
             printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
                    eisa_slot>>12,ha->irq);
 
-            save_flags(flags);
-            cli();
 #if LINUX_VERSION_CODE >= 0x010346 
-            if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
+            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
 #else
             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
 #endif
             {
                 printk("GDT-EISA: Unable to allocate IRQ\n");
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
             shp->unchecked_isa_dma = 0;
             shp->irq = ha->irq;
             shp->dma_channel = 0xff;
-            for (i=0; i<MAXID; ++i) {
-                if (ha->id[0][i].type==SIOP_DTYP) {
-                    shp->this_id = i;
-                    break;
-                }
-            }
             hanum = gdth_ctr_count;
             gdth_ctr_tab[gdth_ctr_count++] = shp;
             gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
 
             NUMDATA(shp)->hanum = (ushort)hanum;
             NUMDATA(shp)->busnum= 0;
-            TRACE2(("EISA detect Bus 0: shp %lx hanum %d\n",
-                          (ulong)shp,NUMDATA(shp)->hanum));
+            TRACE2(("EISA detect Bus 0: hanum %d\n",
+                    NUMDATA(shp)->hanum));
 
             ha->pccb = CMDDATA(shp);
-            ha->pscratch = DMADATA(shp);
+            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+            ha->scratch_busy = FALSE;
             ha->req_first = NULL;
-            for (i=0; i<MAXBUS; ++i) {
-                for (j=0; j<MAXID; ++j) {
-                    ha->id[i][j].type = EMPTY_DTYP;
-                    ha->id[i][j].lock = 0;
-                }
-            }
-            restore_flags(flags);
+            ha->tid_cnt = MAX_HDRIVES;
+            if (max_ids > 0 && max_ids < ha->tid_cnt)
+                ha->tid_cnt = max_ids;
+            for (i=0; i<GDTH_MAXCMDS; ++i)
+                ha->cmd_tab[i].cmnd = UNUSED_CMND;
+            ha->scan_mode = rescan ? 0x10 : 0;
 
-            if (!gdth_search_drives(hanum)) {
+            if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
                 printk("GDT-EISA: Error during device scan\n");
                 --gdth_ctr_count;
-		--gdth_ctr_vcount;
-                save_flags(flags);
-                cli();
+                --gdth_ctr_vcount;
+                if (ha->pscratch != NULL)
+                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
 #else
                 free_irq(ha->irq);
 #endif
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
 
 #if LINUX_VERSION_CODE >= 0x020000
-            shp->max_id      = 8;
-            shp->max_lun     = 8;
-            shp->max_channel = ha->bus_cnt - 1;
+            shp->max_id      = ha->tid_cnt;
+            shp->max_lun     = MAXLUN;
+            shp->max_channel = ha->bus_cnt;
 #else
             /* register addit. SCSI channels as virtual controllers */
-            for (b=1; b<ha->bus_cnt; ++b) {
+            for (b=1; b<ha->bus_cnt+1; ++b) {
                 shp = scsi_register(shtp,sizeof(gdth_num_str));
                 shp->unchecked_isa_dma = 0;
                 shp->irq = ha->irq;
                 shp->dma_channel = 0xff;
-                for (i=0; i<MAXID; ++i) {
-                    if (ha->id[b][i].type==SIOP_DTYP) {
-                        shp->this_id = i;
-                        break;
-                    }
-                }
                 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                 NUMDATA(shp)->hanum = (ushort)hanum;
                 NUMDATA(shp)->busnum = b;
-                TRACE2(("EISA detect Bus %d: shp %lx hanum %d\n",
-                              NUMDATA(shp)->busnum,(ulong)shp,
-                              NUMDATA(shp)->hanum));
+                TRACE2(("EISA detect Bus %d: shp %x hanum %d\n",
+                        NUMDATA(shp)->busnum,(ulong32)shp,
+                        NUMDATA(shp)->hanum));
             }
 #endif
-
+            GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
     }
 
     /* scanning for PCI controllers */
-    for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDT6x21RP2; ++device_id) {
-        if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
-            device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
-            continue;
-        for (index = 0; ; ++index) {
-            if (!gdth_search_pci(device_id,index,&pcistr)) 
-                break;                          /* next device_id */
+#if LINUX_VERSION_CODE >= 0x2015C
+    if (pci_present())
+#else
+    if (pcibios_present())
+#endif
+    {
+        gdth_pci_str pcistr[MAXHA];
+
+        cnt = gdth_search_pci(pcistr);
+        gdth_sort_pci(pcistr,cnt);
+        for (ctr = 0; ctr < cnt; ++ctr) {
+            if (gdth_ctr_count >= MAXHA)
+                break;
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
             ha = HADATA(shp);
-            if (!gdth_init_pci(&pcistr,ha)) {
+            if (!gdth_init_pci(&pcistr[ctr],ha)) {
                 scsi_unregister(shp);
                 continue;
             }
             /* controller found and initialized */
             printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
-                   pcistr.bus,pcistr.device_fn>>3,ha->irq);
+                   pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
 
-            save_flags(flags);
-            cli();
 #if LINUX_VERSION_CODE >= 0x010346 
-            if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
+            if (request_irq(ha->irq, gdth_interrupt,
+                            SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
 #else
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
+            if (request_irq(ha->irq, gdth_interrupt,
+                            SA_INTERRUPT|SA_SHIRQ, "gdth")) 
 #endif
             {
                 printk("GDT-PCI: Unable to allocate IRQ\n");
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
             shp->unchecked_isa_dma = 0;
             shp->irq = ha->irq;
             shp->dma_channel = 0xff;
-            for (i=0; i<MAXID; ++i) {
-                if (ha->id[0][i].type==SIOP_DTYP) {
-                    shp->this_id = i;
-                    break;
-                }
-            }
             hanum = gdth_ctr_count;
             gdth_ctr_tab[gdth_ctr_count++] = shp;
             gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
@@ -3009,55 +3405,48 @@
             NUMDATA(shp)->busnum= 0;
 
             ha->pccb = CMDDATA(shp);
-            ha->pscratch = DMADATA(shp);
+            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+            ha->scratch_busy = FALSE;
             ha->req_first = NULL;
-            for (i=0; i<MAXBUS; ++i) {
-                for (j=0; j<MAXID; ++j) {
-                    ha->id[i][j].type = EMPTY_DTYP;
-                    ha->id[i][j].lock = 0;
-                }
-            }
-            restore_flags(flags);
+            ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
+            if (max_ids > 0 && max_ids < ha->tid_cnt)
+                ha->tid_cnt = max_ids;
+            for (i=0; i<GDTH_MAXCMDS; ++i)
+                ha->cmd_tab[i].cmnd = UNUSED_CMND;
+            ha->scan_mode = rescan ? 0x10 : 0;
 
-            if (!gdth_search_drives(hanum)) {
+            if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
                 printk("GDT-PCI: Error during device scan\n");
                 --gdth_ctr_count;
-		--gdth_ctr_vcount;
-                save_flags(flags);
-                cli();
+                --gdth_ctr_vcount;
+                if (ha->pscratch != NULL)
+                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
 #if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
 #else
                 free_irq(ha->irq);
 #endif
-                restore_flags(flags);
                 scsi_unregister(shp);
                 continue;
             }
 
 #if LINUX_VERSION_CODE >= 0x020000
-            shp->max_id      = 8;
-            shp->max_lun     = 8;
-            shp->max_channel = ha->bus_cnt - 1;
+            shp->max_id      = ha->tid_cnt;
+            shp->max_lun     = MAXLUN;
+            shp->max_channel = ha->bus_cnt;
 #else
             /* register addit. SCSI channels as virtual controllers */
-            for (b=1; b<ha->bus_cnt; ++b) {
+            for (b=1; b<ha->bus_cnt+1; ++b) {
                 shp = scsi_register(shtp,sizeof(gdth_num_str));
                 shp->unchecked_isa_dma = 0;
                 shp->irq = ha->irq;
                 shp->dma_channel = 0xff;
-                for (i=0; i<MAXID; ++i) {
-                    if (ha->id[b][i].type==SIOP_DTYP) {
-                        shp->this_id = i;
-                        break;
-                    }
-                }
                 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                 NUMDATA(shp)->hanum = (ushort)hanum;
                 NUMDATA(shp)->busnum = b;
             }
 #endif
-
+            GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
     }
@@ -3065,13 +3454,15 @@
     TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
     if (gdth_ctr_count > 0) {
 #ifdef GDTH_STATISTICS
-	TRACE2(("gdth_detect(): Initializing timer !\n"));
-	timer_table[GDTH_TIMER].fn = gdth_timeout;
-	timer_table[GDTH_TIMER].expires = jiffies + HZ;
-	timer_active |= 1<<GDTH_TIMER;
+        TRACE2(("gdth_detect(): Initializing timer !\n"));
+        init_timer(&gdth_timer);
+        gdth_timer.expires = jiffies + HZ;
+        gdth_timer.data = 0L;
+        gdth_timer.function = gdth_timeout;
+        add_timer(&gdth_timer);
 #endif
 #if LINUX_VERSION_CODE >= 0x020100
-	register_reboot_notifier(&gdth_notifier);
+        register_reboot_notifier(&gdth_notifier);
 #endif
     }
     gdth_polling = FALSE;
@@ -3081,13 +3472,15 @@
 
 int gdth_release(struct Scsi_Host *shp)
 {
-    unsigned long flags;
+    int hanum;
+    gdth_ha_str *ha;
 
     TRACE2(("gdth_release()\n"));
-
-    save_flags(flags);
-    cli();
     if (NUMDATA(shp)->busnum == 0) {
+        hanum = NUMDATA(shp)->hanum;
+        ha    = HADATA(gdth_ctr_tab[hanum]);
+        gdth_flush(hanum);
+
         if (shp->irq) {
 #if LINUX_VERSION_CODE >= 0x010346
             free_irq(shp->irq,NULL);
@@ -3098,9 +3491,21 @@
         if (shp->dma_channel != 0xff) {
             free_dma(shp->dma_channel);
         }
+        scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+        gdth_ctr_released++;
+        TRACE2(("gdth_release(): HA %d of %d\n", 
+                gdth_ctr_released, gdth_ctr_count));
+
+        if (gdth_ctr_released == gdth_ctr_count) {
+#ifdef GDTH_STATISTICS
+            del_timer(&gdth_timer);
+#endif
+#if LINUX_VERSION_CODE >= 0x020100
+            unregister_reboot_notifier(&gdth_notifier);
+#endif
+        }
     }
 
-    restore_flags(flags);
     scsi_unregister(shp);
     return 0;
 }
@@ -3117,102 +3522,40 @@
     if (ha->type == GDT_EISA) {
         switch (ha->stype) {
           case GDT3_ID:
-            return("GDT3000/3020 (EISA)");
+            return("GDT3000/3020");
           case GDT3A_ID:
-            return("GDT3000A/3020A/3050A (EISA)");
+            return("GDT3000A/3020A/3050A");
           case GDT3B_ID:
-            return("GDT3000B/3010A (EISA)");
+            return("GDT3000B/3010A");
         }
     } else if (ha->type == GDT_ISA) {
-        return("GDT2000/2020 (ISA)");
+        return("GDT2000/2020");
     } else if (ha->type == GDT_PCI) {
         switch (ha->stype) {
           case PCI_DEVICE_ID_VORTEX_GDT60x0:
-            return("GDT6000/6020/6050 (PCI)");
+            return("GDT6000/6020/6050");
           case PCI_DEVICE_ID_VORTEX_GDT6000B:
-            return("GDT6000B/6010 (PCI)");
-        }
-    } else if (ha->type == GDT_PCINEW) {
-        switch (ha->stype) {
-          case PCI_DEVICE_ID_VORTEX_GDT6x10:
-            return("GDT6110/6510 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x20:
-            return("GDT6120/6520 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6530:
-            return("GDT6530 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6550:
-            return("GDT6550 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x17:
-            return("GDT6117/6517 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x27:
-            return("GDT6127/6527 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6537:
-            return("GDT6537 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6557:
-            return("GDT6557/6557-ECC (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x15:
-            return("GDT6115/6515 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x25:
-            return("GDT6125/6525 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6535:
-            return("GDT6535 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6555:
-            return("GDT6555/6555-ECC (PCI)");
-        }
-    } else if (ha->type == GDT_PCIMPR) {
-        switch (ha->stype) {
-          case PCI_DEVICE_ID_VORTEX_GDT6x17RP:
-            return("GDT6117RP/GDT6517RP (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x27RP:
-            return("GDT6127RP/GDT6527RP (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6537RP:
-            return("GDT6537RP (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6557RP:
-            return("GDT6557RP (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x11RP:
-            return("GDT6111RP/GDT6511RP (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x21RP:
-            return("GDT6121RP/GDT6521RP (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x17RP1:
-            return("GDT6117RP1/GDT6517RP1 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x27RP1:
-            return("GDT6127RP1/GDT6527RP1 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6537RP1:
-            return("GDT6537RP1 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6557RP1:
-            return("GDT6557RP1 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x11RP1:
-            return("GDT6111RP1/GDT6511RP1 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x21RP1:
-            return("GDT6121RP1/GDT6521RP1 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x17RP2:
-            return("GDT6117RP2/GDT6517RP2 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x27RP2:
-            return("GDT6127RP2/GDT6527RP2 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6537RP2:
-            return("GDT6537RP2 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6557RP2:
-            return("GDT6557RP2 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x11RP2:
-            return("GDT6111RP2/GDT6511RP2 (PCI)");
-          case PCI_DEVICE_ID_VORTEX_GDT6x21RP2:
-            return("GDT6121RP2/GDT6521RP2 (PCI)");
+            return("GDT6000B/6010");
         }
-    }
+    } 
+    /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
+
     return("");
 }
 
 const char *gdth_info(struct Scsi_Host *shp)
 {
     int hanum;
-    
+    gdth_ha_str *ha;
+
     TRACE2(("gdth_info()\n"));
     hanum = NUMDATA(shp)->hanum;
+    ha    = HADATA(gdth_ctr_tab[hanum]);
 
-    return (gdth_ctr_name(hanum));
+    return ((const char *)ha->ctr_name);
 }
 
-
+/* old error handling */
 int gdth_abort(Scsi_Cmnd *scp)
 {
     TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
@@ -3229,6 +3572,32 @@
     return SCSI_RESET_PUNT;
 }
 
+#if LINUX_VERSION_CODE >= 0x02015F
+/* new error handling */
+int gdth_eh_abort(Scsi_Cmnd *scp)
+{
+    TRACE2(("gdth_eh_abort()\n"));
+    return FAILED;
+}
+
+int gdth_eh_device_reset(Scsi_Cmnd *scp)
+{
+    TRACE2(("gdth_eh_device_reset()\n"));
+    return FAILED;
+}
+
+int gdth_eh_bus_reset(Scsi_Cmnd *scp)
+{
+    TRACE2(("gdth_eh_bus_reset()\n"));
+    return FAILED;
+}
+
+int gdth_eh_host_reset(Scsi_Cmnd *scp)
+{
+    TRACE2(("gdth_eh_host_reset()\n"));
+    return FAILED;
+}
+#endif
 
 #if LINUX_VERSION_CODE >= 0x010300
 int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
@@ -3236,18 +3605,36 @@
 int gdth_bios_param(Disk *disk,int dev,int *ip)
 #endif
 {
-    unchar b, t;
+    unchar t;
     int hanum;
     gdth_ha_str *ha;
+    int drv_hds, drv_secs;
 
     hanum = NUMDATA(disk->device->host)->hanum;
-    b = disk->device->channel;
     t = disk->device->id;
-    TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
+    TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", 
+            hanum, disk->device->channel, t));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-    ip[0] = ha->id[b][t].heads;
-    ip[1] = ha->id[b][t].secs;
+    if (ha->hdr[t].heads == 0) {
+        /* raw device: evaluate mapping (sectors per head, heads per cylinder) */
+        if (disk->capacity /HEADS/SECS <= MAXCYLS) {
+            drv_hds = HEADS;
+            drv_secs= SECS;
+        } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) {
+            drv_hds = MEDHEADS;
+            drv_secs= MEDSECS;
+        } else {
+            drv_hds = BIGHEADS;
+            drv_secs= BIGSECS;
+        }
+        ha->hdr[t].heads = drv_hds;
+        ha->hdr[t].secs = drv_secs;
+        TRACE2(("gdth_bios_param(): raw device -> params evaluated\n"));
+    }
+
+    ip[0] = ha->hdr[t].heads;
+    ip[1] = ha->hdr[t].secs;
     ip[2] = disk->capacity / ip[0] / ip[1];
 
     TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
@@ -3280,10 +3667,12 @@
     int priority;
 
     TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
-                  scp->cmnd[0],scp->target,scp->lun));
+           scp->cmnd[0],scp->target,scp->lun));
     
     scp->scsi_done = (void *)done;
-    scp->SCp.have_data_in = 0;
+    scp->SCp.have_data_in = 1;
+    scp->SCp.phase = -1;
+    scp->SCp.Status = -1;
     hanum = NUMDATA(scp->host)->hanum;
 #ifdef GDTH_STATISTICS
     ++act_ios;
@@ -3299,6 +3688,52 @@
     return 0;
 }
 
+/* flush routine */
+static void gdth_flush(int hanum)
+{
+    int             i;
+    gdth_ha_str     *ha;
+    Scsi_Cmnd       scp;
+    Scsi_Device     sdev;
+    gdth_cmd_str    gdtcmd;
+    char            cmnd[12];
+
+    TRACE2(("gdth_flush() hanum %d\n",hanum));
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    memset(&sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    sdev.host = gdth_ctr_tab[hanum];
+    sdev.id = sdev.host->this_id;
+    scp.cmd_len = 12;
+    scp.host = gdth_ctr_tab[hanum];
+    scp.target = sdev.host->this_id;
+    scp.device = &sdev;
+    scp.use_sg = 0;
+
+    for (i = 0; i < MAX_HDRIVES; ++i) {
+        if (ha->hdr[i].present) {
+            gdtcmd.BoardNode = LOCALBOARD;
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_FLUSH;
+            gdtcmd.u.cache.DeviceNo = i;
+            gdtcmd.u.cache.BlockNo = 1;
+            gdtcmd.u.cache.sg_canz = 0;
+            TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
+            {
+                struct semaphore sem = MUTEX_LOCKED;
+                scp.request.rq_status = RQ_SCSI_BUSY;
+                scp.request.sem = &sem;
+                scp.SCp.this_residual = IOCTL_PRI;
+                GDTH_LOCK_SCSI_DOCMD();
+                scsi_do_cmd(&scp, cmnd, &gdtcmd,
+                            sizeof(gdth_cmd_str), gdth_scsi_done,
+                            30*HZ, 1);
+                GDTH_UNLOCK_SCSI_DOCMD();
+                down(&sem);
+            }
+        }
+    }
+}
 
 /* shutdown routine */
 #if LINUX_VERSION_CODE >= 0x020100
@@ -3307,23 +3742,32 @@
 void gdth_halt(void)
 #endif
 {
-    int             hanum, i, j;
-    gdth_ha_str     *ha;
+    int             hanum;
+#ifndef __alpha__
     Scsi_Cmnd       scp;
     Scsi_Device     sdev;
     gdth_cmd_str    gdtcmd;
     char            cmnd[12];
+#endif
 
 #if LINUX_VERSION_CODE >= 0x020100
     TRACE2(("gdth_halt() event %d\n",event));
     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
-	return NOTIFY_DONE;
+        return NOTIFY_DONE;
 #else
     TRACE2(("gdth_halt()\n"));
+    if (halt_called) {
+        TRACE2(("already called\n"));
+        return;
+    }
+    halt_called = TRUE;
 #endif
     printk("GDT: Flushing all host drives .. ");
     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
-        ha = HADATA(gdth_ctr_tab[hanum]);
+        gdth_flush(hanum);
+
+#ifndef __alpha__
+        /* controller reset */
         memset(&sdev,0,sizeof(Scsi_Device));
         memset(&scp, 0,sizeof(Scsi_Cmnd));
         sdev.host = gdth_ctr_tab[hanum];
@@ -3334,32 +3778,6 @@
         scp.device = &sdev;
         scp.use_sg = 0;
 
-        /* flush */
-        for (i = 0; i < MAXBUS; ++i) {
-            for (j = 0; j < MAXID; ++j) {
-                if (ha->id[i][j].type == CACHE_DTYP) {
-                    gdtcmd.BoardNode = LOCALBOARD;
-                    gdtcmd.Service = CACHESERVICE;
-                    gdtcmd.OpCode = GDT_FLUSH;
-                    gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive;
-                    gdtcmd.u.cache.BlockNo = 1;
-                    gdtcmd.u.cache.sg_canz = 0;
-                    TRACE2(("gdth_halt(): flush ha %d drive %d\n",
-                        hanum, ha->id[i][j].hostdrive));
-                    {
-                        struct semaphore sem = MUTEX_LOCKED;
-                        scp.request.rq_status = RQ_SCSI_BUSY;
-                        scp.request.sem = &sem;
-                        scsi_do_cmd(&scp, cmnd, &gdtcmd,
-                                    sizeof(gdth_cmd_str), gdth_scsi_done,
-                                    30*HZ, 1);
-                        down(&sem);
-                    }
-                }
-            }
-        }
-
-        /* controller reset */
         gdtcmd.BoardNode = LOCALBOARD;
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_RESET;
@@ -3368,16 +3786,20 @@
             struct semaphore sem = MUTEX_LOCKED;
             scp.request.rq_status = RQ_SCSI_BUSY;
             scp.request.sem = &sem;
+            scp.SCp.this_residual = IOCTL_PRI;
+            GDTH_LOCK_SCSI_DOCMD();
             scsi_do_cmd(&scp, cmnd, &gdtcmd,
                 sizeof(gdth_cmd_str), gdth_scsi_done,
                 10*HZ, 1);
+            GDTH_UNLOCK_SCSI_DOCMD();
             down(&sem);
         }
+#endif
     }
     printk("Done.\n");
 
 #ifdef GDTH_STATISTICS
-    timer_active &= ~(1<<GDTH_TIMER);
+    del_timer(&gdth_timer);
 #endif
 #if LINUX_VERSION_CODE >= 0x020100
     unregister_reboot_notifier(&gdth_notifier);
@@ -3387,35 +3809,69 @@
 
 
 /* called from init/main.c */
-void gdth_setup(char *str,int *ints)
+__initfunc (void gdth_setup(char *str,int *ints))
 {
-    static size_t setup_idx = 0;
+    int i, argc;
+    char *cur_str, *argv;
 
-    TRACE2(("gdth_setup() str %s ints[0] %d ints[1] %d\n",
-                  str ? str:"NULL", ints[0],
-                  ints[0] ? ints[1]:0));
+    TRACE2(("gdth_setup() str %s ints[0] %d\n", 
+            str ? str:"NULL", ints ? ints[0]:0));
 
-    if (setup_idx >= MAXHA) {
-        printk("GDT: gdth_setup() called too many times. Bad LILO params ?\n");
-        return;
-    }
-    if (ints[0] != 1) {
-        printk("GDT: Illegal command line !\n");
-        printk("Usage: gdth=<IRQ>\n");
-        printk("Where: <IRQ>: valid EISA controller IRQ (10,11,12,14)\n");
-        printk("              or 0 to disable controller driver\n");
-        return;
-    }
-    if (ints[1] == 10 || ints[1] == 11 || ints[1] == 12 || ints[1] == 14) {
-        irqs[setup_idx++] = ints[1];
-        irqs[setup_idx]   = 0xff;
-        return;
+    /* read irq[] from ints[] */
+    if (ints) {
+        argc = ints[0];
+        if (argc > 0) {
+            if (argc > MAXHA)
+                argc = MAXHA;
+            for (i = 0; i < argc; ++i)
+                irq[i] = ints[i+1];
+        }
     }
-    if (ints[1] == 0) {
-        disable_gdth_scan = TRUE;
-        return;
+
+    /* analyse string */
+    argv = str;
+    while (argv && (cur_str = strchr(argv, ':'))) {
+        int val = 0, c = *++cur_str;
+        
+        if (c == 'n' || c == 'N')
+            val = 0;
+        else if (c == 'y' || c == 'Y')
+            val = 1;
+        else
+            val = (int)simple_strtoul(cur_str, NULL, 0);
+
+        if (!strncmp(argv, "disable:", 8))
+            disable = val;
+        else if (!strncmp(argv, "reserve_mode:", 13))
+            reserve_mode = val;
+        else if (!strncmp(argv, "reverse_scan:", 13))
+            reverse_scan = val;
+        else if (!strncmp(argv, "max_ids:", 8))
+            max_ids = val;
+        else if (!strncmp(argv, "rescan:", 7))
+            rescan = val;
+        else if (!strncmp(argv, "reserve_list:", 13)) {
+            reserve_list[0] = val;
+            for (i = 1; i < MAX_RES_ARGS; i++) {
+                cur_str = strchr(cur_str, ',');
+                if (!cur_str)
+                    break;
+                if (!isdigit((int)*++cur_str)) {
+                    --cur_str;          
+                    break;
+                }
+                reserve_list[i] = 
+                    (int)simple_strtoul(cur_str, NULL, 0);
+            }
+            if (!cur_str)
+                break;
+            argv = ++cur_str;
+            continue;
+        }
+
+        if ((argv = strchr(argv, ',')))
+            ++argv;
     }
-    printk("GDT: Invalid IRQ (%d) specified\n",ints[1]);
 }
 
 
@@ -3423,4 +3879,3 @@
 Scsi_Host_Template driver_template = GDTH;
 #include "scsi_module.c"
 #endif
-
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h
--- v2.2.0-pre6/linux/drivers/scsi/gdth.h	Fri Jul 31 17:07:59 1998
+++ linux/drivers/scsi/gdth.h	Mon Jan 11 10:35:50 1999
@@ -4,13 +4,13 @@
 /*
  * Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux
  * 
- * gdth.h Copyright (C) 1995-97 ICP vortex Computersysteme GmbH, Achim Leubner
+ * gdth.h Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner
  * See gdth.c for further informations and 
  * below for supported controller types
  *
  * <achim@vortex.de>
  *
- * $Id: gdth.h,v 1.9 1997/11/04 09:55:42 achim Exp $
+ * $Id: gdth.h,v 1.16 1998/12/17 15:54:53 achim Exp $
  */
 
 #include <linux/version.h>
@@ -29,9 +29,9 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "1.02"
+#define GDTH_VERSION_STR        "1.10"
 #define GDTH_VERSION            1
-#define GDTH_SUBVERSION         2
+#define GDTH_SUBVERSION         10
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
@@ -48,11 +48,13 @@
 #define GDT3B_ID        0x0330941c              /* GDT3000B/3010A */
 /* GDT_ISA */
 #define GDT2_ID         0x0120941c              /* GDT2000/2020 */
+
 /* vendor ID, device IDs (PCI) */
 /* these defines should already exist in <linux/pci.h> */
 #ifndef PCI_VENDOR_ID_VORTEX
 #define PCI_VENDOR_ID_VORTEX            0x1119  /* PCI controller vendor ID */
 #endif
+
 #ifndef PCI_DEVICE_ID_VORTEX_GDT60x0
 /* GDT_PCI */
 #define PCI_DEVICE_ID_VORTEX_GDT60x0    0       /* GDT6000/6020/6050 */
@@ -83,22 +85,44 @@
 /* GDT_MPR, RP series, narrow/ultra SCSI */
 #define PCI_DEVICE_ID_VORTEX_GDT6x11RP  0x104   /* GDT6111RP/GDT6511RP */
 #define PCI_DEVICE_ID_VORTEX_GDT6x21RP  0x105   /* GDT6121RP/GDT6521RP */
-/* GDT_MPR, RP1 series, wide/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1 0x110   /* GDT6117RP1/GDT6517RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1 0x111   /* GDT6127RP1/GDT6527RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP1 0x112   /* GDT6537RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP1 0x113   /* GDT6557RP1 */
-/* GDT_MPR, RP1 series, narrow/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1 0x114   /* GDT6111RP1/GDT6511RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1 0x115   /* GDT6121RP1/GDT6521RP1 */
-/* GDT_MPR, RP2 series, wide/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2 0x120   /* GDT6117RP2/GDT6517RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2 0x121   /* GDT6127RP2/GDT6527RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP2 0x122   /* GDT6537RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP2 0x123   /* GDT6557RP2 */
-/* GDT_MPR, RP2 series, narrow/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2 0x124   /* GDT6111RP2/GDT6511RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2 0x125   /* GDT6121RP2/GDT6521RP2 */
+#endif
+#ifndef PCI_DEVICE_ID_VORTEX_GDT6x17RD
+/* GDT_MPR, RD series, wide/ultra SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RD  0x110   /* GDT6117RD/GDT6517RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RD  0x111   /* GDT6127RD/GDT6527RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6537RD  0x112   /* GDT6537RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6557RD  0x113   /* GDT6557RD */
+/* GDT_MPR, RD series, narrow/ultra SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RD  0x114   /* GDT6111RD/GDT6511RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RD  0x115   /* GDT6121RD/GDT6521RD */
+/* GDT_MPR, RD series, wide/ultra2 SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT6x18RD  0x118   /* GDT6118RD/GDT6518RD/
+                                                   GDT6618RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x28RD  0x119   /* GDT6128RD/GDT6528RD/
+                                                   GDT6628RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x38RD  0x11A   /* GDT6538RD/GDT6638RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x58RD  0x11B   /* GDT6558RD/GDT6658RD */
+/* GDT_MPR, RN series (64-bit PCI), wide/ultra2 SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT7x18RN  0x168   /* GDT7118RN/GDT7518RN/
+                                                   GDT7618RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x28RN  0x169   /* GDT7128RN/GDT7528RN/
+                                                   GDT7628RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x38RN  0x16A   /* GDT7538RN/GDT7638RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x58RN  0x16B   /* GDT7558RN/GDT7658RN */
+#endif
+
+#ifndef PCI_DEVICE_ID_VORTEX_GDT6x19RD
+/* GDT_MPR, RD series, Fibre Channel */
+#define PCI_DEVICE_ID_VORTEX_GDT6x19RD  0x210   /* GDT6519RD/GDT6619RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x29RD  0x211   /* GDT6529RD/GDT6629RD */
+/* GDT_MPR, RN series (64-bit PCI), Fibre Channel */
+#define PCI_DEVICE_ID_VORTEX_GDT7x19RN  0x260   /* GDT7519RN/GDT7619RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x29RN  0x261   /* GDT7529RN/GDT7629RN */
+#endif
+
+#ifndef PCI_DEVICE_ID_VORTEX_GDTMAXRP
+/* GDT_MPR, last device ID */
+#define PCI_DEVICE_ID_VORTEX_GDTMAXRP   0x2ff   
 #endif
 
 /* limits */
@@ -106,12 +130,14 @@
 #define GDTH_MAXCMDS    124
 #define GDTH_MAXC_P_L   16                      /* max. cmds per lun */
 #define MAXOFFSETS      128
-#define MAXHA           8
-#define MAXID           8
+#define MAXHA           16
+#define MAXID           127
 #define MAXLUN          8
-#define MAXBUS          5
+#define MAXBUS          6
 #define MAX_HDRIVES     35                      /* max. host drive count */
 #define MAX_EVENTS      100                     /* event buffer count */
+#define MAX_RES_ARGS    40                      /* device reservation, 
+                                                   must be a multiple of 4 */
 #define MAXCYLS         1024
 #define HEADS           64
 #define SECS            32                      /* mapping 64*32 */
@@ -126,12 +152,6 @@
 #define SCREEN_CMND     ((Scsi_Cmnd *)-3)
 #define SPECIAL_SCP(p)  (p==UNUSED_CMND || p==INTERNAL_CMND || p==SCREEN_CMND)
 
-/* device types */
-#define EMPTY_DTYP      0
-#define CACHE_DTYP      1
-#define RAW_DTYP        2
-#define SIOP_DTYP       3                       /* the SCSI processor */
-
 /* controller services */
 #define SCSIRAWSERVICE  3
 #define CACHESERVICE    9
@@ -144,14 +164,15 @@
 #define MSG_REQUEST     0                       /* async. event: message */
 
 /* cacheservice defines */
-#define SECTOR_SIZE     0x200                   /* always 512 bytes per sector */
+#define SECTOR_SIZE     0x200                   /* always 512 bytes per sec. */
 
 /* DPMEM constants */
+#define DPMEM_MAGIC     0xC0FFEE11
 #define IC_HEADER_BYTES 48
 #define IC_QUEUE_BYTES  4
 #define DPMEM_COMMAND_OFFSET    IC_HEADER_BYTES+IC_QUEUE_BYTES*MAXOFFSETS
 
-/* service commands */
+/* cache/raw service commands */
 #define GDT_INIT        0                       /* service initialization */
 #define GDT_READ        1                       /* read command */
 #define GDT_WRITE       2                       /* write command */
@@ -163,16 +184,27 @@
 #define GDT_UNMOUNT     11                      /* unmount cache device */
 #define GDT_SET_FEAT    12                      /* set feat. (scatter/gather) */
 #define GDT_GET_FEAT    13                      /* get features */
-#define GDT_RESERVE     14                      /* reserve dev. to raw service */
 #define GDT_WRITE_THR   16                      /* write through */
+#define GDT_READ_THR    17                      /* read through */
 #define GDT_EXT_INFO    18                      /* extended info */
 #define GDT_RESET       19                      /* controller reset */
 
+/* additional raw service commands */
+#define GDT_RESERVE     14                      /* reserve dev. to raw serv. */
+#define GDT_RELEASE     15                      /* release device */
+#define GDT_RESERVE_ALL 16                      /* reserve all devices */
+#define GDT_RELEASE_ALL 17                      /* release all devices */
+#define GDT_RESET_BUS   18                      /* reset bus */
+#define GDT_SCAN_START  19                      /* start device scan */
+#define GDT_SCAN_END    20                      /* stop device scan */  
+
 /* IOCTL command defines */
 #define SCSI_CHAN_CNT   5                       /* subfunctions */
+#define GET_IOCHAN_DESC 0x5e
 #define L_CTRL_PATTERN  0x20000000L
 #define CACHE_INFO      4
 #define CACHE_CONFIG    5
+#define BOARD_INFO      0x28
 #define IO_CHANNEL      0x00020000L             /* channels */
 #define INVALID_CHANNEL 0x0000ffffL     
 
@@ -200,6 +232,7 @@
 /* priorities */
 #define DEFAULT_PRI     0x20
 #define IOCTL_PRI       0x10
+#define HIGH_PRI        0x08
 
 /* data directions */
 #define DATA_IN         0x01000000L             /* data from target */
@@ -211,7 +244,7 @@
 #define SEMA0REG        0x0c8a                  /* command semaphore */
 #define SEMA1REG        0x0c8b                  /* status semaphore */
 #define LDOORREG        0x0c8d                  /* local doorbell */
-#define EDENABREG       0x0c8e                  /* EISA system doorbell enable */
+#define EDENABREG       0x0c8e                  /* EISA system doorbell enab. */
 #define EDOORREG        0x0c8f                  /* EISA system doorbell */
 #define MAILBOXREG      0x0c90                  /* mailbox reg. (16 bytes) */
 #define EISAREG         0x0cc0                  /* EISA configuration */
@@ -221,119 +254,160 @@
 #define SCATTER_GATHER  1                       /* s/g feature */
 #define GDTH_MAXSG      32                      /* max. s/g elements */
 #define SECS32          0x1f                    /* round capacity */
-#define BIOS_ID_OFFS    0x10                    /* offset contr. ID in ISABIOS */
+#define BIOS_ID_OFFS    0x10                    /* offset contr-ID in ISABIOS */
 #define LOCALBOARD      0                       /* board node always 0 */
 #define ASYNCINDEX      0                       /* cmd index async. event */
 #define SPEZINDEX       1                       /* cmd index unknown service */
 #define GDT_WR_THROUGH  0x100                   /* WRITE_THROUGH supported */
 
-/* typedefs */
-
-#pragma pack(1)
 
-typedef struct {
-    char        buffer[GDTH_SCRATCH];           /* scratch buffer */
-} gdth_scratch_str;
+/* typedefs */
+typedef u32     ulong32;
+#define PACKED  __attribute__((packed))
 
 /* screenservice message */
 typedef struct {                               
-    ulong       msg_handle;                     /* message handle */
-    ulong       msg_len;                        /* size of message */
-    ulong       msg_alen;                       /* answer length */
+    ulong32     msg_handle;                     /* message handle */
+    ulong32     msg_len;                        /* size of message */
+    ulong32     msg_alen;                       /* answer length */
     unchar      msg_answer;                     /* answer flag */
     unchar      msg_ext;                        /* more messages */
     unchar      msg_reserved[2];
     char        msg_text[MSGLEN+2];             /* the message text */
-} gdth_msg_str;
+} PACKED gdth_msg_str;
 
 /* get channel count IOCTL */
 typedef struct {
-    ulong       channel_no;                     /* number of channel */
-    ulong       drive_cnt;                      /* number of drives */
+    ulong32     channel_no;                     /* number of channel */
+    ulong32     drive_cnt;                      /* number of drives */
     unchar      siop_id;                        /* SCSI processor ID */
     unchar      siop_state;                     /* SCSI processor state */ 
-} gdth_getch_str;
+} PACKED gdth_getch_str;
+
+/* get raw channel count IOCTL (NEW!) */
+typedef struct {
+    ulong32     version;            /* version of information (-1UL: newest) */
+    unchar      list_entries;       /* list entry count */
+    unchar      first_chan;         /* first channel number */
+    unchar      last_chan;          /* last channel number */
+    unchar      chan_count;         /* (R) channel count */
+    ulong32     list_offset;        /* offset of list[0] */
+    struct {
+        unchar      proc_id;            /* processor id */
+        unchar      proc_defect;        /* defect ? */
+        unchar      reserved[2];
+    } PACKED list[MAXBUS];
+} PACKED gdth_iochan_str;
 
 /* cache info/config IOCTL */
 typedef struct {
-    ulong       version;                        /* firmware version */
+    ulong32     version;                        /* firmware version */
     ushort      state;                          /* cache state (on/off) */
     ushort      strategy;                       /* cache strategy */
     ushort      write_back;                     /* write back state (on/off) */
     ushort      block_size;                     /* cache block size */
-} gdth_cpar_str;
+} PACKED gdth_cpar_str;
 
 typedef struct {
-    ulong       csize;                          /* cache size */
-    ulong       read_cnt;                       /* read/write counter */
-    ulong       write_cnt;
-    ulong       tr_hits;                        /* hits */
-    ulong       sec_hits;
-    ulong       sec_miss;                       /* misses */
-} gdth_cstat_str;
+    ulong32     csize;                          /* cache size */
+    ulong32     read_cnt;                       /* read/write counter */
+    ulong32     write_cnt;
+    ulong32     tr_hits;                        /* hits */
+    ulong32     sec_hits;
+    ulong32     sec_miss;                       /* misses */
+} PACKED gdth_cstat_str;
 
 typedef struct {
     gdth_cpar_str   cpar;
     gdth_cstat_str  cstat;
-} gdth_cinfo_str;
+} PACKED gdth_cinfo_str;
+
+/* board info IOCTL */
+typedef struct {
+    ulong32     ser_no;                         /* serial no. */
+    unchar      oem_id[2];                      /* OEM ID */
+    ushort      ep_flags;                       /* eprom flags */
+    ulong32     proc_id;                        /* processor ID */
+    ulong32     memsize;                        /* memory size (bytes) */
+    unchar      mem_banks;                      /* memory banks */
+    unchar      chan_type;                      /* channel type */
+    unchar      chan_count;                     /* channel count */
+    unchar      rdongle_pres;                   /* dongle present? */
+    ulong32     epr_fw_ver;                     /* (eprom) firmware version */
+    ulong32     upd_fw_ver;                     /* (update) firmware version */
+    ulong32     upd_revision;                   /* update revision */
+    char        type_string[16];                /* controller name */
+    char        raid_string[16];                /* RAID firmware name */
+    unchar      update_pres;                    /* update present? */
+    unchar      xor_pres;                       /* XOR engine present? */
+    unchar      prom_type;                      /* ROM type (eprom/flash) */
+    unchar      prom_count;                     /* number of ROM devices */
+    ulong32     dup_pres;                       /* duplexing module present? */
+    ulong32     chan_pres;                      /* number of expansion chn. */
+    ulong32     mem_pres;                       /* memory expansion inst. ? */
+    unchar      ft_bus_system;                  /* fault bus supported? */
+    unchar      subtype_valid;                  /* board_subtype valid? */
+    unchar      board_subtype;                  /* subtype/hardware level */
+    unchar      ramparity_pres;                 /* RAM parity check hardware? */
+} PACKED gdth_binfo_str; 
 
 /* scatter/gather element */
 typedef struct {
-    ulong       sg_ptr;                         /* address */
-    ulong       sg_len;                         /* length */
-} gdth_sg_str;
+    ulong32     sg_ptr;                         /* address */
+    ulong32     sg_len;                         /* length */
+} PACKED gdth_sg_str;
 
 /* command structure */
 typedef struct {
-    ulong       BoardNode;                      /* board node (always 0) */
-    ulong       CommandIndex;                   /* command number */
+    ulong32     BoardNode;                      /* board node (always 0) */
+    ulong32     CommandIndex;                   /* command number */
     ushort      OpCode;                         /* the command (READ,..) */
     union {
         struct {
             ushort      DeviceNo;               /* number of cache drive */
-            ulong       BlockNo;                /* block number */
-            ulong       BlockCnt;               /* block count */
-            ulong       DestAddr;               /* dest. addr. (if s/g: -1) */
-            ulong       sg_canz;                /* s/g element count */
+            ulong32     BlockNo;                /* block number */
+            ulong32     BlockCnt;               /* block count */
+            ulong32     DestAddr;               /* dest. addr. (if s/g: -1) */
+            ulong32     sg_canz;                /* s/g element count */
             gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
-        } cache;                                /* cache service cmd. str. */
+        } PACKED cache;                         /* cache service cmd. str. */
         struct {
             ushort      param_size;             /* size of p_param buffer */
-            ulong       subfunc;                /* IOCTL function */
-            ulong       channel;                /* device */
-            ulong       p_param;                /* buffer */
-        } ioctl;                                /* IOCTL command structure */
+            ulong32     subfunc;                /* IOCTL function */
+            ulong32     channel;                /* device */
+            ulong32     p_param;                /* buffer */
+        } PACKED ioctl;                         /* IOCTL command structure */
         struct {
             ushort      reserved;
-            ulong       msg_handle;             /* message handle */
-            ulong       msg_addr;               /* message buffer address */
-        } screen;                               /* screen service cmd. str. */
+            ulong32     msg_handle;             /* message handle */
+            ulong32     msg_addr;               /* message buffer address */
+        } PACKED screen;                        /* screen service cmd. str. */
         struct {
             ushort      reserved;
-            ulong       direction;              /* data direction */
-            ulong       mdisc_time;             /* disc. time (0: no timeout)*/
-            ulong       mcon_time;              /* connect time(0: no to.) */
-            ulong       sdata;                  /* dest. addr. (if s/g: -1) */
-            ulong       sdlen;                  /* data length (bytes) */
-            ulong       clen;                   /* SCSI cmd. length(6,10,12) */
+            ulong32     direction;              /* data direction */
+            ulong32     mdisc_time;             /* disc. time (0: no timeout)*/
+            ulong32     mcon_time;              /* connect time(0: no to.) */
+            ulong32     sdata;                  /* dest. addr. (if s/g: -1) */
+            ulong32     sdlen;                  /* data length (bytes) */
+            ulong32     clen;                   /* SCSI cmd. length(6,10,12) */
             unchar      cmd[12];                /* SCSI command */
             unchar      target;                 /* target ID */
             unchar      lun;                    /* LUN */
             unchar      bus;                    /* SCSI bus number */
             unchar      priority;               /* only 0 used */
-            ulong       sense_len;              /* sense data length */
-            ulong       sense_data;             /* sense data addr. */
+            ulong32     sense_len;              /* sense data length */
+            ulong32     sense_data;             /* sense data addr. */
             struct raw  *link_p;                /* linked cmds (not supp.) */
-            ulong       sg_ranz;                /* s/g element count */
+            ulong32     sg_ranz;                /* s/g element count */
             gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
-        } raw;                                  /* raw service cmd. struct. */
+        } PACKED raw;                           /* raw service cmd. struct. */
     } u;
     /* additional variables */
     unchar      Service;                        /* controller service */
     ushort      Status;                         /* command result */
-    ulong       Info;                           /* additional information */
+    ulong32     Info;                           /* additional information */
     Scsi_Cmnd   *RequestBuffer;                 /* request buffer */
-} gdth_cmd_str;
+} PACKED gdth_cmd_str;
 
 /* controller event structure */
 #define ES_ASYNC    1
@@ -347,40 +421,40 @@
         struct {
             ushort          ionode;
             ushort          service;
-            ulong           index;
-        } driver;
+            ulong32         index;
+        } PACKED driver;
         struct {
             ushort          ionode;
             ushort          service;
             ushort          status;
-            ulong           info;
+            ulong32         info;
             unchar          scsi_coord[3];
-        } async;
+        } PACKED async;
         struct {
             ushort          ionode;
             ushort          service;
             ushort          status;
-            ulong           info;
+            ulong32         info;
             ushort          hostdrive;
             unchar          scsi_coord[3];
             unchar          sense_key;
-        } sync;
+        } PACKED sync;
         struct {
-            ulong           l1, l2, l3, l4;
-        } test;
+            ulong32         l1, l2, l3, l4;
+        } PACKED test;
     } eu;
-} gdth_evt_data;
+} PACKED gdth_evt_data;
 
 typedef struct {
-    ulong           first_stamp;
-    ulong           last_stamp;
+    ulong32         first_stamp;
+    ulong32         last_stamp;
     ushort          same_count;
     ushort          event_source;
     ushort          event_idx;
     unchar          application;
     unchar          reserved;
     gdth_evt_data   event_data;
-} gdth_evt_str;
+} PACKED gdth_evt_str;
 
 
 /* DPRAM structures */
@@ -390,32 +464,32 @@
     unchar              S_Cmd_Indx;             /* special command */
     unchar volatile     S_Status;               /* status special command */
     ushort              reserved1;
-    ulong               S_Info[4];              /* add. info special command */
+    ulong32             S_Info[4];              /* add. info special command */
     unchar volatile     Sema0;                  /* command semaphore */
     unchar              reserved2[3];
     unchar              Cmd_Index;              /* command number */
     unchar              reserved3[3];
     ushort volatile     Status;                 /* command status */
     ushort              Service;                /* service(for async.events) */
-    ulong               Info[2];                /* additional info */
+    ulong32             Info[2];                /* additional info */
     struct {
         ushort          offset;                 /* command offs. in the DPRAM*/
         ushort          serv_id;                /* service */
-    } comm_queue[MAXOFFSETS];                   /* command queue */
-    ulong               bios_reserved[2];
+    } PACKED comm_queue[MAXOFFSETS];            /* command queue */
+    ulong32             bios_reserved[2];
     unchar              gdt_dpr_cmd[1];         /* commands */
-} gdt_dpr_if;
+} PACKED gdt_dpr_if;
 
 /* SRAM structure PCI controllers */
 typedef struct {
-    ulong       magic;                          /* controller ID from BIOS */
+    ulong32     magic;                          /* controller ID from BIOS */
     ushort      need_deinit;                    /* switch betw. BIOS/driver */
     unchar      switch_support;                 /* see need_deinit */
     unchar      padding[9];
     unchar      os_used[16];                    /* OS code per service */
     unchar      unused[28];
     unchar      fw_magic;                       /* contr. ID from firmware */
-} gdt_pci_sram;
+} PACKED gdt_pci_sram;
 
 /* SRAM structure EISA controllers (but NOT GDT3000/3020) */
 typedef struct {
@@ -423,7 +497,7 @@
     ushort      need_deinit;                    /* switch betw. BIOS/driver */
     unchar      switch_support;                 /* see need_deinit */
     unchar      padding;
-} gdt_eisa_sram;
+} PACKED gdt_eisa_sram;
 
 
 /* DPRAM ISA controllers */
@@ -431,12 +505,12 @@
     union {
         struct {
             unchar      bios_used[0x3c00-32];   /* 15KB - 32Bytes BIOS */
-            ulong       magic;                  /* controller (EISA) ID */
+            ulong32     magic;                  /* controller (EISA) ID */
             ushort      need_deinit;            /* switch betw. BIOS/driver */
             unchar      switch_support;         /* see need_deinit */
             unchar      padding[9];
             unchar      os_used[16];            /* OS code per service */
-        } dp_sram;
+        } PACKED dp_sram;
         unchar          bios_area[0x4000];      /* 16KB reserved for BIOS */
     } bu;
     union {
@@ -450,8 +524,8 @@
         unchar          irqdel;                 /* acknowledge board int. */
         unchar volatile Sema1;                  /* status semaphore */
         unchar          rq;                     /* IRQ/DRQ configuration */
-    } io;
-} gdt2_dpram_str;
+    } PACKED io;
+} PACKED gdt2_dpram_str;
 
 /* DPRAM PCI controllers */
 typedef struct {
@@ -470,8 +544,8 @@
         unchar          unused3[3];
         unchar          irqdel;                 /* acknowledge board int. */
         unchar          unused4[3];
-    } io;
-} gdt6_dpram_str;
+    } PACKED io;
+} PACKED gdt6_dpram_str;
 
 /* PLX register structure (new PCI controllers) */
 typedef struct {
@@ -482,7 +556,7 @@
     unchar              unused2[2];
     ushort volatile     status;                 /* command status */
     ushort              service;                /* service */
-    ulong               info[2];                /* additional info */
+    ulong32             info[2];                /* additional info */
     unchar              unused3[0x10];
     unchar              ldoor_reg;              /* PCI to local doorbell */
     unchar              unused4[3];
@@ -491,7 +565,7 @@
     unchar              control0;               /* control0 register(unused) */
     unchar              control1;               /* board interrupts enable */
     unchar              unused6[0x16];
-} gdt6c_plx_regs;
+} PACKED gdt6c_plx_regs;
 
 /* DPRAM new PCI controllers */
 typedef struct {
@@ -500,7 +574,7 @@
         unchar          if_area[0x4000-sizeof(gdt_pci_sram)];
     } u;
     gdt_pci_sram        gdt6sr;                 /* SRAM structure */
-} gdt6c_dpram_str;
+} PACKED gdt6c_dpram_str;
 
 /* i960 register structure (PCI MPR controllers) */
 typedef struct {
@@ -511,15 +585,15 @@
     unchar              unused3;
     ushort volatile     status;                 /* command status */
     ushort              service;                /* service */
-    ulong               info[2];                /* additional info */
+    ulong32             info[2];                /* additional info */
     unchar              ldoor_reg;              /* PCI to local doorbell */
     unchar              unused4[11];
     unchar volatile     edoor_reg;              /* local to PCI doorbell */
     unchar              unused5[7];
     unchar              edoor_en_reg;           /* board interrupts enable */
     unchar              unused6[27];
-    ulong               unused7[1004];          /* size: 4 KB */
-} gdt6m_i960_regs;
+    ulong32             unused7[1004];          /* size: 4 KB */
+} PACKED gdt6m_i960_regs;
 
 /* DPRAM PCI MPR controllers */
 typedef struct {
@@ -529,58 +603,71 @@
         unchar          if_area[0x3000-sizeof(gdt_pci_sram)];
     } u;
     gdt_pci_sram        gdt6sr;                 /* SRAM structure */
-} gdt6m_dpram_str;
+} PACKED gdt6m_dpram_str;
 
 
 /* PCI resources */
 typedef struct {
-    ushort      device_id;                      /* device ID (0,..,9) */
-    unchar      bus;                            /* PCI bus */
-    unchar      device_fn;                      /* PCI device/function no. */
-    ulong       dpmem;                          /* DPRAM address */
-    ulong       io;                             /* IO address */
-    ulong       io_mm;                          /* IO address mem. mapped */
-    ulong       bios;                           /* BIOS address */
-    unchar      irq;                            /* IRQ */
+#if LINUX_VERSION_CODE >= 0x02015C
+    struct pci_dev      *pdev;
+#endif
+    ushort              device_id;              /* device ID (0,..,9) */
+    unchar              bus;                    /* PCI bus */
+    unchar              device_fn;              /* PCI device/function no. */
+    ulong               dpmem;                  /* DPRAM address */
+    ulong               io;                     /* IO address */
+    ulong               io_mm;                  /* IO address mem. mapped */
+    unchar              irq;                    /* IRQ */
 } gdth_pci_str;
 
 
 /* controller information structure */
 typedef struct {
-    unchar              bus_cnt;                /* SCSI bus count */
-    unchar              type;                   /* controller class */
+    ushort              type;                   /* controller class */
     ushort              raw_feat;               /* feat. raw service (s/g,..) */
-    ulong               stype;                  /* controller subtype */
+    ulong32             stype;                  /* controller subtype */
     ushort              cache_feat;             /* feat. cache serv. (s/g,..) */
-    ushort		bmic;			/* BMIC address (EISA) */
-    void               	*brd;	                /* DPRAM address */
-    ulong               brd_phys;               /* slot number/BIOS address */
+    ushort              bmic;                   /* BMIC address (EISA) */
+    void                *brd;                   /* DPRAM address */
+    ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
     gdth_cmd_str        *pccb;                  /* address command structure */
-    gdth_scratch_str    *pscratch;
+    char                *pscratch;              /* scratch (DMA) buffer */
+    unchar              scratch_busy;           /* in use? */
+    unchar              scan_mode;              /* current scan mode */
     unchar              irq;                    /* IRQ */
     unchar              drq;                    /* DRQ (ISA controllers) */
     ushort              status;                 /* command status */
-    ulong               info;
-    ulong               info2;                  /* additional info */
+    ulong32             info;
+    ulong32             info2;                  /* additional info */
     Scsi_Cmnd           *req_first;             /* top of request queue */
     struct {
-        unchar          type;                   /* device type */
+        unchar          present;                /* host drive present? */
+        unchar          lock;                   /* drive locked? (hot plug) */
         unchar          heads;                  /* mapping */
         unchar          secs;
-        unchar          lock;                   /* drive locked ? (hot plug) */
-        ushort          hostdrive;              /* host drive number */
         ushort          devtype;                /* further information */
-        ulong           size;                   /* capacity */
-    } id[MAXBUS][MAXID];         
+        ulong32         size;                   /* capacity */
+    } hdr[MAXID];                               /* host drives */
+    struct {
+        unchar          lock;                   /* channel locked? (hot plug) */
+    } raw[MAXBUS];                              /* raw devices */
+    struct {
+        Scsi_Cmnd       *cmnd;                  /* pending request */
+        ushort          service;                /* service */
+    } cmd_tab[GDTH_MAXCMDS];                    /* table of pend. requests */
+    unchar              bus_cnt;                /* SCSI bus count */
+    unchar              tid_cnt;                /* Target ID count */
+    unchar              bus_id[MAXBUS];         /* IOP IDs */
     ushort              cmd_cnt;                /* command count in DPRAM */
     ushort              cmd_len;                /* length of actual command */
     ushort              cmd_offs_dpmem;         /* actual offset in DPRAM */
     ushort              ic_all_size;            /* sizeof DPRAM interf. area */
-    unchar              reserved;
-    unchar              mode;                   /* information from /proc */
-    ushort              param_size;
     gdth_cpar_str       cpar;                   /* controller cache par. */
+    char                ctr_name[16];           /* controller name */
+#if LINUX_VERSION_CODE >= 0x02015F
+    spinlock_t          smp_lock;
+#endif
 } gdth_ha_str;
 
 /* structure for scsi_register(), SCSI bus != 0 */
@@ -594,7 +681,6 @@
     gdth_num_str        numext;                 /* must be the first element */
     gdth_ha_str         haext;
     gdth_cmd_str        cmdext;
-    gdth_scratch_str    dmaext;
 } gdth_ext_str;
 
 
@@ -611,27 +697,27 @@
     unchar      vendor[8];
     unchar      product[16];
     unchar      revision[4];
-} gdth_inq_data;
+} PACKED gdth_inq_data;
 
 /* READ_CAPACITY data format */
 typedef struct {
-    ulong       last_block_no;
-    ulong       block_length;
-} gdth_rdcap_data;
+    ulong32     last_block_no;
+    ulong32     block_length;
+} PACKED gdth_rdcap_data;
 
 /* REQUEST_SENSE data format */
 typedef struct {
     unchar      errorcode;
     unchar      segno;
     unchar      key;
-    ulong       info;
+    ulong32     info;
     unchar      add_length;
-    ulong       cmd_info;
+    ulong32     cmd_info;
     unchar      adsc;
     unchar      adsq;
     unchar      fruc;
     unchar      key_spec[3];
-} gdth_sense_data;
+} PACKED gdth_sense_data;
 
 /* MODE_SENSE data format */
 typedef struct {
@@ -640,20 +726,20 @@
         unchar  med_type;
         unchar  dev_par;
         unchar  bd_length;
-    } hd;
+    } PACKED hd;
     struct {
         unchar  dens_code;
         unchar  block_count[3];
         unchar  reserved;
         unchar  block_length[3];
-    } bd;
-} gdth_modep_data;
+    } PACKED bd;
+} PACKED gdth_modep_data;
 
+/* stack frame */
 typedef struct {
-    ulong       b[10];                          /* 32 bit compiler ! */
-} gdth_stackframe;
+    ulong       b[10];                          /* 32/64 bit compiler ! */
+} PACKED gdth_stackframe;
 
-#pragma pack()
 
 /* function prototyping */
 
@@ -669,27 +755,82 @@
 #endif
 const char *gdth_info(struct Scsi_Host *);
 
-
+#if LINUX_VERSION_CODE >= 0x02015F
 int gdth_bios_param(Disk *,kdev_t,int *);
 extern struct proc_dir_entry proc_scsi_gdth;
 int gdth_proc_info(char *,char **,off_t,int,int,int);
-#define GDTH { proc_dir:          &proc_scsi_gdth,                     \
-               proc_info:         gdth_proc_info,                      \
-               name:              "GDT SCSI Disk Array Controller",    \
-               detect:            gdth_detect,                         \
-               release:           gdth_release,                        \
-               info:              gdth_info,                           \
-               command:           gdth_command,                        \
-               queuecommand:      gdth_queuecommand,                   \
-               abort:             gdth_abort,                          \
-               reset:             gdth_reset,                          \
-               bios_param:        gdth_bios_param,                     \
-               can_queue:         GDTH_MAXCMDS,                        \
-               this_id:           -1,                                  \
-               sg_tablesize:      GDTH_MAXSG,                          \
-               cmd_per_lun:       GDTH_MAXC_P_L,                       \
-               unchecked_isa_dma: 1,                                   \
-               use_clustering:    ENABLE_CLUSTERING}
+int gdth_eh_abort(Scsi_Cmnd *scp);
+int gdth_eh_device_reset(Scsi_Cmnd *scp);
+int gdth_eh_bus_reset(Scsi_Cmnd *scp);
+int gdth_eh_host_reset(Scsi_Cmnd *scp);
+#define GDTH { proc_dir:        &proc_scsi_gdth,                 \
+               proc_info:       gdth_proc_info,                  \
+               name:            "GDT SCSI Disk Array Controller",\
+               detect:          gdth_detect,                     \
+               release:         gdth_release,                    \
+               info:            gdth_info,                       \
+               command:         gdth_command,                    \
+               queuecommand:    gdth_queuecommand,               \
+               eh_abort_handler: gdth_eh_abort,                  \
+               eh_device_reset_handler: gdth_eh_device_reset,    \
+               eh_bus_reset_handler: gdth_eh_bus_reset,          \
+               eh_host_reset_handler: gdth_eh_host_reset,        \
+               abort:           gdth_abort,                      \
+               reset:           gdth_reset,                      \
+               bios_param:      gdth_bios_param,                 \
+               can_queue:       GDTH_MAXCMDS,                    \
+               this_id:         -1,                              \
+               sg_tablesize:    GDTH_MAXSG,                      \
+               cmd_per_lun:     GDTH_MAXC_P_L,                   \
+               present:         0,                               \
+               unchecked_isa_dma: 1,                             \
+               use_clustering:  ENABLE_CLUSTERING,               \
+               use_new_eh_code: 1       /* use new error code */ }    
+#elif LINUX_VERSION_CODE >= 0x010300
+int gdth_bios_param(Disk *,kdev_t,int *);
+extern struct proc_dir_entry proc_scsi_gdth;
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+#define GDTH { NULL, NULL,                              \
+                   &proc_scsi_gdth,                     \
+                   gdth_proc_info,                      \
+                   "GDT SCSI Disk Array Controller",    \
+                   gdth_detect,                         \
+                   gdth_release,                        \
+                   gdth_info,                           \
+                   gdth_command,                        \
+                   gdth_queuecommand,                   \
+                   gdth_abort,                          \
+                   gdth_reset,                          \
+                   NULL,                                \
+                   gdth_bios_param,                     \
+                   GDTH_MAXCMDS,                        \
+                   -1,                                  \
+                   GDTH_MAXSG,                          \
+                   GDTH_MAXC_P_L,                       \
+                   0,                                   \
+                   1,                                   \
+                   ENABLE_CLUSTERING}
+#else
+int gdth_bios_param(Disk *,int,int *);
+#define GDTH { NULL, NULL,                              \
+                   "GDT SCSI Disk Array Controller",    \
+                   gdth_detect,                         \
+                   gdth_release,                        \
+                   gdth_info,                           \
+                   gdth_command,                        \
+                   gdth_queuecommand,                   \
+                   gdth_abort,                          \
+                   gdth_reset,                          \
+                   NULL,                                \
+                   gdth_bios_param,                     \
+                   GDTH_MAXCMDS,                        \
+                   -1,                                  \
+                   GDTH_MAXSG,                          \
+                   GDTH_MAXC_P_L,                       \
+                   0,                                   \
+                   1,                                   \
+                   ENABLE_CLUSTERING}
+#endif
 
 #endif
 
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth_ioctl.h linux/drivers/scsi/gdth_ioctl.h
--- v2.2.0-pre6/linux/drivers/scsi/gdth_ioctl.h	Tue Nov  4 09:17:30 1997
+++ linux/drivers/scsi/gdth_ioctl.h	Mon Jan 11 10:17:20 1999
@@ -2,7 +2,7 @@
 #define _GDTH_IOCTL_H
 
 /* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.1 1997/02/21 08:07:27 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.2 1998/12/17 15:42:49 achim Exp $
  */
 
 /* IOCTLs */
@@ -16,12 +16,12 @@
 #define GDTIOCTL_LOCKCHN    (GDTIOCTL_MASK | 7) /* lock channel */
 #define GDTIOCTL_EVENT      (GDTIOCTL_MASK | 8) /* read controller events */
 
-#define GDTIOCTL_MAGIC      0x06030f07UL
+#define GDTIOCTL_MAGIC      0xaffe0001UL
 
 
 /* IOCTL structure (write) */
 typedef struct {
-    ulong                   magic;              /* IOCTL magic */
+    ulong32                 magic;              /* IOCTL magic */
     ushort                  ioctl;              /* IOCTL */
     ushort                  ionode;             /* controller number */
     ushort                  service;            /* controller service */
@@ -43,14 +43,15 @@
         struct {
             int             erase;              /* erase event ? */
             int             handle;
+            unchar          evt[34];            /* event structure */
         } event;
     } iu;
 } gdth_iowr_str;
 
 /* IOCTL structure (read) */
 typedef struct {
-    ulong                   size;               /* buffer size */
-    ulong                   status;             /* IOCTL error code */
+    ulong32                 size;               /* buffer size */
+    ulong32                 status;             /* IOCTL error code */
     union {
         struct {
             unchar          data[1];            /* data */
@@ -76,7 +77,7 @@
         } ctrcnt;
         struct {
             int             handle;
-            unchar          evt[32];            /* event structure */
+            unchar          evt[34];            /* event structure */
         } event;
     } iu;
 } gdth_iord_str;
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c
--- v2.2.0-pre6/linux/drivers/scsi/gdth_proc.c	Mon Feb 23 18:12:07 1998
+++ linux/drivers/scsi/gdth_proc.c	Mon Jan 11 10:17:20 1999
@@ -1,5 +1,5 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.6 1997/10/31 10:36:24 achim Exp $
+ * $Id: gdth_proc.c,v 1.11 1998/12/17 15:52:35 achim Exp $
  */
 
 #include "gdth_ioctl.h"
@@ -10,7 +10,7 @@
     int hanum,busnum,i;
 
     TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n",
-            length,hostno,offset,inout));
+            length,hostno,(int)offset,inout));
 
     for (i=0; i<gdth_ctr_vcount; ++i) {
         if (gdth_ctr_vtab[i]->host_no == hostno)
@@ -69,7 +69,7 @@
 {
     int             orig_length, drive, wb_mode;
     char            cmnd[12];
-    int             i, j, found;
+    int             i, found;
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
@@ -96,28 +96,28 @@
         } else {
             printk("GDT: Flushing all host drives .. ");
         }
-        for (i = 0; i < MAXBUS; ++i) {
-            for (j = 0; j < MAXID; ++j) {
-                if (ha->id[i][j].type == CACHE_DTYP) {
-                    if (drive != -1 &&
-                        ha->id[i][j].hostdrive != (ushort)drive)
-                        continue;
-                    found = TRUE;
-                    gdtcmd.BoardNode = LOCALBOARD;
-                    gdtcmd.Service = CACHESERVICE;
-                    gdtcmd.OpCode = GDT_FLUSH;
-                    gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive;
-                    gdtcmd.u.cache.BlockNo = 1;
-                    gdtcmd.u.cache.sg_canz = 0;
-                    {
-                        struct semaphore sem = MUTEX_LOCKED;
-                        scp.request.rq_status = RQ_SCSI_BUSY;
-                        scp.request.sem = &sem;
-                        scsi_do_cmd(&scp, cmnd, &gdtcmd,
-                                    sizeof(gdth_cmd_str), gdth_scsi_done,
-                                    30*HZ, 1);
-                        down(&sem);
-                    }
+        for (i = 0; i < MAX_HDRIVES; ++i) {
+            if (ha->hdr[i].present) {
+                if (drive != -1 && i != drive)
+                    continue;
+                found = TRUE;
+                gdtcmd.BoardNode = LOCALBOARD;
+                gdtcmd.Service = CACHESERVICE;
+                gdtcmd.OpCode = GDT_FLUSH;
+                gdtcmd.u.cache.DeviceNo = i;
+                gdtcmd.u.cache.BlockNo = 1;
+                gdtcmd.u.cache.sg_canz = 0;
+                {
+                    struct semaphore sem = MUTEX_LOCKED;
+                    scp.request.rq_status = RQ_SCSI_BUSY;
+                    scp.request.sem = &sem;
+                    scp.SCp.this_residual = IOCTL_PRI;
+                    GDTH_LOCK_SCSI_DOCMD();
+                    scsi_do_cmd(&scp, cmnd, &gdtcmd,
+                                sizeof(gdth_cmd_str), gdth_scsi_done,
+                                30*HZ, 1);
+                    GDTH_UNLOCK_SCSI_DOCMD();
+                    down(&sem);
                 }
             }
         }
@@ -179,8 +179,11 @@
             struct semaphore sem = MUTEX_LOCKED;
             scp.request.rq_status = RQ_SCSI_BUSY;
             scp.request.sem = &sem;
+            scp.SCp.this_residual = IOCTL_PRI;
+            GDTH_LOCK_SCSI_DOCMD();
             scsi_do_cmd(&scp, cmnd, &gdtcmd, sizeof(gdth_cmd_str),
                         gdth_scsi_done, 30*HZ, 1);
+            GDTH_UNLOCK_SCSI_DOCMD();
             down(&sem);
         }
         kfree( pcpar );
@@ -195,15 +198,13 @@
 static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
 {
     char            cmnd[12];
-    int             id;
-    unchar          i, j, k, found;
+    unchar          i, j;
     gdth_ha_str     *ha;
     gdth_iowr_str   *piowr;
     gdth_iord_str   *piord;
     gdth_cmd_str    *pcmd;
-    ulong           *ppadd;
-    ulong           add_size, flags;
-
+    ulong32         *ppadd, add_size;
+    ulong           flags;
 
     TRACE2(("gdth_set_bin_info() ha %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -228,7 +229,7 @@
             add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE;
             if (ha->cache_feat & SCATTER_GATHER) {
                 ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr;
-                pcmd->u.cache.DestAddr = -1UL;
+                pcmd->u.cache.DestAddr = 0xffffffff;
                 pcmd->u.cache.sg_lst[0].sg_len = add_size;
                 pcmd->u.cache.sg_canz = 1;
             } else {
@@ -239,7 +240,7 @@
             add_size = pcmd->u.raw.sdlen;
             if (ha->raw_feat & SCATTER_GATHER) {
                 ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr;
-                pcmd->u.raw.sdata = -1UL;
+                pcmd->u.raw.sdata = 0xffffffff;
                 pcmd->u.raw.sg_lst[0].sg_len = add_size;
                 pcmd->u.raw.sg_ranz = 1;
             } else {
@@ -249,10 +250,9 @@
         } else {
             return(-EINVAL);
         }
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
 
         piord->size = sizeof(gdth_iord_str) + add_size;
         if (add_size > 0) {
@@ -265,33 +265,33 @@
             scp.request.rq_status = RQ_SCSI_BUSY;
             scp.request.sem = &sem;
             scp.SCp.this_residual = IOCTL_PRI;
+            GDTH_LOCK_SCSI_DOCMD();
             scsi_do_cmd(&scp, cmnd, pcmd,
                         sizeof(gdth_cmd_str), gdth_scsi_done,
                         piowr->timeout*HZ, 1);
+            GDTH_UNLOCK_SCSI_DOCMD();
             down(&sem);
-            piord->status = (ulong)scp.SCp.Message;
+            piord->status = (ulong32)scp.SCp.Message;
         }
         break;
 
       case GDTIOCTL_DRVERS:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
         piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
         break;
 
       case GDTIOCTL_CTRTYPE:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
         if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
-            piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 10);
+            piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10);
         } else if (ha->type != GDT_PCIMPR) {
             piord->iu.ctrtype.type = (unchar)((ha->stype<<8) + 6);
         } else {
@@ -303,20 +303,18 @@
         break;
 
       case GDTIOCTL_CTRCNT:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
         piord->iu.ctrcnt.count = (ushort)gdth_ctr_count;
         break;
 
       case GDTIOCTL_OSVERS:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
         piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16);
@@ -325,39 +323,24 @@
         break;
 
       case GDTIOCTL_LOCKDRV:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
-        for (i = k = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
-            found = FALSE;
-            for (j = 0; j < ha->bus_cnt; ++j) {
-                for (k = 0; k < MAXID; ++k) {
-                    if (ha->id[j][k].type == CACHE_DTYP &&
-                        ha->id[j][k].hostdrive == piowr->iu.lockdrv.drives[i]) {
-                        found = TRUE;
-                        break;
-                    }
-                }
-                if (found)
-                    break;
-            }
-            if (!found)
+        piord = (gdth_iord_str *)ha->pscratch;
+        for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
+            j = piowr->iu.lockdrv.drives[i];
+            if (j >= MAX_HDRIVES || !ha->hdr[j].present) 
                 continue;
-
             if (piowr->iu.lockdrv.lock) {
-                save_flags( flags );
-                cli();
-                ha->id[j][k].lock = 1;
-                restore_flags( flags );
-                gdth_wait_completion( hanum, j, k );
-                gdth_stop_timeout( hanum, j, k );
+                GDTH_LOCK_HA(ha, flags);
+                ha->hdr[j].lock = 1;
+                GDTH_UNLOCK_HA(ha, flags);
+                gdth_wait_completion( hanum, ha->bus_cnt, j );
+                gdth_stop_timeout( hanum, ha->bus_cnt, j );
             } else {
-                save_flags( flags );
-                cli();
-                ha->id[j][k].lock = 0;
-                restore_flags( flags );
-                gdth_start_timeout( hanum, j, k );
+                GDTH_LOCK_HA(ha, flags);
+                ha->hdr[j].lock = 0;
+                GDTH_UNLOCK_HA(ha, flags);
+                gdth_start_timeout( hanum, ha->bus_cnt, j );
                 gdth_next( hanum );
             }
         }
@@ -366,46 +349,54 @@
         break;
 
       case GDTIOCTL_LOCKCHN:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        for (k = 0, j = piowr->iu.lockchn.channel; k < MAXID; ++k) {
-            if (ha->id[j][k].type != RAW_DTYP)
-                continue;
-
+        i = piowr->iu.lockchn.channel;
+        if (i < ha->bus_cnt) {
             if (piowr->iu.lockchn.lock) {
-                save_flags( flags );
-                cli();
-                ha->id[j][k].lock = 1;
-                restore_flags( flags );
-                gdth_wait_completion( hanum, j, k );
-                gdth_stop_timeout( hanum, j, k );
+                GDTH_LOCK_HA(ha, flags);
+                ha->raw[i].lock = 1;
+                GDTH_UNLOCK_HA(ha, flags);
+                for (j = 0; j < ha->tid_cnt; ++j) {
+                    gdth_wait_completion( hanum, i, j );
+                    gdth_stop_timeout( hanum, i, j );
+                }
             } else {
-                save_flags( flags );
-                cli();
-                ha->id[j][k].lock = 0;
-                restore_flags( flags );
-                gdth_start_timeout( hanum, j, k );
-                gdth_next( hanum );
+                GDTH_LOCK_HA(ha, flags);
+                ha->raw[i].lock = 0;
+                GDTH_UNLOCK_HA(ha, flags);
+                for (j = 0; j < ha->tid_cnt; ++j) {
+                    gdth_start_timeout( hanum, i, j );
+                    gdth_next( hanum );
+                }
             }
         }
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
         break;
 
       case GDTIOCTL_EVENT:
-        id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
-        if (id == -1)
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
             return(-EBUSY);
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
-        if (piowr->iu.event.erase == 0) {
-            piord->iu.event.handle = gdth_read_event( piowr->iu.event.handle,
-                (gdth_evt_str *)piord->iu.event.evt );
+        piord = (gdth_iord_str *)ha->pscratch;
+        if (piowr->iu.event.erase == 0xff) {
+            gdth_store_event(ha, 
+                             ((gdth_evt_str *)piowr->iu.event.evt)->event_source,
+                             ((gdth_evt_str *)piowr->iu.event.evt)->event_idx,
+                             &((gdth_evt_str *)piowr->iu.event.evt)->event_data);
+            if (((gdth_evt_str *)piowr->iu.event.evt)->event_source == ES_ASYNC)
+                gdth_log_event(&((gdth_evt_str *)piowr->iu.event.evt)->event_data);
+        } else if (piowr->iu.event.erase == 0xfe) {
+            gdth_clear_events();
+        } else if (piowr->iu.event.erase == 0) {
+            piord->iu.event.handle = 
+                gdth_read_event(ha,piowr->iu.event.handle,
+                                (gdth_evt_str *)piord->iu.event.evt);
         } else {
             piord->iu.event.handle = piowr->iu.event.handle;
-            gdth_readapp_event( (unchar)piowr->iu.event.erase,
-                (gdth_evt_str *)piord->iu.event.evt );
+            gdth_readapp_event(ha, (unchar)piowr->iu.event.erase,
+                               (gdth_evt_str *)piord->iu.event.evt);
         }
         piord->size = sizeof(gdth_iord_str);
         piord->status = S_OK;
@@ -415,7 +406,7 @@
         return(-EINVAL);
     }
     /* we return a buffer ID to detect the right buffer during READ-IOCTL */
-    return id;
+    return 1;
 }
 
 static int gdth_get_info(char *buffer,char **start,off_t offset,
@@ -432,15 +423,15 @@
     id = length;
 
     /* look for buffer ID in length */
-    if (id > 4) {
+    if (id > 1) {
 #if LINUX_VERSION_CODE >= 0x020000
         size = sprintf(buffer+len,
-                       "%s SCSI Disk Array Controller\n",
-                       gdth_ctr_name(hanum));
+                       "%s Disk Array Controller\n",
+                       ha->ctr_name);
 #else
         size = sprintf(buffer+len,
-                       "%s SCSI Disk Array Controller (SCSI Bus %d)\n",
-                       gdth_ctr_name(hanum),busnum);
+                       "%s Disk Array Controller (Bus %d)\n",
+                       ha->ctr_name,busnum);
 #endif
         len += size;  pos = begin + len;
         size = sprintf(buffer+len,
@@ -457,12 +448,12 @@
             goto stop_output;
 
     } else {
-        piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+        piord = (gdth_iord_str *)ha->pscratch;
         if (piord == NULL)
             goto stop_output;
         length = piord->size;
         memcpy(buffer+len, (char *)piord, length);
-        gdth_ioctl_free(hanum, id);
+        gdth_ioctl_free(hanum);
         len += length; pos = begin + len;
 
         if (pos < offset) {
@@ -479,7 +470,7 @@
     if (len > length)
         len = length;
     TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
-            len,pos,begin,offset,length,size));
+            len,(int)pos,(int)begin,(int)offset,length,size));
     return(len);
 }
 
@@ -496,140 +487,152 @@
 
 static int gdth_ioctl_alloc(int hanum, ushort size)
 {
+    gdth_ha_str *ha;
     ulong flags;
-    int i;
+    int ret_val;
 
-    if (size == 0)
+    if (size == 0 || size > GDTH_SCRATCH)
         return -1;
 
-    save_flags(flags);
-    cli();
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
 
-    for (i = 0; i < 4; ++i) {
-        if (gdth_ioctl_tab[i][hanum] == NULL) {
-            gdth_ioctl_tab[i][hanum] = kmalloc( size, GFP_ATOMIC | GFP_DMA );
-            break;
-        }
-    }
+    if (!ha->scratch_busy) {
+        ha->scratch_busy = TRUE;
+        ret_val = TRUE;
+    } else
+        ret_val = FALSE;
 
-    restore_flags(flags);
-    if (i == 4 || gdth_ioctl_tab[i][hanum] == NULL)
-        return -1;
-    return (i+1);
+    GDTH_UNLOCK_HA(ha, flags);
+    return ret_val;
 }
 
-static void gdth_ioctl_free(int hanum, int idx)
+static void gdth_ioctl_free(int hanum)
 {
+    gdth_ha_str *ha;
     ulong flags;
 
-    save_flags(flags);
-    cli();
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
 
-    kfree( gdth_ioctl_tab[idx-1][hanum] );
-    gdth_ioctl_tab[idx-1][hanum] = NULL;
+    ha->scratch_busy = FALSE;
 
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 
 static void gdth_wait_completion(int hanum, int busnum, int id)
 {
+    gdth_ha_str *ha;
     ulong flags;
     int i;
     Scsi_Cmnd *scp;
 
-    save_flags(flags);
-    cli();
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
 
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
-        scp = gdth_cmd_tab[i][hanum].cmnd;
-        if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
+        scp = ha->cmd_tab[i].cmnd;
 #if LINUX_VERSION_CODE >= 0x020000
+        if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
             scp->channel == (unchar)busnum)
 #else
+        if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
             NUMDATA(scp->host)->busnum == (unchar)busnum)
 #endif
         {
-            restore_flags(flags);
+            scp->SCp.have_data_in = 0;
+            GDTH_UNLOCK_HA(ha, flags);
             while (!scp->SCp.have_data_in)
                 barrier();
-            save_flags(flags);
-            cli();
+            GDTH_LOCK_SCSI_DONE(flags);
+            scp->scsi_done(scp);
+            GDTH_UNLOCK_SCSI_DONE(flags);
+        GDTH_LOCK_HA(ha, flags);
         }
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 
 static void gdth_stop_timeout(int hanum, int busnum, int id)
 {
+    gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
-    gdth_ha_str *ha;
 
-    save_flags(flags);
-    cli();
     ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        if (scp->target == (unchar)id &&
 #if LINUX_VERSION_CODE >= 0x020000
+        if (scp->target == (unchar)id &&
             scp->channel == (unchar)busnum)
 #else
+        if (scp->target == (unchar)id &&
             NUMDATA(scp->host)->busnum == (unchar)busnum)
 #endif
         {
             TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
-            scp->SCp.buffers_residual = gdth_update_timeout(scp, 0);
+            scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 
 static void gdth_start_timeout(int hanum, int busnum, int id)
 {
+    gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
-    gdth_ha_str *ha;
 
-    save_flags(flags);
-    cli();
     ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        if (scp->target == (unchar)id &&
 #if LINUX_VERSION_CODE >= 0x020000
+        if (scp->target == (unchar)id &&
             scp->channel == (unchar)busnum)
 #else
+        if (scp->target == (unchar)id &&
             NUMDATA(scp->host)->busnum == (unchar)busnum)
 #endif
         {
             TRACE2(("gdth_start_timeout(): update_timeout()\n"));
-            gdth_update_timeout(scp, scp->SCp.buffers_residual);
+            gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
         }
     }
-    restore_flags(flags);
+    GDTH_UNLOCK_HA(ha, flags);
 }
 
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout)
+static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
 {
-    ulong flags;
     int oldto;
 
-    save_flags(flags);
-    cli();
+    oldto = scp->timeout_per_command;
+    scp->timeout_per_command = timeout;
 
-    oldto = scp->timeout;
-    scp->timeout = timeout;
+#if LINUX_VERSION_CODE >= 0x02014B
+    if (timeout == 0) {
+        del_timer(&scp->eh_timeout);
+        scp->eh_timeout.data = (unsigned long) NULL;
+        scp->eh_timeout.expires = 0;
+    } else {
+        if (scp->eh_timeout.data != (unsigned long) NULL) 
+            del_timer(&scp->eh_timeout);
+        scp->eh_timeout.data = (unsigned long) scp;
+        scp->eh_timeout.expires = jiffies + timeout;
+        add_timer(&scp->eh_timeout);
+    }
+#else
     if (timeout > 0) {
-        if (timer_table[GDTH_TIMER].expires == 0) {
-            timer_table[GDTH_TIMER].expires = jiffies + timeout;
-            timer_active |= 1 << GDTH_TIMER;
+        if (timer_table[SCSI_TIMER].expires == 0) {
+            timer_table[SCSI_TIMER].expires = jiffies + timeout;
+            timer_active |= 1 << SCSI_TIMER;
         } else {
-            if (jiffies + timeout < timer_table[GDTH_TIMER].expires)
-                timer_table[GDTH_TIMER].expires = jiffies + timeout;
+            if (jiffies + timeout < timer_table[SCSI_TIMER].expires)
+                timer_table[SCSI_TIMER].expires = jiffies + timeout;
         }
     }
+#endif
 
-    restore_flags(flags);
     return oldto;
 }
-
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/gdth_proc.h linux/drivers/scsi/gdth_proc.h
--- v2.2.0-pre6/linux/drivers/scsi/gdth_proc.h	Tue Nov  4 09:17:30 1997
+++ linux/drivers/scsi/gdth_proc.h	Mon Jan 11 10:17:20 1999
@@ -2,7 +2,7 @@
 #define _GDTH_PROC_H
 
 /* gdth_proc.h 
- * $Id: gdth_proc.h,v 1.2 1997/02/21 08:08:51 achim Exp $
+ * $Id: gdth_proc.h,v 1.5 1998/12/17 15:43:53 achim Exp $
  */
 
 static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
@@ -12,11 +12,11 @@
                          int length,int vh,int hanum,int busnum);
 
 static int gdth_ioctl_alloc(int hanum, ushort size);
-static void gdth_ioctl_free(int hanum, int id);
+static void gdth_ioctl_free(int hanum);
 static void gdth_wait_completion(int hanum, int busnum, int id);
 static void gdth_stop_timeout(int hanum, int busnum, int id);
 static void gdth_start_timeout(int hanum, int busnum, int id);
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout);
+static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
 
 void gdth_scsi_done(Scsi_Cmnd *scp);
 
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/i91uscsi.c linux/drivers/scsi/i91uscsi.c
--- v2.2.0-pre6/linux/drivers/scsi/i91uscsi.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/scsi/i91uscsi.c	Sun Jan 10 22:27:27 1999
@@ -71,6 +71,7 @@
 	12/13/98 bv, Use spinlocks instead of cli() for serialized
 		     access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail
 		     members of the HCS structure.
+	01/09/98 bv, Fix a deadlock on SMP system.
 **********************************************************************/
 
 #define DEBUG_INTERRUPT 0
@@ -221,20 +222,9 @@
 	unsigned long the_time = jiffies + amount;	/* 0.01 seconds per jiffy */
 
 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
-	/*
-	 * We need to release the io_request_lock 
-	 * to make sure that the jiffies are updated
-	 */
-	spin_unlock_irq(&io_request_lock);
-
 	while (time_before_eq(jiffies, the_time));
-
-	/*
-	 * Acquire the io_request_lock again
-	 */
-	spin_lock_irq(&io_request_lock);
 #else
-	while (time_before(jiffies, the_time));
+	while (jiffies < the_time);
 #endif
 }
 
@@ -1037,8 +1027,17 @@
 	if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
 		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
 		/* disable Jasmin SCSI Int        */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 		tulip_main(pCurHcb);
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 		pCurHcb->HCS_Semaph = 1;
 		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
 
@@ -1176,8 +1175,17 @@
 		if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
 			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
 			/* disable Jasmin SCSI Int        */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 			tulip_main(pCurHcb);
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        		spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 			pCurHcb->HCS_Semaph = 1;
 			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
 
@@ -1230,8 +1238,16 @@
 		/* disable Jasmin SCSI Int        */
 		pCurHcb->HCS_Semaph = 0;
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 		tulip_main(pCurHcb);
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 		pCurHcb->HCS_Semaph = 1;
 		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
 	}
@@ -1274,8 +1290,16 @@
 #endif
 	tul_post_scsi_rst(pCurHcb);
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 	tulip_main(pCurHcb);
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 	pCurHcb->HCS_Semaph = 1;
 	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
@@ -1311,7 +1335,15 @@
 		/* disable Jasmin SCSI Int        */
 		pCurHcb->HCS_Semaph = 0;
 
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
 		tulip_main(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
 
 		pCurHcb->HCS_Semaph = 1;
 		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- v2.2.0-pre6/linux/drivers/scsi/imm.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/imm.c	Sat Jan  9 19:16:43 1999
@@ -328,7 +328,7 @@
     if (k)
 	return (r & 0xb8);
 
-    /* Counter expired - Time out occured */
+    /* Counter expired - Time out occurred */
     imm_fail(host_no, DID_TIME_OUT);
     printk("imm timeout in imm_wait\n");
     return 0;			/* command timed out */
@@ -943,7 +943,7 @@
     unsigned char l = 0, h = 0;
     int retv, x;
 
-    /* First check for any errors that may of occured
+    /* First check for any errors that may of occurred
      * Here we check for internal errors
      */
     if (tmp->failed)
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c
--- v2.2.0-pre6/linux/drivers/scsi/ini9100u.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/ini9100u.c	Sun Jan 10 22:27:27 1999
@@ -93,6 +93,8 @@
  *		- Remove cli() locking for kernels >= 2.1.95. This uses
  *		  spinlocks to serialize access to the pSRB_head and
  *		  pSRB_tail members of the HCS structure.
+ * 09/01/99 bv	- v1.03d
+ *		- Fixed a deadlock problem in SMP.
  **************************************************************************/
 
 #define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
@@ -173,7 +175,7 @@
 char *i91uCopyright = "Copyright (C) 1996-98";
 char *i91uInitioName = "by Initio Corporation";
 char *i91uProductName = "INI-9X00U/UW";
-char *i91uVersion = "v1.03b";
+char *i91uVersion = "v1.03d";
 
 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 struct proc_dir_entry proc_scsi_ini9100u =
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h
--- v2.2.0-pre6/linux/drivers/scsi/ini9100u.h	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/ini9100u.h	Mon Jan 11 10:36:18 1999
@@ -88,7 +88,7 @@
 extern int i91u_biosparam(Disk *, int, int *);	/*for linux v1.13 */
 #endif
 
-#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03b"
+#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03d"
 
 #if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0)
 #define INI9100U	{ \
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.2.0-pre6/linux/drivers/scsi/megaraid.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/megaraid.c	Sat Jan  9 19:16:43 1999
@@ -858,7 +858,7 @@
 }
     
 /*--------------------------------------------------------------------
- * Initializes the adress of the controller's mailbox register
+ * Initializes the address of the controller's mailbox register
  *  The mailbox register is used to issue commands to the card.
  *  Format of the mailbox area:
  *   00 01 command
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.2.0-pre6/linux/drivers/scsi/ppa.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/ppa.c	Sat Jan  9 19:16:43 1999
@@ -316,7 +316,7 @@
     if (k)
 	return (r & 0xf0);
 
-    /* Counter expired - Time out occured */
+    /* Counter expired - Time out occurred */
     ppa_fail(host_no, DID_TIME_OUT);
     printk("ppa timeout in ppa_wait\n");
     return 0;			/* command timed out */
@@ -804,7 +804,7 @@
     unsigned char l = 0, h = 0;
     int retv;
 
-    /* First check for any errors that may of occured
+    /* First check for any errors that may of occurred
      * Here we check for internal errors
      */
     if (tmp->failed)
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.2.0-pre6/linux/drivers/scsi/scsi.c	Fri Jan  8 22:36:10 1999
+++ linux/drivers/scsi/scsi.c	Mon Jan 11 09:56:56 1999
@@ -280,6 +280,8 @@
 {"YAMAHA","CDR100","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"YAMAHA","CDR102","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN},
+{"IBM","DPES-","*", BLIST_NOTQ | BLIST_NOLUN},
+{"WDIGTL","WDE","*", BLIST_NOTQ | BLIST_NOLUN},
 /*
  * Must be at end of list...
  */
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.2.0-pre6/linux/drivers/scsi/scsi.h	Thu Dec 31 10:29:01 1998
+++ linux/drivers/scsi/scsi.h	Mon Jan 11 10:35:45 1999
@@ -317,7 +317,7 @@
 #define IS_RESETTING    0x08
 #define IS_ABORTING     0x10
 #define ASKED_FOR_SENSE 0x20
-
+#define SYNC_RESET      0x40
 
 #if defined(__mc68000__) || defined(CONFIG_APUS)
 #include <asm/pgtable.h>
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.2.0-pre6/linux/drivers/scsi/scsi_obsolete.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/scsi_obsolete.c	Sun Jan 10 12:42:52 1999
@@ -23,6 +23,9 @@
  *  Major improvements to the timeout, abort, and reset processing,
  *  as well as performance modifications for large queue depths by
  *  Leonard N. Zubkoff <lnz@dandelion.com>
+ *
+ *  Improved compatibility with 2.0 behaviour by Manfred Spraul
+ *  <masp0008@stud.uni-sb.de>
  */
 
 /*
@@ -354,6 +357,18 @@
     printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result);
 #endif
 
+    if(SCpnt->flags & SYNC_RESET)
+    {
+        /*
+        * The behaviou of scsi_reset(SYNC) was changed in 2.1.? .
+        * The scsi mid-layer does a REDO after every sync reset, the driver
+        * must not do that any more. In order to prevent old drivers from
+        * crashing, all scsi_done() calls during sync resets are ignored.
+        */
+        printk("scsi%d: device driver called scsi_done() "
+	       "for a syncronous reset.\n", SCpnt->host->host_no);
+        return;
+    }
     if(SCpnt->flags & WAS_SENSE)
     {
 	SCpnt->use_sg = SCpnt->old_use_sg;
@@ -494,7 +509,7 @@
 	    case RESERVATION_CONFLICT:
 		printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
 		       " reset.\n", SCpnt->host->host_no, SCpnt->channel);
-		scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
+                scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
 		status = REDO;
 		break;
 	    default:
@@ -613,7 +628,7 @@
 		printk("scsi%d channel %d : resetting for second half of retries.\n",
 		       SCpnt->host->host_no, SCpnt->channel);
 		scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
-		break;
+		/* fall through to REDO */
 	    }
 	}
 	else
@@ -913,6 +928,8 @@
 	    SCpnt->internal_timeout |= IN_RESET;
 	    update_timeout(SCpnt, RESET_TIMEOUT);
 
+	    if (reset_flags & SCSI_RESET_SYNCHRONOUS)
+	      SCpnt->flags |= SYNC_RESET;
 	    if (host->host_busy)
 	    {
                 for(SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
@@ -969,6 +986,8 @@
 		  host->last_reset = jiffies;
 		if (!host->block) host->host_busy--;
 	    }
+	    if (reset_flags & SCSI_RESET_SYNCHRONOUS)
+	      SCpnt->flags &= ~SYNC_RESET;
 
 #ifdef DEBUG
 	    printk("scsi reset function returned %d\n", temp);
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/sound/lowlevel/README linux/drivers/sound/lowlevel/README
--- v2.2.0-pre6/linux/drivers/sound/lowlevel/README	Wed Aug 26 11:37:39 1998
+++ linux/drivers/sound/lowlevel/README	Sat Jan  9 10:01:55 1999
@@ -2,7 +2,7 @@
 ============================================
 
 This directory contains additional low level sound drivers which
-are not part of USS/Lite (Open Sound System). These drivers are
+are not part of OSS/Lite (Open Sound System). These drivers are
 maintained by their authors (not by Hannu Savolainen).
 
 If you like to write a new low level sound driver, please contact
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.2.0-pre6/linux/drivers/sound/wavfront.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/wavfront.c	Sat Jan  9 19:16:43 1999
@@ -74,11 +74,29 @@
 #include <linux/config.h>
 #include <linux/init.h>
 
+#include <linux/delay.h>
+
 #include "sound_config.h"
 #include "soundmodule.h"
 
 #include <linux/wavefront.h>
 
+/*
+ *	This sucks, hopefully it'll get standardised
+ */
+ 
+#if defined(__alpha__)
+#ifdef __SMP__
+#define LOOPS_PER_SEC cpu_data[smp_processor_id()].loops_per_sec
+#else
+#define LOOPS_PER_SEC	loops_per_sec
+#endif
+#endif
+
+#if defined(__i386__)
+#define LOOPS_PER_SEC current_cpu_data.loops_per_sec
+#endif
+ 
 #define MIDI_SYNTH_NAME	"WaveFront MIDI"
 #define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT
 #include "midi_synth.h"
@@ -440,7 +458,7 @@
 
 	if (short_loop_cnt == 0) {
 		short_loop_cnt = wait_usecs *
-			(current_cpu_data.loops_per_sec / 1000000);
+			(LOOPS_PER_SEC / 1000000);
 	}
 
 	/* Spin for a short period of time, because >99% of all
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.2.0-pre6/linux/drivers/video/fbmem.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/fbmem.c	Sat Jan  9 19:16:43 1999
@@ -22,9 +22,7 @@
 #include <linux/console.h>
 #include <linux/console_struct.h>
 #include <linux/init.h>
-#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
-#endif
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -205,7 +203,6 @@
 	return MINOR(current->tty->device) - 1;
 }
 
-#ifdef CONFIG_PROC_FS
 static int fbmem_read_proc(char *buf, char **start, off_t offset,
 			   int len, int *eof, void *private)
 {
@@ -220,7 +217,6 @@
 	*start = buf + offset;
 	return len > offset ? len - offset : 0;
 }
-#endif
 
 static ssize_t
 fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
@@ -583,20 +579,16 @@
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *proc_fbmem;
-#endif
 
 __initfunc(void
 fbmem_init(void))
 {
 	int i;
 
-#ifdef CONFIG_PROC_FS
 	proc_fbmem = create_proc_entry("fb", 0, 0);
 	if (proc_fbmem)
 		proc_fbmem->read_proc = fbmem_read_proc;
-#endif
 
 	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
 		printk("unable to get major %d for fb devs\n", FB_MAJOR);
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c
--- v2.2.0-pre6/linux/drivers/video/mdacon.c	Sun Nov  8 14:03:04 1998
+++ linux/drivers/video/mdacon.c	Tue Jan 12 14:03:22 1999
@@ -331,7 +331,7 @@
 	mda_type_name = "MDA";
 
 	if (! mda_detect()) {
-		printk("mdacon: MDA card not detected.");
+		printk("mdacon: MDA card not detected.\n");
 		return NULL;
 	}
 
diff -u --recursive --new-file v2.2.0-pre6/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.2.0-pre6/linux/drivers/video/retz3fb.c	Tue Dec 22 14:16:57 1998
+++ linux/drivers/video/retz3fb.c	Sat Jan  9 19:16:43 1999
@@ -757,7 +757,7 @@
 	reg_w(regs, VDAC_MASK, 0xff);
 
 	/*
-	 * Extended palette adressing ???
+	 * Extended palette addressing ???
 	 */
 	switch (bpp){
 	case 8:
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h
--- v2.2.0-pre6/linux/fs/autofs/autofs_i.h	Thu Nov 19 09:56:28 1998
+++ linux/fs/autofs/autofs_i.h	Mon Jan 11 15:03:30 1999
@@ -92,10 +92,6 @@
 
 #define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32)
 
-#ifndef END_OF_TIME
-#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1))
-#endif
-
 #define AUTOFS_SBI_MAGIC 0x6d4a556d
 
 struct autofs_sb_info {
@@ -111,6 +107,11 @@
 	u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
 };
 
+extern inline struct autofs_sb_info *autofs_sbi(struct super_block *sb)
+{
+	return (struct autofs_sb_info *)(sb->u.generic_sbp);
+}
+
 /* autofs_oz_mode(): do we see the man behind the curtain?  (The
    processes which do manipulations for us in user space sees the raw
    filesystem without "magic".) */
@@ -126,6 +127,7 @@
 void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
 void autofs_hash_delete(struct autofs_dir_ent *);
 struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *);
+void autofs_hash_dputall(struct autofs_dirhash *);
 void autofs_hash_nuke(struct autofs_dirhash *);
 
 /* Expiration-handling functions */
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/dirhash.c linux/fs/autofs/dirhash.c
--- v2.2.0-pre6/linux/fs/autofs/dirhash.c	Sun Nov  8 14:03:04 1998
+++ linux/fs/autofs/dirhash.c	Mon Jan 11 15:03:30 1999
@@ -47,7 +47,7 @@
 
 	ent = dh->expiry_head.exp_next;
 
-	if ( ent == &(dh->expiry_head) )
+	if ( ent == &(dh->expiry_head) || sbi->catatonic )
 		return NULL;	/* No entries */
 
 	while ( jiffies - ent->last_usage >= timeout ) {
@@ -62,8 +62,10 @@
 		dentry = ent->dentry;
 
 		if ( !dentry ) {
+			/* Should only happen in catatonic mode */
 			printk("autofs: dentry == NULL but inode range is directory, entry %s\n", ent->name);
 			autofs_delete_usage(ent);
+			continue;
 		}
 
 		if ( !dentry->d_inode ) {
@@ -200,6 +202,23 @@
 
 	*ptr = ((bucket+1) << 16) + ecount;
 	return ent;
+}
+
+/* Iterate over all the ents, and remove all dentry pointers.  Used on
+   entering catatonic mode, in order to make the filesystem unmountable. */
+void autofs_hash_dputall(struct autofs_dirhash *dh)
+{
+	int i;
+	struct autofs_dir_ent *ent, *nent;
+
+	for ( i = 0 ; i < AUTOFS_HASH_SIZE ; i++ ) {
+		for ( ent = dh->h[i] ; ent ; ent = ent->next ) {
+			if ( ent->dentry ) {
+				dput(ent->dentry);
+				ent->dentry = NULL;
+			}
+		}
+	}
 }
 
 /* Delete everything.  This is used on filesystem destruction, so we
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.2.0-pre6/linux/fs/autofs/inode.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/autofs/inode.c	Mon Jan 11 15:03:30 1999
@@ -34,8 +34,7 @@
 
 static void autofs_put_super(struct super_block *sb)
 {
-	struct autofs_sb_info *sbi =
-		(struct autofs_sb_info *) sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(sb);
 	unsigned int n;
 
 	if ( !sbi->catatonic )
@@ -297,8 +296,7 @@
 {
 	ino_t ino = inode->i_ino;
 	unsigned int n;
-	struct autofs_sb_info *sbi =
-		(struct autofs_sb_info *) inode->i_sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
 
 	/* Initialize to the default case (stub directory) */
 
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.2.0-pre6/linux/fs/autofs/root.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/autofs/root.c	Mon Jan 11 15:03:30 1999
@@ -68,13 +68,15 @@
 {
 	struct autofs_dir_ent *ent = NULL;
 	struct autofs_dirhash *dirhash;
+	struct autofs_sb_info *sbi;
 	struct inode * inode = filp->f_dentry->d_inode;
 	off_t onr, nr;
 
 	if (!inode || !S_ISDIR(inode->i_mode))
 		return -ENOTDIR;
 
-	dirhash = &((struct autofs_sb_info *)inode->i_sb->u.generic_sbp)->dirhash;
+	sbi = autofs_sbi(inode->i_sb);
+	dirhash = &sbi->dirhash;
 	nr = filp->f_pos;
 
 	switch(nr)
@@ -168,12 +170,10 @@
  */
 static int autofs_revalidate(struct dentry * dentry)
 {
-	struct autofs_sb_info *sbi;
 	struct inode * dir = dentry->d_parent->d_inode;
+	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
 	struct autofs_dir_ent *ent;
 
-	sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
-
 	/* Pending dentry */
 	if ( dentry->d_flags & DCACHE_AUTOFS_PENDING ) {
 		if (autofs_oz_mode(sbi))
@@ -220,7 +220,7 @@
 	if (!S_ISDIR(dir->i_mode))
 		return -ENOTDIR;
 
-	sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
+	sbi = autofs_sbi(dir->i_sb);
 
 	oz_mode = autofs_oz_mode(sbi);
 	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
@@ -267,7 +267,7 @@
 
 static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
 	struct autofs_dirhash *dh = &sbi->dirhash;
 	struct autofs_dir_ent *ent;
 	unsigned int n;
@@ -338,7 +338,7 @@
  */
 static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
 {
-	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
 	struct autofs_dirhash *dh = &sbi->dirhash;
 	struct autofs_dir_ent *ent;
 	unsigned int n;
@@ -365,7 +365,7 @@
 
 static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
 	struct autofs_dirhash *dh = &sbi->dirhash;
 	struct autofs_dir_ent *ent;
 
@@ -393,7 +393,7 @@
 
 static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
 	struct autofs_dirhash *dh = &sbi->dirhash;
 	struct autofs_dir_ent *ent;
 	ino_t ino;
@@ -492,8 +492,7 @@
 static int autofs_root_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg)
 {
-	struct autofs_sb_info *sbi =
-		(struct autofs_sb_info *)inode->i_sb->u.generic_sbp;
+	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
 
 	DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp));
 
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c
--- v2.2.0-pre6/linux/fs/autofs/waitq.c	Mon Dec 28 15:00:52 1998
+++ linux/fs/autofs/waitq.c	Mon Jan 11 15:03:30 1999
@@ -41,6 +41,7 @@
 		wq = nwq;
 	}
 	fput(sbi->pipe);	/* Close the pipe */
+	autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
 }
 
 static int autofs_write(struct file *file, const void *addr, int bytes)
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/nls/Config.in linux/fs/nls/Config.in
--- v2.2.0-pre6/linux/fs/nls/Config.in	Tue Dec 22 14:16:57 1998
+++ linux/fs/nls/Config.in	Sat Jan  9 10:01:56 1999
@@ -25,20 +25,20 @@
   tristate 'Codepage 862 (Hebrew)'                 CONFIG_NLS_CODEPAGE_862
   tristate 'Codepage 863 (Canadian French)'        CONFIG_NLS_CODEPAGE_863
   tristate 'Codepage 864 (Arabic)'                 CONFIG_NLS_CODEPAGE_864
-  tristate 'Codepage 865 (Nordic European)'        CONFIG_NLS_CODEPAGE_865
+  tristate 'Codepage 865 (Norwegian, Danish)'      CONFIG_NLS_CODEPAGE_865
   tristate 'Codepage 866 (Cyrillic/Russian)'       CONFIG_NLS_CODEPAGE_866
   tristate 'Codepage 869 (Greek)'                  CONFIG_NLS_CODEPAGE_869
   tristate 'Codepage 874 (Thai)'                   CONFIG_NLS_CODEPAGE_874
   tristate 'NLS ISO 8859-1  (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1
-  tristate 'NLS ISO 8859-2  (Latin 2; Slavic/Central European)' CONFIG_NLS_ISO8859_2
+  tristate 'NLS ISO 8859-2  (Latin 2; Slavic/Central European Languages)' CONFIG_NLS_ISO8859_2
   tristate 'NLS ISO 8859-3  (Latin 3; Esperanto, Galician, Maltese, Turkish)' CONFIG_NLS_ISO8859_3
   tristate 'NLS ISO 8859-4  (Latin 4; Estonian, Latvian, Lithuanian)' CONFIG_NLS_ISO8859_4
   tristate 'NLS ISO 8859-5  (Cyrillic)'             CONFIG_NLS_ISO8859_5
   tristate 'NLS ISO 8859-6  (Arabic)'               CONFIG_NLS_ISO8859_6
   tristate 'NLS ISO 8859-7  (Modern Greek)'         CONFIG_NLS_ISO8859_7
   tristate 'NLS ISO 8859-8  (Hebrew)'               CONFIG_NLS_ISO8859_8
-  tristate 'NLS ISO 8859-9  (Latin 5; Turkey)'      CONFIG_NLS_ISO8859_9
-  tristate 'NLS ISO 8859-15 (Latin 9; Western European with Euro)' CONFIG_NLS_ISO8859_15
+  tristate 'NLS ISO 8859-9  (Latin 5; Turkish)'     CONFIG_NLS_ISO8859_9
+  tristate 'NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)' CONFIG_NLS_ISO8859_15
   tristate 'NLS KOI8-R (Russian)'                   CONFIG_NLS_KOI8_R
   endmenu
 fi
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.2.0-pre6/linux/fs/proc/array.c	Thu Jan  7 15:11:40 1999
+++ linux/fs/proc/array.c	Fri Jan  8 22:54:17 1999
@@ -60,7 +60,6 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/signal.h>
@@ -372,28 +371,6 @@
 		i.freeswap >> 10);
 }
 
-static int get_swapstats(char * buffer)
-{
-	unsigned long *w = swapstats.kswap_wakeups;
-	
-	return sprintf(buffer,
-		       "ProcFreeTry:    %8lu\n"
-		       "ProcFreeSucc:   %8lu\n"
-		       "ProcShrinkTry:  %8lu\n"
-		       "ProcShrinkSucc: %8lu\n"
-		       "KswapFreeTry:   %8lu\n"
-		       "KswapFreeSucc:  %8lu\n"
-		       "KswapWakeups:	%8lu %lu %lu %lu\n",
-		       swapstats.gfp_freepage_attempts,
-		       swapstats.gfp_freepage_successes,
-		       swapstats.gfp_shrink_attempts,
-		       swapstats.gfp_shrink_successes,
-		       swapstats.kswap_freepage_attempts,
-		       swapstats.kswap_freepage_successes,
-		       w[0], w[1], w[2], w[3]
-		       );
-}
-
 static int get_version(char * buffer)
 {
 	extern char *linux_banner;
@@ -1279,9 +1256,6 @@
 
 		case PROC_MEMINFO:
 			return get_meminfo(page);
-
-		case PROC_SWAPSTATS:
-			return get_swapstats(page);
 
 #ifdef CONFIG_PCI_OLD_PROC
   	        case PROC_PCI:
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.2.0-pre6/linux/fs/proc/root.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/proc/root.c	Fri Jan  8 22:54:17 1999
@@ -493,11 +493,6 @@
 	S_IFREG | S_IRUGO, 1, 0, 0,
 	0, &proc_array_inode_operations
 };
-static struct proc_dir_entry proc_root_swapstats = {
-	PROC_SWAPSTATS, 9, "swapstats",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
 static struct proc_dir_entry proc_root_kmsg = {
 	PROC_KMSG, 4, "kmsg",
 	S_IFREG | S_IRUSR, 1, 0, 0,
@@ -653,7 +648,6 @@
 	proc_register(&proc_root, &proc_root_loadavg);
 	proc_register(&proc_root, &proc_root_uptime);
 	proc_register(&proc_root, &proc_root_meminfo);
-	proc_register(&proc_root, &proc_root_swapstats);
 	proc_register(&proc_root, &proc_root_kmsg);
 	proc_register(&proc_root, &proc_root_version);
 	proc_register(&proc_root, &proc_root_cpuinfo);
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/select.c linux/fs/select.c
--- v2.2.0-pre6/linux/fs/select.c	Fri Nov 27 13:09:28 1998
+++ linux/fs/select.c	Sun Jan 10 10:22:34 1999
@@ -221,6 +221,10 @@
 		    || (ret = __get_user(usec, &tvp->tv_usec)))
 			goto out_nofds;
 
+		ret = -EINVAL;
+		if (sec < 0 || usec < 0)
+			goto out_nofds;
+
 		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
 			timeout = ROUND_UP(usec, 1000000/HZ);
 			timeout += sec * (unsigned long) HZ;
@@ -331,10 +335,13 @@
 	if (nfds > NR_OPEN)
 		goto out;
 
-	if (timeout < 0)
-		timeout = MAX_SCHEDULE_TIMEOUT;
-	else if (timeout)
-		timeout = (timeout*HZ+999)/1000+1;
+	if (timeout) {
+		/* Carefula about overflow in the intermediate values */
+		if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
+			timeout = (timeout*HZ+999)/1000+1;
+		else /* Negative or overflow */
+			timeout = MAX_SCHEDULE_TIMEOUT;
+	}
 
 	err = -ENOMEM;
 	if (timeout) {
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.2.0-pre6/linux/fs/ufs/namei.c	Thu Jan  7 15:11:40 1999
+++ linux/fs/ufs/namei.c	Fri Jan  8 22:54:18 1999
@@ -56,10 +56,10 @@
 #define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
 
 /*
- * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
+ * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
  *
- * Len <= UFS_MAXNAMLEN' is guaranteed by caller.
- * De != NULL' is guaranteed by caller.
+ * len <= UFS_MAXNAMLEN' is guaranteed by caller.
+ * de != NULL' is guaranteed by caller.
  */
 static inline int ufs_match (int len, const char * const name,
 	struct ufs_dir_entry * de, unsigned flags, unsigned swab)
diff -u --recursive --new-file v2.2.0-pre6/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.2.0-pre6/linux/fs/ufs/super.c	Fri Jan  8 22:36:14 1999
+++ linux/fs/ufs/super.c	Fri Jan  8 22:54:18 1999
@@ -641,11 +641,14 @@
 		case UFS_FSSTABLE:
 			UFSD(("fs is stable\n"))
 			break;
+		case UFS_FSOSF1:
+			UFSD(("fs is DEC OSF/1\n"))
+			break;
 		case UFS_FSACTIVE:
 			printk("ufs_read_super: fs is active\n");
 			sb->s_flags |= MS_RDONLY;
 			break;
-		    case UFS_FSBAD:
+		case UFS_FSBAD:
 			printk("ufs_read_super: fs is bad\n");
 			sb->s_flags |= MS_RDONLY;
 			break;
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h
--- v2.2.0-pre6/linux/include/asm-alpha/core_cia.h	Mon Dec 28 15:00:53 1998
+++ linux/include/asm-alpha/core_cia.h	Wed Jan 13 10:42:49 1999
@@ -328,7 +328,7 @@
 {
 	unsigned long w = __kernel_insbl(b, addr & 3);
 	*(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
-	wmb();
+	mb();
 }
 
 __EXTERN_INLINE unsigned int cia_inw(unsigned long addr)
@@ -342,7 +342,7 @@
 {
 	unsigned long w = __kernel_inswl(b, addr & 3);
 	*(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
-	wmb();
+	mb();
 }
 
 __EXTERN_INLINE unsigned int cia_inl(unsigned long addr)
@@ -353,7 +353,7 @@
 __EXTERN_INLINE void cia_outl(unsigned int b, unsigned long addr)
 {
 	*(vuip) ((addr << 5) + CIA_IO + 0x18) = b;
-	wmb();
+	mb();
 }
 
 
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h
--- v2.2.0-pre6/linux/include/asm-alpha/core_mcpcia.h	Mon Dec 28 15:00:53 1998
+++ linux/include/asm-alpha/core_mcpcia.h	Sun Jan 10 09:59:59 1999
@@ -71,9 +71,7 @@
  *
  */
 
-#define MCPCIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
-#define MCPCIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
-#define MCPCIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
+#define MCPCIA_MEM_MASK 0x07ffffff /* SPARSE Mem region mask is 27 bits */
 
 #define MCPCIA_DMA_WIN_BASE_DEFAULT    (2*1024*1024*1024U)
 #define MCPCIA_DMA_WIN_SIZE_DEFAULT    (2*1024*1024*1024U)
@@ -386,23 +384,10 @@
 	unsigned long hose = (addr >> 32) & 3;
 
 	if (addr >= alpha_mv.sm_base_r1
-	    && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_R1_MASK) {
-		mask = MCPCIA_MEM_R1_MASK;
+	    && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_MASK) {
+		mask = MCPCIA_MEM_MASK;
 		base = MCPCIA_SPARSE(hose);
 	}
-#if 0
-	/* FIXME FIXME FIXME: SPARSE_MEM_R2 and R3 are not defined?  */
-	else if (addr >= alpha_mv.sm_base_r2
-		 && addr <= alpha_mv.sm_base_r2 + MCPCIA_MEM_R2_MASK) {
-		mask = MCPCIA_MEM_R2_MASK;
-		base = MCPCIA_SPARSE_MEM_R2;
-	}
-	else if (addr >= alpha_mv.sm_base_r3
-		 && addr <= alpha_mv.sm_base_r3 + MCPCIA_MEM_R3_MASK) {
-		mask = MCPCIA_MEM_R3_MASK;
-		base = MCPCIA_SPARSE_MEM_R3;
-	}
-#endif
 	else
 	{
 #if 0
@@ -462,8 +447,8 @@
 	unsigned long hose = (in_addr >> 32) & 3;
 	unsigned long result, msb, work, temp;
 
-	msb = addr & 0xE0000000UL;
-	temp = addr & MCPCIA_MEM_R1_MASK;
+	msb = addr & ~MCPCIA_MEM_MASK;
+	temp = addr & MCPCIA_MEM_MASK;
 	set_hae(msb);
 
 	work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00);
@@ -477,8 +462,8 @@
 	unsigned long hose = (in_addr >> 32) & 3;
 	unsigned long result, msb, work, temp;
 
-	msb = addr & 0xE0000000UL;
-	temp = addr & MCPCIA_MEM_R1_MASK ;
+	msb = addr & ~MCPCIA_MEM_MASK;
+	temp = addr & MCPCIA_MEM_MASK ;
 	set_hae(msb);
 
 	work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08);
@@ -492,8 +477,8 @@
 	unsigned long hose = (in_addr >> 32) & 3;
         unsigned long msb; 
 
-	msb = addr & 0xE0000000;
-	addr &= MCPCIA_MEM_R1_MASK;
+	msb = addr & ~MCPCIA_MEM_MASK;
+	addr &= MCPCIA_MEM_MASK;
 	set_hae(msb);
 
 	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101;
@@ -505,8 +490,8 @@
 	unsigned long hose = (in_addr >> 32) & 3;
         unsigned long msb ; 
 
-	msb = addr & 0xE0000000 ;
-	addr &= MCPCIA_MEM_R1_MASK ;
+	msb = addr & ~MCPCIA_MEM_MASK ;
+	addr &= MCPCIA_MEM_MASK ;
 	set_hae(msb);
 
 	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001;
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h
--- v2.2.0-pre6/linux/include/asm-alpha/core_polaris.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/core_polaris.h	Sun Jan 10 09:59:59 1999
@@ -0,0 +1,239 @@
+#ifndef __ALPHA_POLARIS__H__
+#define __ALPHA_POLARIS__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/compiler.h>
+
+/*
+ * POLARIS is the internal name for a core logic chipset which provides
+ * memory controller and PCI access for the 21164PC chip based systems.
+ *
+ * This file is based on:
+ *
+ * Polaris System Controller
+ * Device Functional Specification
+ * 22-Jan-98
+ * Rev. 4.2
+ *
+ */
+
+/* Polaris memory regions */
+#define		POLARIS_SPARSE_MEM_BASE		(IDENT_ADDR + 0xf800000000)
+#define		POLARIS_DENSE_MEM_BASE		(IDENT_ADDR + 0xf900000000)
+#define 	POLARIS_SPARSE_IO_BASE		(IDENT_ADDR + 0xf980000000)
+#define		POLARIS_SPARSE_CONFIG_BASE	(IDENT_ADDR + 0xf9c0000000)
+#define		POLARIS_IACK_BASE		(IDENT_ADDR + 0xf9f8000000)
+#define		POLARIS_DENSE_IO_BASE		(IDENT_ADDR + 0xf9fc000000)
+#define		POLARIS_DENSE_CONFIG_BASE	(IDENT_ADDR + 0xf9fe000000)
+
+/* The Polaris command/status registers live in PCI Config space for
+ * bus 0/device 0.  As such, they may be bytes, words, or doublewords.
+ */
+#define		POLARIS_W_VENID		(POLARIS_DENSE_CONFIG_BASE)
+#define		POLARIS_W_DEVID		(POLARIS_DENSE_CONFIG_BASE+2)
+#define		POLARIS_W_CMD		(POLARIS_DENSE_CONFIG_BASE+4)
+#define		POLARIS_W_STATUS	(POLARIS_DENSE_CONFIG_BASE+6)
+
+/* No HAE address.  Polaris has no concept of an HAE, since it
+ * supports transfers of all sizes in dense space.
+ */
+
+#define POLARIS_DMA_WIN_BASE_DEFAULT	0x80000000	/* fixed, 2G @ 2G */
+#define POLARIS_DMA_WIN_SIZE_DEFAULT	0x80000000	/* fixed, 2G @ 2G */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define POLARIS_DMA_WIN_BASE		alpha_mv.dma_win_base
+#define POLARIS_DMA_WIN_SIZE		alpha_mv.dma_win_size
+#else
+#define POLARIS_DMA_WIN_BASE		POLARIS_DMA_WIN_BASE_DEFAULT
+#define POLARIS_DMA_WIN_SIZE		POLARIS_DMA_WIN_SIZE_DEFAULT
+#endif
+
+/*
+ * Data structure for handling POLARIS machine checks:
+ */
+struct el_POLARIS_sysdata_mcheck {
+    u_long      psc_status;
+    u_long	psc_pcictl0;
+    u_long	psc_pcictl1;
+    u_long	psc_pcictl2;
+};
+
+ #ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+__EXTERN_INLINE unsigned long polaris_virt_to_bus(void * address)
+{
+	return virt_to_phys(address) + POLARIS_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * polaris_bus_to_virt(unsigned long address)
+{
+	return phys_to_virt(address - POLARIS_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * POLARIS, the PCI/memory support chipset for the PCA56 (21164PC)
+ * processors, can use either a sparse address  mapping scheme, or the 
+ * so-called byte-word PCI address space, to get at PCI memory and I/O.
+ *
+ * However, we will support only the BWX form.
+ */
+
+#define vucp	volatile unsigned char *
+#define vusp	volatile unsigned short *
+#define vuip	volatile unsigned int  *
+#define vulp	volatile unsigned long  *
+
+__EXTERN_INLINE unsigned int polaris_inb(unsigned long addr)
+{
+        return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
+}
+
+__EXTERN_INLINE void polaris_outb(unsigned char b, unsigned long addr)
+{
+	__kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_IO_BASE));
+	mb();
+}
+
+__EXTERN_INLINE unsigned int polaris_inw(unsigned long addr)
+{
+        return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE));
+}
+
+__EXTERN_INLINE void polaris_outw(unsigned short b, unsigned long addr)
+{
+	__kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_IO_BASE));
+	mb();
+}
+
+__EXTERN_INLINE unsigned int polaris_inl(unsigned long addr)
+{
+        return *(vuip)(addr + POLARIS_DENSE_IO_BASE);
+}
+
+__EXTERN_INLINE void polaris_outl(unsigned int b, unsigned long addr)
+{
+        *(vuip)(addr + POLARIS_DENSE_IO_BASE) = b;
+        mb();
+}
+
+/*
+ * Memory functions.  Polaris allows all accesses (byte/word
+ * as well as long/quad) to be done through dense space.
+ *
+ * We will only support DENSE access via BWX insns.
+ */
+
+__EXTERN_INLINE unsigned long polaris_readb(unsigned long addr)
+{
+        return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_MEM_BASE));
+}
+
+__EXTERN_INLINE unsigned long polaris_readw(unsigned long addr)
+{
+        return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_MEM_BASE));
+}
+
+__EXTERN_INLINE unsigned long polaris_readl(unsigned long addr)
+{
+        return *(vuip)(addr + POLARIS_DENSE_MEM_BASE);
+}
+
+__EXTERN_INLINE unsigned long polaris_readq(unsigned long addr)
+{
+        return *(vulp)(addr + POLARIS_DENSE_MEM_BASE);
+}
+
+__EXTERN_INLINE void polaris_writeb(unsigned char b, unsigned long addr)
+{
+        __kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_MEM_BASE));
+        mb();
+}
+
+__EXTERN_INLINE void polaris_writew(unsigned short b, unsigned long addr)
+{
+        __kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_MEM_BASE));
+        mb();
+}
+
+__EXTERN_INLINE void polaris_writel(unsigned int b, unsigned long addr)
+{
+        *(vuip)(addr + POLARIS_DENSE_MEM_BASE) = b;
+        mb();
+}
+
+__EXTERN_INLINE void polaris_writeq(unsigned long b, unsigned long addr)
+{
+        *(vulp)(addr + POLARIS_DENSE_MEM_BASE) = b;
+        mb();
+}
+
+/* Find the DENSE memory area for a given bus address.  */
+
+__EXTERN_INLINE unsigned long polaris_dense_mem(unsigned long addr)
+{
+        return POLARIS_DENSE_MEM_BASE;
+}
+
+#undef vucp
+#undef vusp
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus     polaris_virt_to_bus
+#define bus_to_virt     polaris_bus_to_virt
+
+#define __inb           polaris_inb
+#define __inw           polaris_inw
+#define __inl           polaris_inl
+#define __outb          polaris_outb
+#define __outw          polaris_outw
+#define __outl          polaris_outl
+#define __readb         polaris_readb
+#define __readw         polaris_readw
+#define __writeb        polaris_writeb
+#define __writew        polaris_writew
+#define __readl         polaris_readl
+#define __readq         polaris_readq
+#define __writel        polaris_writel
+#define __writeq        polaris_writeq
+#define dense_mem       polaris_dense_mem
+
+#define inb(port) __inb((port))
+#define inw(port) __inw((port))
+#define inl(port) __inl((port))
+
+#define outb(v, port) __outb((v),(port))
+#define outw(v, port) __outw((v),(port))
+#define outl(v, port) __outl((v),(port))
+
+#define readb(a)        __readb((unsigned long)(a))
+#define readw(a)        __readw((unsigned long)(a))
+#define readl(a)        __readl((unsigned long)(a))
+#define readq(a)        __readq((unsigned long)(a))
+
+#define writeb(v,a)     __writeb((v),(unsigned long)(a))
+#define writew(v,a)     __writew((v),(unsigned long)(a))
+#define writel(v,a)     __writel((v),(unsigned long)(a))
+#define writeq(v,a)     __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_POLARIS__H__ */
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h
--- v2.2.0-pre6/linux/include/asm-alpha/core_tsunami.h	Wed Sep  9 14:51:10 1998
+++ linux/include/asm-alpha/core_tsunami.h	Sun Jan 10 09:59:59 1999
@@ -16,8 +16,8 @@
  *
  */
 
-#define TSUNAMI_DMA_WIN_BASE_DEFAULT    (1024*1024*1024)
-#define TSUNAMI_DMA_WIN_SIZE_DEFAULT    (1024*1024*1024)
+#define TSUNAMI_DMA_WIN_BASE_DEFAULT    (1024*1024*1024U)
+#define TSUNAMI_DMA_WIN_SIZE_DEFAULT    (1024*1024*1024U)
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
 #define TSUNAMI_DMA_WIN_BASE		alpha_mv.dma_win_base
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.2.0-pre6/linux/include/asm-alpha/io.h	Mon Dec 28 15:00:53 1998
+++ linux/include/asm-alpha/io.h	Sun Jan 10 09:59:59 1999
@@ -141,6 +141,8 @@
 # include <asm/core_tsunami.h>
 #elif defined(CONFIG_ALPHA_JENSEN)
 # include <asm/jensen.h>
+#elif defined(CONFIG_ALPHA_RX164)
+# include <asm/core_polaris.h>
 #else
 #error "What system is this?"
 #endif
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h
--- v2.2.0-pre6/linux/include/asm-alpha/irq.h	Thu Dec 31 10:29:02 1998
+++ linux/include/asm-alpha/irq.h	Sun Jan 10 09:59:59 1999
@@ -34,6 +34,7 @@
       defined(CONFIG_ALPHA_XLT)       || \
       defined(CONFIG_ALPHA_MIATA)     || \
       defined(CONFIG_ALPHA_RUFFIAN)   || \
+      defined(CONFIG_ALPHA_RX164)     || \
       defined(CONFIG_ALPHA_NORITAKE)
 # define NR_IRQS	48
 
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h
--- v2.2.0-pre6/linux/include/asm-alpha/spinlock.h	Mon Dec 28 15:00:53 1998
+++ linux/include/asm-alpha/spinlock.h	Sun Jan 10 09:59:59 1999
@@ -207,7 +207,7 @@
 	"	br	1b\n"
 	".previous"
 	: "=m" (__dummy_lock(lock)), "=&r" (regx)
-	: "0" (__dummy_lock(lock))
+	: "m" (__dummy_lock(lock))
 	);
 }
 #endif /* DEBUG_RWLOCK */
@@ -230,7 +230,7 @@
 	"6:	br	1b\n"
 	".previous"
 	: "=m" (__dummy_lock(lock)), "=&r" (regx)
-	: "0" (__dummy_lock(lock)));
+	: "m" (__dummy_lock(lock)));
 }
 
 #define read_lock_irq(lock)	(__cli(), read_lock(lock))
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.2.0-pre6/linux/include/asm-alpha/unistd.h	Wed Sep  9 14:51:10 1998
+++ linux/include/asm-alpha/unistd.h	Sat Jan  9 19:08:27 1999
@@ -67,7 +67,7 @@
 #define __NR_getpgrp		 63
 #define __NR_getpagesize	 64
 #define __NR_osf_mremap		 65	/* not implemented */
-#define __NR_osf_vfork		 66
+#define __NR_vfork		 66
 #define __NR_stat		 67
 #define __NR_lstat		 68
 #define __NR_osf_sbrk		 69	/* not implemented */
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-i386/locks.h linux/include/asm-i386/locks.h
--- v2.2.0-pre6/linux/include/asm-i386/locks.h	Sat Nov 29 10:33:21 1997
+++ linux/include/asm-i386/locks.h	Mon Jan 11 10:11:58 1999
@@ -62,7 +62,7 @@
 	   not be safe this way */
 	if(!--sp->users)
 	{
-		lock_clear_bit(0,&sp->lock);sp->cpu= NO_PROC_ID;
+		sp->cpu= NO_PROC_ID;lock_clear_bit(0,&sp->lock);
 		return 1;
 	}
 	return 0;
@@ -102,15 +102,17 @@
 
 extern __inline__ void spinunlock(struct spinlock *sp)
 {
+	int pri;
 	if(current->lock_order!=sp->priority)
 		panic("lock release order violation %s (%d)\n", sp->name, current->lock_order);
+	pri=sp->oldpri;
 	if(prim_spin_unlock(sp))
 	{
 		/*
 		 *	Update the debugging lock priority chain. We dumped
 		 *	our last right to the lock.
 		 */
-		current->lock_order=sp->oldpri;
+		current->lock_order=sp->pri;
 	}	
 }
 
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.2.0-pre6/linux/include/asm-i386/semaphore.h	Wed Dec 16 10:32:56 1998
+++ linux/include/asm-i386/semaphore.h	Mon Jan 11 10:35:06 1999
@@ -49,11 +49,6 @@
  *
  * This is trivially done with load_locked/store_cond,
  * but on the x86 we need an external synchronizer.
- * Currently this is just the global interrupt lock,
- * bah. Go for a smaller spinlock some day.
- *
- * (On the other hand this shouldn't be in any critical
- * path, so..)
  */
 static inline void wake_one_more(struct semaphore * sem)
 {
diff -u --recursive --new-file v2.2.0-pre6/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v2.2.0-pre6/linux/include/asm-sparc/page.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/page.h	Sun Jan 10 22:56:43 1999
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/head.h>       /* for KERNBASE */
 #include <asm/btfixup.h>
 
diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/file.h linux/include/linux/file.h
--- v2.2.0-pre6/linux/include/linux/file.h	Mon Dec 28 15:00:53 1998
+++ linux/include/linux/file.h	Sat Jan  9 19:16:44 1999
@@ -62,7 +62,7 @@
  * precious bytes from my kernel, even without counting all the code compiled
  * as module!
  *
- * I suspect there are many other similiar "optimizations" across the
+ * I suspect there are many other similar "optimizations" across the
  * kernel...
  */
 extern void fput(struct file *file); 
diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.2.0-pre6/linux/include/linux/mm.h	Fri Jan  8 22:36:24 1999
+++ linux/include/linux/mm.h	Mon Jan 11 10:37:07 1999
@@ -324,6 +324,7 @@
 #define GFP_USER	(__GFP_LOW | __GFP_WAIT | __GFP_IO)
 #define GFP_KERNEL	(__GFP_MED | __GFP_WAIT | __GFP_IO)
 #define GFP_NFS		(__GFP_HIGH | __GFP_WAIT | __GFP_IO)
+#define GFP_KSWAPD	(__GFP_IO)
 
 /* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
    platforms, used as appropriate on others */
diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.2.0-pre6/linux/include/linux/proc_fs.h	Mon Jan  4 15:08:18 1999
+++ linux/include/linux/proc_fs.h	Mon Jan 11 10:37:07 1999
@@ -52,8 +52,7 @@
 	PROC_STRAM,
 	PROC_SOUND,
 	PROC_MTRR, /* whether enabled or not */
-	PROC_FS,
-	PROC_SWAPSTATS
+	PROC_FS
 };
 
 enum pid_directory_inos {
diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.2.0-pre6/linux/include/linux/sched.h	Fri Jan  8 22:36:24 1999
+++ linux/include/linux/sched.h	Mon Jan 11 10:37:07 1999
@@ -33,6 +33,7 @@
 #define CLONE_SIGHAND	0x00000800	/* set if signal handlers shared */
 #define CLONE_PID	0x00001000	/* set if pid shared */
 #define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
+#define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mmput */
 
 /*
  * These are the constant used to fake the fixed-point load-average
@@ -257,8 +258,8 @@
 	/* Pointer to task[] array linkage. */
 	struct task_struct **tarray_ptr;
 
-	struct wait_queue *wait_chldexit, *vfork_sleep;	/* for wait4()/vfork */
-
+	struct wait_queue *wait_chldexit;	/* for wait4() */
+	struct semaphore *vfork_sem;		/* for vfork() */
 	unsigned long policy, rt_priority;
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
@@ -269,10 +270,7 @@
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 	int swappable:1;
-	int trashing_memory:1;
 	unsigned long swap_address;
-	unsigned long old_maj_flt;	/* old value of maj_flt */
-	unsigned long dec_flt;		/* page fault count of the last time */
 	unsigned long swap_cnt;		/* number of pages to swap on next pass */
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
@@ -323,6 +321,7 @@
 #define PF_DUMPCORE	0x00000200	/* dumped core */
 #define PF_SIGNALED	0x00000400	/* killed by a signal */
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
+#define PF_VFORK	0x00001000	/* Wake up parent in mmput */
 
 #define PF_USEDFPU	0x00100000	/* task used FPU this quantum (SMP) */
 #define PF_DTRACE	0x00200000	/* delayed trace (used on m68k, i386) */
@@ -356,7 +355,7 @@
 /* utime */	{0,0,0,0},0, \
 /* per CPU times */ {0, }, {0, }, \
 /* flt */	0,0,0,0,0,0, \
-/* swp */	0,0,0,0,0,0, \
+/* swp */	0,0,0, \
 /* process credentials */					\
 /* uid etc */	0,0,0,0,0,0,0,0,				\
 /* suppl grps*/ 0, {0,},					\
diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.2.0-pre6/linux/include/linux/swap.h	Thu Jan  7 15:11:40 1999
+++ linux/include/linux/swap.h	Mon Jan 11 10:35:07 1999
@@ -61,15 +61,6 @@
 extern unsigned long page_cache_size;
 extern int buffermem;
 
-struct swap_stats 
-{
-	long	proc_freepage_attempts;
-	long	proc_freepage_successes;
-	long	kswap_freepage_attempts;
-	long	kswap_freepage_successes;
-};
-extern struct swap_stats swap_stats;
-
 /* Incomplete types for prototype declarations: */
 struct task_struct;
 struct vm_area_struct;
@@ -82,7 +73,7 @@
 extern void swap_setup (void);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_pages(unsigned int gfp_mask, int count);
+extern int try_to_free_pages(unsigned int gfp_mask);
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, unsigned long, char *, int);
@@ -139,9 +130,7 @@
 
 #ifdef SWAP_CACHE_INFO
 extern unsigned long swap_cache_add_total;
-extern unsigned long swap_cache_add_success;
 extern unsigned long swap_cache_del_total;
-extern unsigned long swap_cache_del_success;
 extern unsigned long swap_cache_find_total;
 extern unsigned long swap_cache_find_success;
 #endif
diff -u --recursive --new-file v2.2.0-pre6/linux/include/linux/swapctl.h linux/include/linux/swapctl.h
--- v2.2.0-pre6/linux/include/linux/swapctl.h	Mon Jan  4 15:08:18 1999
+++ linux/include/linux/swapctl.h	Mon Jan 11 10:35:08 1999
@@ -4,41 +4,6 @@
 #include <asm/page.h>
 #include <linux/fs.h>
 
-/* Swap tuning control */
-
-typedef struct swap_control_v6
-{
-	unsigned int	sc_max_page_age;
-	unsigned int	sc_page_advance;
-	unsigned int	sc_page_decline;
-	unsigned int	sc_page_initial_age;
-	unsigned int	sc_age_cluster_fract;
-	unsigned int	sc_age_cluster_min;
-	unsigned int	sc_pageout_weight;
-	unsigned int	sc_bufferout_weight;
-} swap_control_v6;
-typedef struct swap_control_v6 swap_control_t;
-extern swap_control_t swap_control;
-
-typedef struct swapstat_v1
-{
-	unsigned long	wakeups;
-	unsigned long	pages_reclaimed;
-	unsigned long	pages_shm;
-	unsigned long	pages_mmap;
-	unsigned long	pages_swap;
-
-	unsigned long	gfp_freepage_attempts;
-	unsigned long	gfp_freepage_successes;
-	unsigned long	gfp_shrink_attempts;
-	unsigned long	gfp_shrink_successes;
-	unsigned long	kswap_freepage_attempts;
-	unsigned long	kswap_freepage_successes;
-	unsigned long	kswap_wakeups[4];
-} swapstat_v1;
-typedef swapstat_v1 swapstat_t;
-extern swapstat_t swapstats;
-
 typedef struct buffer_mem_v1
 {
 	unsigned int	min_percent;
@@ -66,30 +31,5 @@
 } pager_daemon_v1;
 typedef pager_daemon_v1 pager_daemon_t;
 extern pager_daemon_t pager_daemon;
-
-#define SC_VERSION	1
-#define SC_MAX_VERSION	1
-
-#ifdef __KERNEL__
-
-/* Define the maximum (least urgent) priority for the page reclaim code */
-#define RCL_MAXPRI 6
-/* We use an extra priority in the swap accounting code to represent
-   failure to free a resource at any priority */
-#define RCL_FAILURE (RCL_MAXPRI + 1)
-
-#define AGE_CLUSTER_FRACT	(swap_control.sc_age_cluster_fract)
-#define AGE_CLUSTER_MIN		(swap_control.sc_age_cluster_min)
-#define PAGEOUT_WEIGHT		(swap_control.sc_pageout_weight)
-#define BUFFEROUT_WEIGHT	(swap_control.sc_bufferout_weight)
-
-/* Page aging (see mm/swap.c) */
-
-#define MAX_PAGE_AGE		(swap_control.sc_max_page_age)
-#define PAGE_ADVANCE		(swap_control.sc_page_advance)
-#define PAGE_DECLINE		(swap_control.sc_page_decline)
-#define PAGE_INITIAL_AGE	(swap_control.sc_page_initial_age)
-
-#endif /* __KERNEL */
 
 #endif /* _LINUX_SWAPCTL_H */
diff -u --recursive --new-file v2.2.0-pre6/linux/ipc/sem.c linux/ipc/sem.c
--- v2.2.0-pre6/linux/ipc/sem.c	Mon Dec 28 15:00:53 1998
+++ linux/ipc/sem.c	Sat Jan  9 19:16:44 1999
@@ -696,7 +696,7 @@
                 /*
                  * If queue.status == 1 we where woken up and
                  * have to retry else we simply return.
-                 * If an interrupt occured we have to clean up the
+                 * If an interrupt occurred we have to clean up the
                  * queue
                  *
                  */
diff -u --recursive --new-file v2.2.0-pre6/linux/kernel/fork.c linux/kernel/fork.c
--- v2.2.0-pre6/linux/kernel/fork.c	Fri Jan  8 22:36:25 1999
+++ linux/kernel/fork.c	Sun Jan 10 13:23:35 1999
@@ -284,7 +284,10 @@
 void mmput(struct mm_struct *mm)
 {
 	/* notify parent sleeping on vfork() */
-	wake_up(&current->p_opptr->vfork_sleep);
+	if (current->flags & PF_VFORK) {
+		current->flags &= ~PF_VFORK;
+		up(current->p_opptr->vfork_sem);
+	}
 
 	if (atomic_dec_and_test(&mm->count)) {
 		release_segments(mm);
@@ -456,10 +459,12 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU);
+	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK);
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		new_flags &= ~(PF_PTRACED|PF_TRACESYS);
+	if (clone_flags & CLONE_VFORK)
+		new_flags |= PF_VFORK;
 	p->flags = new_flags;
 }
 
@@ -524,7 +529,7 @@
 	p->p_pptr = p->p_opptr = current;
 	p->p_cptr = NULL;
 	init_waitqueue(&p->wait_chldexit);
-	init_waitqueue(&p->vfork_sleep);
+	p->vfork_sem = NULL;
 
 	p->sigpending = 0;
 	sigemptyset(&p->signal);
@@ -571,7 +576,6 @@
 
 	/* ok, now we should be set up.. */
 	p->swappable = 1;
-	p->trashing_memory = 0;
 	p->exit_signal = clone_flags & CSIGNAL;
 	p->pdeath_signal = 0;
 
diff -u --recursive --new-file v2.2.0-pre6/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.2.0-pre6/linux/kernel/sysctl.c	Thu Jan  7 15:11:41 1999
+++ linux/kernel/sysctl.c	Fri Jan  8 22:54:16 1999
@@ -216,8 +216,6 @@
 };
 
 static ctl_table vm_table[] = {
-	{VM_SWAPCTL, "swapctl", 
-	 &swap_control, sizeof(swap_control_t), 0644, NULL, &proc_dointvec},
 	{VM_FREEPG, "freepages", 
 	 &freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec},
 	{VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL,
diff -u --recursive --new-file v2.2.0-pre6/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.0-pre6/linux/mm/page_alloc.c	Fri Jan  8 22:36:25 1999
+++ linux/mm/page_alloc.c	Tue Jan 12 14:32:44 1999
@@ -90,33 +90,6 @@
  */
 spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;
 
-/*
- * This routine is used by the kernel swap daemon to determine
- * whether we have "enough" free pages. It is fairly arbitrary,
- * having a low-water and high-water mark.
- *
- * This returns:
- *  0 - urgent need for memory
- *  1 - need some memory, but do it slowly in the background
- *  2 - no need to even think about it.
- */
-int free_memory_available(void)
-{
-	static int available = 1;
-
-	if (nr_free_pages < freepages.low) {
-		available = 0;
-		return 0;
-	}
-
-	if (nr_free_pages > freepages.high) {
-		available = 1;
-		return 2;
-	}
-
-	return available;
-}
-
 static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
 {
 	struct free_area_struct *area = free_area + order;
@@ -155,11 +128,6 @@
 		free_pages_ok(page->map_nr, 0);
 		return;
 	}
-#if 0
-	if (PageSwapCache(page) && atomic_read(&page->count) == 1)
-		printk(KERN_WARNING "VM: Releasing swap cache page at %p",
-			__builtin_return_address(0));
-#endif
 }
 
 void free_pages(unsigned long addr, unsigned long order)
@@ -177,12 +145,6 @@
 			free_pages_ok(map_nr, order);
 			return;
 		}
-#if 0
-		if (PageSwapCache(map) && atomic_read(&map->count) == 1)
-			printk(KERN_WARNING 
-				"VM: Releasing swap cache pages at %p",
-				__builtin_return_address(0));
-#endif
 	}
 }
 
@@ -249,38 +211,24 @@
 		 * do our best to just allocate things without
 		 * further thought.
 		 */
-		if (current->flags & PF_MEMALLOC)
-			goto ok_to_allocate;
+		if (!(current->flags & PF_MEMALLOC)) {
+			static int trashing = 0;
+			int freed;
 
-		/*
-		 * Avoid going back-and-forth between allocating
-		 * memory and trying to free it. If we get into
-		 * a bad memory situation, we're better off trying
-		 * to free things up until things are better.
-		 *
-		 * Most notably, this puts most of the onus of
-		 * freeing up memory on the processes that _use_
-		 * the most memory, rather than on everybody.
-		 */
-		if (nr_free_pages > freepages.min) {
-			if (!current->trashing_memory)
-				goto ok_to_allocate;
-			if (nr_free_pages > freepages.low) {
-				current->trashing_memory = 0;
-				goto ok_to_allocate;
+			if (nr_free_pages > freepages.min) {
+				if (!trashing)
+					goto ok_to_allocate;
+				if (nr_free_pages > freepages.low) {
+					trashing = 0;
+					goto ok_to_allocate;
+				}
 			}
-		}
-		/*
-		 * Low priority (user) allocations must not
-		 * succeed if we are having trouble allocating
-		 * memory.
-		 */
-		current->trashing_memory = 1;
-		{
-			int freed;
+
+			trashing = 1;
 			current->flags |= PF_MEMALLOC;
-			freed = try_to_free_pages(gfp_mask, freepages.high - nr_free_pages);
+			freed = try_to_free_pages(gfp_mask);
 			current->flags &= ~PF_MEMALLOC;
+
 			if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
 				goto nopage;
 		}
@@ -406,21 +354,29 @@
 	struct swap_info_struct *swapdev = SWP_TYPE(entry) + swap_info;
 	
 	offset = (offset >> page_cluster) << page_cluster;
-	
-	for (i = 1 << page_cluster; i > 0; i--) {
-	      if (offset >= swapdev->max
-			      || nr_free_pages - atomic_read(&nr_async_pages) <
-			      (freepages.high + freepages.low)/2)
-		      return;
-	      if (!swapdev->swap_map[offset] ||
-		  swapdev->swap_map[offset] == SWAP_MAP_BAD ||
-		  test_bit(offset, swapdev->swap_lockmap))
-		      continue;
-	      new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset), 0);
-	      if (new_page != NULL)
-		      __free_page(new_page);
-	      offset++;
-	}
+
+	i = 1 << page_cluster;
+	do {
+		/* Don't read-ahead past the end of the swap area */
+		if (offset >= swapdev->max)
+			break;
+		/* Don't block on I/O for read-ahead */
+		if (atomic_read(&nr_async_pages) >= pager_daemon.swap_cluster)
+			break;
+		/* Don't read in bad or busy pages */
+		if (!swapdev->swap_map[offset])
+			break;
+		if (swapdev->swap_map[offset] == SWAP_MAP_BAD)
+			break;
+		if (test_bit(offset, swapdev->swap_lockmap))
+			break;
+
+		/* Ok, do the async read-ahead now */
+		new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset), 0);
+		if (new_page != NULL)
+			__free_page(new_page);
+		offset++;
+	} while (--i);
 	return;
 }
 
diff -u --recursive --new-file v2.2.0-pre6/linux/mm/swap.c linux/mm/swap.c
--- v2.2.0-pre6/linux/mm/swap.c	Fri Jan  1 12:58:21 1999
+++ linux/mm/swap.c	Fri Jan  8 22:54:16 1999
@@ -46,23 +46,6 @@
    out, so that we don't try to swap TOO many pages out at once */
 atomic_t nr_async_pages = ATOMIC_INIT(0);
 
-/*
- * Constants for the page aging mechanism: the maximum age (actually,
- * the maximum "youthfulness"); the quanta by which pages rejuvenate
- * and age; and the initial age for new pages. 
- *
- * The "pageout_weight" is strictly a fixedpoint number with the
- * ten low bits being the fraction (ie 8192 really means "8.0").
- */
-swap_control_t swap_control = {
-	20, 3, 1, 3,		/* Page aging */
-	32, 4,			/* Aging cluster */
-	8192,			/* sc_pageout_weight aka PAGEOUT_WEIGHT */
-	8192,			/* sc_bufferout_weight aka BUFFEROUT_WEIGHT */
-};
-
-swapstat_t swapstats = {0};
-
 buffer_mem_t buffer_mem = {
 	2,	/* minimum percent buffer */
 	10,	/* borrow percent buffer */
@@ -80,7 +63,6 @@
 	SWAP_CLUSTER_MAX,	/* minimum number of tries */
 	SWAP_CLUSTER_MAX,	/* do swap I/O in clusters of this size */
 };
-
 
 /*
  * Perform any setup for the swap system
diff -u --recursive --new-file v2.2.0-pre6/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.2.0-pre6/linux/mm/swap_state.c	Fri Jan  1 12:58:21 1999
+++ linux/mm/swap_state.c	Wed Jan 13 09:54:50 1999
@@ -29,18 +29,16 @@
 
 #ifdef SWAP_CACHE_INFO
 unsigned long swap_cache_add_total = 0;
-unsigned long swap_cache_add_success = 0;
 unsigned long swap_cache_del_total = 0;
-unsigned long swap_cache_del_success = 0;
 unsigned long swap_cache_find_total = 0;
 unsigned long swap_cache_find_success = 0;
 
 void show_swap_cache_info(void)
 {
-	printk("Swap cache: add %ld/%ld, delete %ld/%ld, find %ld/%ld\n",
-		swap_cache_add_total, swap_cache_add_success, 
-		swap_cache_del_total, swap_cache_del_success,
-		swap_cache_find_total, swap_cache_find_success);
+	printk("Swap cache: add %ld, delete %ld, find %ld/%ld\n",
+		swap_cache_add_total, 
+		swap_cache_del_total,
+		swap_cache_find_success, swap_cache_find_total);
 }
 #endif
 
@@ -69,9 +67,6 @@
 	page->offset = entry;
 	add_page_to_hash_queue(page, &swapper_inode, entry);
 	add_page_to_inode_queue(&swapper_inode, page);
-#ifdef SWAP_CACHE_INFO
-	swap_cache_add_success++;
-#endif
 	return 1;
 }
 
@@ -192,16 +187,6 @@
 		printk ("VM: Removing swap cache page with wrong inode hash "
 			"on page %08lx\n", page_address(page));
 	}
-#if 0
-	/*
-	 * This is a legal case, but warn about it.
-	 */
-	if (atomic_read(&page->count) == 1) {
-		printk (KERN_WARNING 
-			"VM: Removing page cache on unshared page %08lx\n", 
-			page_address(page));
-	}
-#endif
 
 #ifdef DEBUG_SWAP
 	printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n",
@@ -222,7 +207,6 @@
 
 #ifdef SWAP_CACHE_INFO
 	swap_cache_del_total++;
-	swap_cache_del_success++;
 #endif
 #ifdef DEBUG_SWAP
 	printk("DebugVM: delete_from_swap_cache(%08lx count %d, "
@@ -262,15 +246,22 @@
 struct page * lookup_swap_cache(unsigned long entry)
 {
 	struct page *found;
-	
+
+#ifdef SWAP_CACHE_INFO
+	swap_cache_find_total++;
+#endif
 	while (1) {
 		found = find_page(&swapper_inode, entry);
 		if (!found)
 			return 0;
 		if (found->inode != &swapper_inode || !PageSwapCache(found))
 			goto out_bad;
-		if (!PageLocked(found))
+		if (!PageLocked(found)) {
+#ifdef SWAP_CACHE_INFO
+			swap_cache_find_success++;
+#endif
 			return found;
+		}
 		__free_page(found);
 		__wait_on_page(found);
 	}
@@ -292,7 +283,7 @@
 
 struct page * read_swap_cache_async(unsigned long entry, int wait)
 {
-	struct page *found_page, *new_page;
+	struct page *found_page = 0, *new_page;
 	unsigned long new_page_addr;
 	
 #ifdef DEBUG_SWAP
@@ -300,15 +291,20 @@
 	       entry, wait ? ", wait" : "");
 #endif
 	/*
+	 * Make sure the swap entry is still in use.
+	 */
+	if (!swap_duplicate(entry))	/* Account for the swap cache */
+		goto out;
+	/*
 	 * Look for the page in the swap cache.
 	 */
 	found_page = lookup_swap_cache(entry);
 	if (found_page)
-		goto out;
+		goto out_free_swap;
 
 	new_page_addr = __get_free_page(GFP_USER);
 	if (!new_page_addr)
-		goto out;	/* Out of memory */
+		goto out_free_swap;	/* Out of memory */
 	new_page = mem_map + MAP_NR(new_page_addr);
 
 	/*
@@ -317,11 +313,6 @@
 	found_page = lookup_swap_cache(entry);
 	if (found_page)
 		goto out_free_page;
-	/*
-	 * Make sure the swap entry is still in use.
-	 */
-	if (!swap_duplicate(entry))	/* Account for the swap cache */
-		goto out_free_page;
 	/* 
 	 * Add it to the swap cache and read its contents.
 	 */
@@ -339,6 +330,8 @@
 
 out_free_page:
 	__free_page(new_page);
+out_free_swap:
+	swap_free(entry);
 out:
 	return found_page;
 }
diff -u --recursive --new-file v2.2.0-pre6/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.2.0-pre6/linux/mm/swapfile.c	Fri Nov 27 13:09:31 1998
+++ linux/mm/swapfile.c	Fri Jan  8 23:48:41 1999
@@ -23,6 +23,7 @@
 
 struct swap_info_struct swap_info[MAX_SWAPFILES];
 
+#define SWAPFILE_CLUSTER 256
 
 static inline int scan_swap_map(struct swap_info_struct *si)
 {
@@ -30,7 +31,7 @@
 	/* 
 	 * We try to cluster swap pages by allocating them
 	 * sequentially in swap.  Once we've allocated
-	 * SWAP_CLUSTER_MAX pages this way, however, we resort to
+	 * SWAPFILE_CLUSTER pages this way, however, we resort to
 	 * first-free allocation, starting a new cluster.  This
 	 * prevents us from scattering swap pages all over the entire
 	 * swap partition, so that we reduce overall disk seek times
@@ -46,7 +47,7 @@
 			goto got_page;
 		}
 	}
-	si->cluster_nr = SWAP_CLUSTER_MAX;
+	si->cluster_nr = SWAPFILE_CLUSTER;
 	for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) {
 		if (si->swap_map[offset])
 			continue;
diff -u --recursive --new-file v2.2.0-pre6/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.2.0-pre6/linux/mm/vmscan.c	Fri Jan  8 22:36:25 1999
+++ linux/mm/vmscan.c	Sun Jan 10 13:20:11 1999
@@ -439,7 +439,7 @@
 		 * forever in a really bad memory squeeze.
 		 */
 		if (nr_free_pages < freepages.high)
-			try_to_free_pages(0, 16);
+			try_to_free_pages(GFP_KSWAPD);
 	}
 
 	return 0;
@@ -454,9 +454,10 @@
  * cluster them so that we get good swap-out behaviour. See
  * the "free_memory()" macro for details.
  */
-int try_to_free_pages(unsigned int gfp_mask, int count)
+int try_to_free_pages(unsigned int gfp_mask)
 {
 	int priority;
+	int count = SWAP_CLUSTER_MAX;
 
 	lock_kernel();
 
diff -u --recursive --new-file v2.2.0-pre6/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.2.0-pre6/linux/net/ipv4/Config.in	Thu Jan  7 15:11:41 1999
+++ linux/net/ipv4/Config.in	Sat Jan  9 10:01:56 1999
@@ -72,7 +72,7 @@
     bool 'IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD
   fi
 fi
-bool 'IP: TCP syncookie support (not enabled per default) ' CONFIG_SYN_COOKIES
+bool 'IP: TCP syncookie support (not enabled per default)' CONFIG_SYN_COOKIES
 comment '(it is safe to leave these untouched)'
 #bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP
 tristate 'IP: Reverse ARP' CONFIG_INET_RARP
diff -u --recursive --new-file v2.2.0-pre6/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.2.0-pre6/linux/net/ipv4/ip_fw.c	Fri Jan  8 22:36:25 1999
+++ linux/net/ipv4/ip_fw.c	Sun Jan 10 22:56:43 1999
@@ -63,7 +63,6 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/config.h>
 
 #include <linux/socket.h>
 #include <linux/sockios.h>
diff -u --recursive --new-file v2.2.0-pre6/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.2.0-pre6/linux/net/irda/irttp.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irttp.c	Sun Jan 10 22:56:43 1999
@@ -26,7 +26,6 @@
 #include <linux/config.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
-#include <linux/config.h>
 
 #include <asm/byteorder.h>
 
diff -u --recursive --new-file v2.2.0-pre6/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.2.0-pre6/linux/scripts/Menuconfig	Mon Dec 28 15:00:53 1998
+++ linux/scripts/Menuconfig	Sat Jan  9 19:16:44 1999
@@ -57,6 +57,14 @@
 # 13 Dec 1998, Riley H Williams (rhw@bigfoot.com)
 # When an error occurs, actually display the error message as well as
 # our comments thereon.
+#
+# 31 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
+# Fix mod_bool to honor $CONFIG_MODULES.
+# Fix dep_tristate to call define_bool when dependency is "n".
+#
+# 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+# Blow away lxdialog.scrltmp on entry to activate_menu.  This protects
+# against people who use commands like ' ' to select menus.
 
 
 #
@@ -177,17 +185,13 @@
 #       else in the kernel.
 #
 function dep_tristate () {
-	if [ "$CONFIG_MODULES" != "y" ]
-	then
-		bool "$1" "$2"
-	else
-		if  eval [ "_$3" != "_m" ]
-		then
-			tristate "$1" "$2" $3
-		else
-			mod_bool "$1" "$2"
-		fi
-	fi
+	if [ "$3" = "y" ]; then
+	    tristate "$1" "$2"
+	else if [ "$3" = "m" ]; then
+	    mod_bool "$1" "$2"
+	else 
+	    define_bool "$2" "$n"
+	fi; fi
 }
 
 #
@@ -372,16 +376,20 @@
 # Same as bool() except options are (Module/No)
 #
 function mod_bool () {
-	set_x_info "$2" "n"
-
-	case $x in
-	y|m) flag='M' ;;
-	*)   flag=' ' ;;
-	esac
-
-	echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
-
-	echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists
+	if [ "$CONFIG_MODULES" != "y" ]; then
+	    define_bool "$2" "n"
+	else
+	    set_x_info "$2" "n"
+ 
+	    case $x in
+	    y|m) flag='M' ;;
+	    *)   flag=' ' ;;
+	    esac
+ 
+	    echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
+ 
+	    echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists
+	fi
 }
 
 #
@@ -720,6 +728,7 @@
 # dialog commands or recursively call other menus.
 #
 function activate_menu () {
+	rm -f lxdialog.scrltmp
 	while true
 	do
 		comment_ctr=0		#So comment lines get unique tags
diff -u --recursive --new-file v2.2.0-pre6/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c
--- v2.2.0-pre6/linux/scripts/lxdialog/menubox.c	Thu Nov 12 16:21:25 1998
+++ linux/scripts/lxdialog/menubox.c	Sat Jan  9 19:16:44 1999
@@ -48,6 +48,12 @@
  *    *)  If for some reason the last scrolling position is not saved by
  *        lxdialog, it sets the scrolling so that the selected item is in the
  *        middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
  */
 
 #include "dialog.h"
@@ -227,6 +233,7 @@
 	    choice = choice - scroll;
 	    fclose(f);
 	} else {
+	    scroll=0;
 	    remove("lxdialog.scrltmp");
 	    fclose(f);
 	    f=NULL;
diff -u --recursive --new-file v2.2.0-pre6/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.2.0-pre6/linux/scripts/tkgen.c	Fri Jan  8 22:36:28 1999
+++ linux/scripts/tkgen.c	Sat Jan  9 19:16:44 1999
@@ -69,6 +69,11 @@
  *              0: they may have been set to 1 elsewhere. CONFIG_NETLINK is
  *              an example.
  *
+ * 1999 01 04
+ * Michael Elizabeth Chastain <mec@shout.net>
+ * - Call clear_globalflags when writing out update_mainmenu.
+ *   This fixes the missing global/vfix lines for ARCH=alpha on 2.2.0-pre4.
+ *
  * TO DO:
  *   - clean up - there are useless ifdef's everywhere.
  *   - better comments throughout - C code generating tcl is really cryptic.
@@ -358,7 +363,7 @@
 	}
       
       printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.m configure -state normal;",menu_num, line_num);
+      printf("global CONFIG_MODULES; if {($CONFIG_MODULES == 1)} then { .menu%d.config.f.x%d.m configure -state normal };",menu_num, line_num);
       printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
       /*
        * Or in a bit to the variable - this causes all of the radiobuttons
@@ -913,6 +918,7 @@
    * the top level menu, and this procedure will ensure that things are
    * correct.
    */
+  clear_globalflags(scfg);
   printf("proc update_mainmenu {w}  {\n");
   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
     {
